<?php
declare(strict_types=1);

/**
 * CLI Entry Point — Migrations, Seeds, and System Commands.
 *
 * Usage:
 *   php cli.php migrate            Run all pending migrations
 *   php cli.php migrate:rollback   Rollback last batch
 *   php cli.php migrate:status     Show migration status
 *   php cli.php seed               Run all pending seeds
 *   php cli.php seed:run <Name>    Run a specific seed
 *   php cli.php cron               Run background jobs
 */

// Prevent web access
if (PHP_SAPI !== 'cli') {
    die('CLI only.');
}

require_once __DIR__ . '/vendor/autoload.php';

// Load .env
$envFile = __DIR__ . '/.env';
if (file_exists($envFile)) {
    $lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($lines as $line) {
        $line = trim($line);
        if ($line === '' || $line[0] === '#') continue;
        if (str_contains($line, '=')) {
            [$key, $value] = explode('=', $line, 2);
            $key = trim($key);
            $value = trim($value);
            if (!isset($_ENV[$key])) {
                $_ENV[$key] = $value;
                putenv("{$key}={$value}");
            }
        }
    }
}

// Minimal bootstrap — just database, no session/routing
$config = [];
$configDir = __DIR__ . '/config';
if (is_dir($configDir)) {
    foreach (glob($configDir . '/*.php') as $configFile) {
        $key = basename($configFile, '.php');
        $config[$key] = require $configFile;
    }
}

// Build database config
$dbConfig = [
    'host'      => $_ENV['DB_HOST'] ?? $config['database']['host'] ?? '127.0.0.1',
    'port'      => $_ENV['DB_PORT'] ?? $config['database']['port'] ?? '3306',
    'name'      => $_ENV['DB_NAME'] ?? $config['database']['name'] ?? 'the_club_erp',
    'user'      => $_ENV['DB_USER'] ?? $config['database']['user'] ?? 'root',
    'pass'      => $_ENV['DB_PASS'] ?? $config['database']['pass'] ?? '',
    'charset'   => $config['database']['charset'] ?? 'utf8mb4',
    'collation' => $config['database']['collation'] ?? 'utf8mb4_unicode_ci',
];

$db = new \App\Core\Database(
    (string) $dbConfig['host'],
    (int) $dbConfig['port'],
    (string) $dbConfig['name'],
    (string) $dbConfig['user'],
    (string) $dbConfig['pass'],
    (string) $dbConfig['charset']
);

$command = $argv[1] ?? 'help';
$arg2 = $argv[2] ?? null;

echo "\n";

switch ($command) {
    case 'migrate':
        $runner = new \App\Core\Migration\MigrationRunner($db);
        $results = $runner->migrate();
        if (empty($results)) {
            echo "✅ Nothing to migrate. All migrations are up to date.\n";
        } else {
            echo "✅ Ran " . count($results) . " migration(s):\n";
            foreach ($results as $name) {
                echo "   ✔ {$name}\n";
            }
        }
        break;

    case 'migrate:rollback':
        $runner = new \App\Core\Migration\MigrationRunner($db);
        $results = $runner->rollback();
        if (empty($results)) {
            echo "⚠️  Nothing to rollback.\n";
        } else {
            echo "✅ Rolled back " . count($results) . " migration(s):\n";
            foreach ($results as $name) {
                echo "   ↩ {$name}\n";
            }
        }
        break;

    case 'migrate:status':
        $runner = new \App\Core\Migration\MigrationRunner($db);
        $status = $runner->status();
        echo str_pad('Migration', 60) . "Status\n";
        echo str_repeat('─', 70) . "\n";
        foreach ($status as $s) {
            $icon = $s['status'] === 'Ran' ? '✔' : '○';
            echo "{$icon} " . str_pad($s['migration'], 58) . $s['status'] . "\n";
        }
        break;

    case 'seed':
        echo "🌱 Running seeds...\n";
        $runner = new \App\Core\Seeder\SeederRunner($db);
        $results = $runner->run();
        if (empty($results)) {
            echo "✅ Nothing to seed. All seeds already executed.\n";
        } else {
            echo "✅ Ran " . count($results) . " seed(s):\n";
            foreach ($results as $name) {
                echo "   🌱 {$name}\n";
            }
        }
        break;

    case 'seed:run':
        if (!$arg2) {
            echo "❌ Please specify seed name: php cli.php seed:run SeedName\n";
            exit(1);
        }
        $runner = new \App\Core\Seeder\SeederRunner($db);
        $runner->runSingle($arg2);
        echo "✅ Seed executed: {$arg2}\n";
        break;

    case 'cron':
        echo "⏰ Running cron jobs...\n";
        $cronRunner = __DIR__ . '/cron/runner.php';
        if (file_exists($cronRunner)) {
            require $cronRunner;
        } else {
            echo "⚠️  No cron runner found.\n";
        }
        break;

    case 'subscriptions:migrate':
        $dryRun = in_array('--dry-run', $argv);
        echo "📋 Subscription Data Migration" . ($dryRun ? " (DRY RUN)" : "") . "\n";
        echo str_repeat('─', 50) . "\n";

        $app = \App\Core\App::getInstance();
        $app->setDb($db);
        $app->boot();

        $migration = new \App\Modules\Subscriptions\Services\SubscriptionDataMigration($db);
        $result = $migration->run($dryRun);

        echo "  Members processed:      {$result['members_processed']}\n";
        echo "  Subscriptions created:   {$result['subscriptions_created']}\n";
        echo "  Orphaned IDs fixed:      {$result['orphaned_ids_fixed']}\n";
        echo "  Duplicates removed:      {$result['duplicates_removed']}\n";
        echo "  Amount corrections:      {$result['amount_corrections']}\n";
        echo "  Fines applied:           {$result['fines_applied']}\n";
        if (!empty($result['errors'])) {
            echo "\n  ⚠️  Errors:\n";
            foreach ($result['errors'] as $err) {
                echo "    - {$err}\n";
            }
        }
        echo "\n✅ " . ($dryRun ? "Dry run complete. No changes made." : "Migration complete.") . "\n";
        break;

    case 'subscriptions:validate':
        echo "🔍 Subscription Data Validation\n";
        echo str_repeat('─', 50) . "\n";

        $app = \App\Core\App::getInstance();
        $app->setDb($db);
        $app->boot();

        $migration = new \App\Modules\Subscriptions\Services\SubscriptionDataMigration($db);
        $issues = $migration->validate();

        if (empty($issues)) {
            echo "  ✅ All subscription data is consistent.\n";
        } else {
            foreach ($issues as $issue) {
                echo "  ⚠️  [{$issue['type']}] — {$issue['count']} issue(s)\n";
            }
        }
        break;

    case 'routes':
        $app = \App\Core\App::getInstance();
        $app->boot();
        $routes = [];
        $modulesDir = __DIR__ . '/app/Modules';
        $routeFiles = glob($modulesDir . '/*/Routes.php');
        sort($routeFiles);
        foreach ($routeFiles as $file) {
            $moduleRoutes = require $file;
            if (is_array($moduleRoutes)) {
                foreach ($moduleRoutes as $r) {
                    if (is_array($r) && count($r) >= 3) {
                        $routes[] = $r;
                    }
                }
            }
        }
        echo str_pad('METHOD', 8) . str_pad('PATH', 50) . str_pad('HANDLER', 55) . str_pad('MIDDLEWARE', 20) . "PERMISSION\n";
        echo str_repeat('─', 145) . "\n";
        foreach ($routes as $r) {
            $mw = implode(',', $r[3] ?? []);
            echo str_pad($r[0], 8) . str_pad($r[1], 50) . str_pad($r[2], 55) . str_pad($mw, 20) . ($r[4] ?? '') . "\n";
        }
        echo "\nTotal: " . count($routes) . " routes\n";
        break;

    case 'permissions:orphans':
        require_once __DIR__ . '/app/Core/Registries/PermissionRegistry.php';
        $app = \App\Core\App::getInstance();
        $app->boot();
        $orphans = \App\Modules\AccessMatrix\Services\PermissionDiscoveryService::findOrphanPermissions();
        echo "ORPHAN PERMISSIONS (registered but not used in any route):\n";
        echo str_repeat('─', 60) . "\n";
        if (empty($orphans)) {
            echo "  ✅ No orphan permissions found.\n";
        } else {
            foreach ($orphans as $o) {
                echo "  ⚠️  {$o}\n";
            }
            echo "\nTotal: " . count($orphans) . " orphan permissions\n";
        }
        break;

    case 'permissions:unprotected':
        $app = \App\Core\App::getInstance();
        $app->boot();
        $unprotected = \App\Modules\AccessMatrix\Services\PermissionDiscoveryService::findUnprotectedRoutes();
        echo "UNPROTECTED ROUTES (no permission defined):\n";
        echo str_repeat('─', 80) . "\n";
        if (empty($unprotected)) {
            echo "  ✅ All routes have permissions.\n";
        } else {
            echo str_pad('MODULE', 20) . str_pad('METHOD', 8) . "PATH\n";
            echo str_repeat('─', 80) . "\n";
            foreach ($unprotected as $u) {
                echo str_pad($u['file'], 20) . str_pad($u['method'], 8) . $u['path'] . "\n";
            }
            echo "\nTotal: " . count($unprotected) . " unprotected routes\n";
        }
        break;

    case 'permissions:stats':
        $app = \App\Core\App::getInstance();
        $app->boot();
        $stats = \App\Modules\AccessMatrix\Services\PermissionDiscoveryService::getPermissionStats();
        echo "PERMISSION STATISTICS:\n";
        echo str_repeat('─', 50) . "\n";
        echo "  Total permissions: {$stats['total']}\n";
        echo "  Total groups: {$stats['groups']}\n";
        echo str_repeat('─', 50) . "\n";
        echo str_pad('GROUP', 30) . "COUNT\n";
        echo str_repeat('─', 50) . "\n";
        foreach ($stats['by_group'] as $group => $count) {
            echo str_pad($group, 30) . $count . "\n";
        }
        break;

    case 'export:book':
        echo "📖 Generating Book of the ERP PDF...\n";
        $storageDir = __DIR__ . '/storage/cache';
        $lockFile = $storageDir . '/book-export.lock';
        $pdfFile = $storageDir . '/book-export.pdf';
        $errorFile = $storageDir . '/book-export.error';

        @unlink($errorFile);
        file_put_contents($lockFile, 'processing');

        try {
            $screenshotsPath = realpath(__DIR__ . '/public/assets/tutorials/screenshots');
            $viewsPath = realpath(__DIR__ . '/app/Modules/Tutorials/Views');

            $app = \App\Core\App::getInstance();
            $app->setDb($db);

            $controller = new \App\Modules\Tutorials\Controllers\TutorialController();
            $bookData = $controller->collectBookData($screenshotsPath, $viewsPath);

            ob_start();
            $data = $bookData;
            include __DIR__ . '/app/Modules/Tutorials/Views/export_pdf.php';
            $html = ob_get_clean();

            echo "   HTML generated (" . strlen($html) . " bytes)\n";
            echo "   Running wkhtmltopdf...\n";

            $wkhtmltopdf = null;
            foreach (['/usr/local/bin/wkhtmltopdf', '/usr/bin/wkhtmltopdf'] as $path) {
                if (file_exists($path) && is_executable($path)) {
                    $wkhtmltopdf = $path;
                    break;
                }
            }
            if (!$wkhtmltopdf) {
                $wkhtmltopdf = trim((string) shell_exec('which wkhtmltopdf 2>/dev/null'));
            }

            if (!$wkhtmltopdf) {
                file_put_contents($pdfFile, $html);
                echo "   ⚠️  wkhtmltopdf not found, saved as HTML\n";
            } else {
                $tmpInput = tempnam(sys_get_temp_dir(), 'pdf_in_') . '.html';
                file_put_contents($tmpInput, $html);

                $cmd = escapeshellarg($wkhtmltopdf)
                    . ' --encoding utf-8 --page-size A4'
                    . ' --margin-top 15 --margin-bottom 15 --margin-left 12 --margin-right 12'
                    . ' --enable-local-file-access'
                    . ' --no-stop-slow-scripts'
                    . ' --javascript-delay 200'
                    . ' --image-quality 85'
                    . ' --print-media-type'
                    . ' ' . escapeshellarg($tmpInput)
                    . ' ' . escapeshellarg($pdfFile)
                    . ' 2>&1';

                $output = [];
                exec($cmd, $output, $returnCode);
                @unlink($tmpInput);

                if (($returnCode === 0 || $returnCode === 1) && file_exists($pdfFile) && filesize($pdfFile) > 0) {
                    echo "   ✅ PDF generated: " . round(filesize($pdfFile) / 1024 / 1024, 2) . " MB\n";
                } else {
                    $errMsg = implode("\n", $output);
                    file_put_contents($errorFile, $errMsg ?: "wkhtmltopdf failed (code: {$returnCode})");
                    @unlink($pdfFile);
                    echo "   ❌ wkhtmltopdf failed: {$errMsg}\n";
                }
            }
        } catch (\Throwable $e) {
            file_put_contents($errorFile, $e->getMessage());
            echo "   ❌ Error: " . $e->getMessage() . "\n";
        }
        @unlink($lockFile);
        break;

    case 'help':
    default:
        echo "THE CLUB ERP — CLI Commands\n";
        echo "───────────────────────────────────\n";
        echo "  php cli.php migrate               Run pending migrations\n";
        echo "  php cli.php migrate:rollback      Rollback last batch\n";
        echo "  php cli.php migrate:status        Show migration status\n";
        echo "  php cli.php seed                  Run all pending seeds\n";
        echo "  php cli.php seed:run <Name>       Run specific seed\n";
        echo "  php cli.php cron                  Run background jobs\n";
        echo "  php cli.php subscriptions:migrate Run subscription data migration\n";
        echo "  php cli.php subscriptions:migrate --dry-run  Preview without changes\n";
        echo "  php cli.php subscriptions:validate           Validate subscription data integrity\n";
        echo "  php cli.php routes                List all routes\n";
        echo "  php cli.php export:book           Generate Book of the ERP PDF\n";
        echo "  php cli.php permissions:orphans   Registered but unused permissions\n";
        echo "  php cli.php permissions:unprotected  Routes without permissions\n";
        echo "  php cli.php permissions:stats     Permission count per module\n";
        echo "  php cli.php help                  Show this help\n";
        break;
}

echo "\n";