<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Services\Install\LockGuard;
use Illuminate\Console\Command;

/**
 *   php artisan wdot:upgrade
 *   php artisan wdot:upgrade --no-backup
 *   php artisan wdot:upgrade --skip-composer
 *
 * 그누보드 g7 의 `core:update` 패리티 (GAP-10).
 *
 * 절차:
 *   1) install.lock 검증
 *   2) 백업 (DB sqldump + storage/app/public tarball)
 *   3) composer install --no-dev (선택)
 *   4) migrate --force
 *   5) optimize:clear + optimize
 *   6) 변경된 마이그레이션 / 시드 출력
 *
 * @see /_qa-audit/INSTALLER_GAP_VS_GNUBOARD.md GAP-10/12
 */
final class WdotUpgradeCommand extends Command
{
    protected $signature = 'wdot:upgrade
        {--no-backup : 백업 단계 스킵}
        {--skip-composer : composer install 단계 스킵}
        {--dry-run : 실제 실행 없이 어떤 단계가 돌지만 표시}';

    protected $description = 'W·Dot CMS 마이너/패치 업그레이드 — 백업 + migrate + optimize (GAP-10)';

    public function handle(LockGuard $lock): int
    {
        $this->line('');
        $this->line('  <bg=cyan;fg=white> W·Dot CMS Upgrade </>');
        $this->line('');

        if (! $lock->verify()) {
            $this->error('install.lock 이 없거나 위조되었습니다. wdot:install / wdot:rotate-install-key 를 먼저 실행하세요.');

            return self::FAILURE;
        }

        $steps = [
            'backup'   => '백업 (mysqldump + storage tarball)',
            'composer' => 'composer install --no-dev --optimize-autoloader',
            'migrate'  => 'php artisan migrate --force',
            'optimize' => 'php artisan optimize',
        ];
        if ($this->option('no-backup')) {
            unset($steps['backup']);
        }
        if ($this->option('skip-composer')) {
            unset($steps['composer']);
        }

        if ($this->option('dry-run')) {
            $this->info('--dry-run: 다음 단계가 실행됩니다');
            foreach ($steps as $key => $desc) {
                $this->line(sprintf('  %d) %-10s %s', array_search($key, array_keys($steps), true) + 1, $key, $desc));
            }

            return self::SUCCESS;
        }

        $startedAt = now();

        // 1) Backup
        if (isset($steps['backup'])) {
            $backupDir = storage_path('backups/upgrade-'.$startedAt->format('Ymd-Hi'));
            @mkdir($backupDir, 0700, true);

            $db = (string) config('database.connections.mysql.database');
            $host = (string) config('database.connections.mysql.host');
            $user = (string) config('database.connections.mysql.username');
            $pass = (string) config('database.connections.mysql.password');

            $sqlFile = $backupDir.'/db-'.$db.'.sql.gz';
            $cmd = sprintf(
                'mysqldump -h %s -u %s %s %s 2>/dev/null | gzip > %s',
                escapeshellarg($host),
                escapeshellarg($user),
                $pass ? '-p'.escapeshellarg($pass) : '',
                escapeshellarg($db),
                escapeshellarg($sqlFile),
            );
            @shell_exec($cmd);
            if (is_file($sqlFile) && filesize($sqlFile) > 0) {
                $this->info('  ✓ DB 백업: '.$sqlFile);
            } else {
                $this->warn('  ⚠ mysqldump 결과 비어있음 — 계속 진행');
            }

            // storage/app
            if (is_dir(storage_path('app'))) {
                $tarFile = $backupDir.'/storage-app.tar.gz';
                @shell_exec('tar czf '.escapeshellarg($tarFile).' -C '.escapeshellarg(storage_path()).' app 2>&1');
                if (is_file($tarFile)) {
                    $this->info('  ✓ storage/app 백업: '.$tarFile);
                }
            }

            // composer.lock + .env 보관
            foreach (['composer.lock', '.env'] as $f) {
                $src = base_path($f);
                if (is_file($src)) {
                    @copy($src, $backupDir.'/'.basename($f));
                }
            }
            $this->info('  ✓ 백업 위치: '.$backupDir);
        }

        // 2) Composer
        if (isset($steps['composer'])) {
            $this->info('▶ composer install --no-dev --optimize-autoloader');
            $composer = trim((string) @shell_exec('which composer 2>/dev/null'));
            if ($composer === '') {
                $this->warn('  ⚠ composer 명령을 찾을 수 없음 — 스킵');
            } else {
                $out = @shell_exec($composer.' install --no-dev --optimize-autoloader --working-dir='.escapeshellarg(base_path()).' 2>&1');
                $this->line('  '.trim((string) $out));
            }
        }

        // 3) Migrate
        $this->info('▶ php artisan migrate --force');
        $exit = $this->call('migrate', ['--force' => true]);
        if ($exit !== 0) {
            $this->error('migrate 실패. 백업에서 복구하세요.');

            return self::FAILURE;
        }

        // 4) Optimize
        $this->info('▶ optimize:clear + optimize');
        $this->call('optimize:clear');
        $this->call('optimize');

        // 변경 이력 — 최근 5 개 마이그레이션
        $this->newLine();
        $this->line('  최근 마이그레이션 5건:');
        $this->call('migrate:status', ['--quiet' => false]);

        $this->newLine();
        $this->line('  <bg=green;fg=white> ✅ 업그레이드 완료 </>');
        $this->line('  소요 시간       : '.$startedAt->diffInSeconds(now()).'s');
        $this->line('  install.lock    : 유효 (HMAC 검증 통과)');

        return self::SUCCESS;
    }
}
