#!/usr/bin/env php
<?php

declare(strict_types=1);

// CLI 的 stdout 只放命令结果（含 --json），告警与弃用提示统一走 stderr。
ini_set('display_errors', 'stderr');

use KingCMS\Auth\AdminAccounts;
use KingCMS\Auth\AdminPasswordReset;
use KingCMS\Auth\SessionStore;
use KingCMS\Console\CronCommand;
use KingCMS\Console\ResetPasswordCommand;
use KingCMS\Database\Connection;
use KingCMS\Database\Migrator;

$autoload = __DIR__ . '/../vendor/autoload.php';
if (is_file($autoload)) {
    require $autoload;
} else {
    spl_autoload_register(static function (string $class): void {
        $prefix = 'KingCMS\\';
        if (strncmp($class, $prefix, strlen($prefix)) !== 0) {
            return;
        }

        $relative = substr($class, strlen($prefix));
        $file = __DIR__ . '/../app/' . str_replace('\\', '/', $relative) . '.php';
        if (is_file($file)) {
            require $file;
        }
    });
}

$command = $argv[1] ?? '';

if ($command === 'local:export' || $command === 'local:upgrade' || $command === 'local:check-update') {
    $dataDir = getenv('KINGCMS_DATA_DIR');
    if (!is_string($dataDir) || trim($dataDir) === '') {
        $dataDir = __DIR__ . '/../data';
    }
    $dataDir = rtrim(trim($dataDir), '/');

    exit(\KingCMS\Console\LocalPackageCommand::run(
        $command,
        array_slice($argv, 2),
        dirname(__DIR__),
        $dataDir,
        dirname(__DIR__) . '/modules'
    ));
}

if ($command === 'local:list' || $command === 'local:check') {
    // 私有扩展巡检：只读，不构造 App（不建库、不跑迁移）。KINGCMS_LOCAL_DIR 由
    // LocalExtensions 解析，KINGCMS_DATA_DIR 与 bin/mcp 使用同一约定。
    $dataDir = getenv('KINGCMS_DATA_DIR');
    if (!is_string($dataDir) || trim($dataDir) === '') {
        $dataDir = __DIR__ . '/../data';
    }
    $dataDir = rtrim(trim($dataDir), '/');

    exit(\KingCMS\Console\LocalSiteCommand::run(
        $command,
        array_slice($argv, 2),
        $dataDir,
        dirname(__DIR__) . '/modules'
    ));
}

if ($command === 'cron:run') {
    $dataDir = __DIR__ . '/../data';
    $pdo = Connection::get($dataDir . '/kingcms.sqlite');
    (new Migrator($pdo, __DIR__ . '/../app/Database/migrations'))->run();

    exit((new CronCommand($pdo, $dataDir, __DIR__ . '/../modules'))->run());
}

if ($command === 'langpack:run') {
    \KingCMS\I18n\AiChatClient::$background = true;
    $app = new \KingCMS\App(__DIR__ . '/../data');
    $processed = (new \KingCMS\I18n\LangPackJobs($app->pdo(), $app->dataDir()))
        ->runAll($app->settings(), $app->registry());
    fwrite(STDOUT, $processed < 0 ? "已有语言包进程在运行\n" : sprintf("处理语言包任务 %d 个\n", $processed));
    exit(0);
}

if ($command === 'article:batch-run') {
    \KingCMS\I18n\AiChatClient::$background = true;
    $app = new \KingCMS\App(__DIR__ . '/../data');
    $processed = (new \KingCMS\Modules\Article\ArticleBatchService(
        $app->pdo(),
        $app->settings(),
        $app->registry()
    ))->runQueued();
    fwrite(STDOUT, sprintf("处理批量文章任务 %d 个\n", $processed));
    exit(0);
}

if ($command === 'pulo:import') {
    // 默认 dry-run（库不存在时连库都不建），--commit 才写库。
    exit(\KingCMS\Import\Pulo\PuloImportCommand::run(
        array_slice($argv, 2),
        __DIR__ . '/../data',
        __DIR__ . '/../modules'
    ));
}

if ($command === 'product:batch-run') {
    $app = new \KingCMS\App(__DIR__ . '/../data');
    $processed = (new \KingCMS\Modules\Shop\Import\ProductBatchService(
        $app->pdo(),
        $app->settings(),
        $app->registry(),
        $app->dataDir()
    ))->runQueued();
    fwrite(STDOUT, sprintf("处理批量商品任务 %d 个\n", $processed));
    exit(0);
}

if ($command === 'upgrade:run') {
    $app = new \KingCMS\App(__DIR__ . '/../data');
    $processed = \KingCMS\Upgrade\UpgradeRunner::forSite($app->pdo(), $app->dataDir())->runAll();
    fwrite(STDOUT, $processed < 0 ? "已有升级进程在运行\n" : sprintf("处理升级任务 %d 个\n", $processed));
    exit(0);
}

if ($command === 'semantic:run' || $command === 'semantic:backfill' || $command === 'semantic:status') {
    $app = new \KingCMS\App(__DIR__ . '/../data');
    $search = \KingCMS\Search\SemanticSearch::fromSettings($app->pdo(), $app->settings());
    if ($command === 'semantic:status') {
        $status = $search->status();
        $modes = ['vector' => '向量', 'rewrite' => '查询改写', 'off' => '未开启'];
        fwrite(STDOUT, sprintf("方式：%s%s  内容：%d  已建向量：%d  排队：%d\n", $modes[$status['mode']] ?? $status['mode'], $status['model'] !== '' ? '（' . $status['model'] . '）' : '', $status['entities'], $status['vectors'], $status['queued']));
        exit(0);
    }
    if (!$search->enabled()) {
        fwrite(STDERR, $search->mode() === 'rewrite' ? "当前 AI 服务商没有向量接口，已使用查询改写，无需补建\n" : "未开启向量语义搜索（后台 设置 → 智能搜索）\n");
        exit(1);
    }
    if ($command === 'semantic:backfill') {
        fwrite(STDOUT, sprintf("已入队 %d 条，cron:run 会逐条处理\n", $search->backfill()));
        exit(0);
    }
    $failed = 0;
    $created = $search->runAll(static function (string $type, int $id, string $error) use (&$failed): void {
        $failed++;
        fwrite(STDERR, sprintf("%s %d 失败：%s\n", $type, $id, $error));
    });
    fwrite(STDOUT, sprintf("生成向量 %d 条，失败 %d 条\n", $created, $failed));
    exit($failed > 0 ? 2 : 0);
}

if ($command === 'release:build') {
    exit(\KingCMS\Release\ReleaseBuildCommand::run(array_slice($argv, 2)));
}

if ($command === 'theme:publish') {
    exit(\KingCMS\Release\ThemePublisher::run(array_slice($argv, 2)));
}

if ($command === 'country:build') {
    exit(\KingCMS\Console\CountryDataBuildCommand::run(array_slice($argv, 2)));
}

if ($command === 'country:update') {
    try {
        $manifest = (new \KingCMS\I18n\CountryData())->update($argv[2] ?? null);
        fwrite(STDOUT, '国家数据已更新到 ' . ($manifest['data_version'] ?? '') . PHP_EOL);
        exit(0);
    } catch (\Throwable $exception) {
        fwrite(STDERR, $exception->getMessage() . PHP_EOL);
        exit(1);
    }
}

if ($command === 'check:web') {
    // 线上部署自检：只读，不建库、不跑迁移；HTTP 与 PHP 环境均由 WebCheck 负责。
    exit(\KingCMS\Console\CheckWebCommand::run(array_slice($argv, 2), dirname(__DIR__)));
}

if ($command !== 'admin:reset-password') {
    fwrite(STDERR, "用法：php x1/bin/kingcms local:list [--json]|local:check|local:export|local:upgrade|local:check-update|cron:run|langpack:run|upgrade:run|semantic:run|semantic:backfill|semantic:status|release:build|theme:publish|country:build|country:update|pulo:import|check:web|admin:reset-password\n");
    exit(1);
}

$ask = static function (string $prompt): string {
    fwrite(STDOUT, $prompt);
    $line = fgets(STDIN);

    return $line === false ? '' : rtrim($line, "\r\n");
};

$askHidden = static function (string $prompt): string {
    fwrite(STDOUT, $prompt);

    $interactive = function_exists('stream_isatty') && stream_isatty(STDIN);
    if ($interactive) {
        shell_exec('stty -echo');
    }

    try {
        $line = fgets(STDIN);
    } finally {
        if ($interactive) {
            shell_exec('stty echo');
            fwrite(STDOUT, PHP_EOL);
        }
    }

    return $line === false ? '' : rtrim($line, "\r\n");
};

$out = static function (string $message): void {
    fwrite(STDOUT, $message . PHP_EOL);
};

$dataDir = __DIR__ . '/../data';
$pdo = Connection::get($dataDir . '/kingcms.sqlite');
(new Migrator($pdo, __DIR__ . '/../app/Database/migrations'))->run();

$reset = new AdminPasswordReset(
    $pdo,
    new AdminAccounts($pdo),
    new SessionStore($pdo, 43200)
);

exit((new ResetPasswordCommand($reset, $ask, $askHidden, $out))->run());
