<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class FixDoubleEncodedOptions extends Command
{
    protected $signature = 'fix:options
                            {--ids= : 指定题目ID，多个用逗号隔开，如: --ids=21757,21892}
                            {--limit=10 : 限制处理数量，默认10条}
                            {--execute : 真正执行修复，不加此参数则为 dry-run 模式}';

    protected $description = '修复 questions 表中双重编码的 options 字段';

    public function handle()
    {
        $ids = $this->option('ids');
        $limit = (int) $this->option('limit');
        $execute = $this->option('execute');

        $this->info('');
        $this->info($execute ? '=== 执行模式 ===' : '=== DRY-RUN 模式（不会修改数据）===');
        $this->info('');

        // 构建查询
        $query = DB::connection('remote_mysql')
            ->table('questions')
            ->where('options', 'LIKE', '"{%')  // 双重编码特征：以 "{ 开头
            ->whereNotNull('options');

        // 如果指定了 IDs
        if ($ids) {
            $idArray = array_map('trim', explode(',', $ids));
            $query->whereIn('id', $idArray);
            $this->info("指定 ID: " . implode(', ', $idArray));
        } else {
            $query->limit($limit);
            $this->info("限制数量: {$limit} 条");
        }

        $questions = $query->get(['id', 'options']);

        if ($questions->isEmpty()) {
            $this->warn('没有找到需要修复的数据');
            return 0;
        }

        $this->info("找到 {$questions->count()} 条待处理记录");
        $this->info('');
        $this->table(['ID', '状态', '原始值 (前50字符)', '修复后 (前50字符)'], []);

        $successCount = 0;
        $failCount = 0;
        $results = [];

        foreach ($questions as $q) {
            $original = $q->options;
            $result = $this->tryFix($original);

            if ($result['success']) {
                $status = '<fg=green>可修复</>';
                $successCount++;

                if ($execute) {
                    DB::connection('remote_mysql')
                        ->table('questions')
                        ->where('id', $q->id)
                        ->update(['options' => $result['fixed']]);
                    $status = '<fg=green>已修复</>';
                }
            } else {
                $status = '<fg=red>失败: ' . $result['error'] . '</>';
                $failCount++;
            }

            $results[] = [
                $q->id,
                $status,
                mb_substr($original, 0, 50) . '...',
                $result['success'] ? mb_substr($result['fixed'], 0, 50) . '...' : '-',
            ];

            // 详细日志
            $this->line("ID: {$q->id}");
            $this->line("  原始: " . mb_substr($original, 0, 80) . '...');
            if ($result['success']) {
                $this->line("  修复: " . mb_substr($result['fixed'], 0, 80) . '...');
            } else {
                $this->error("  错误: " . $result['error']);
            }
            $this->line('');
        }

        // 汇总
        $this->info('=== 汇总 ===');
        $this->info("可修复/已修复: {$successCount} 条");
        if ($failCount > 0) {
            $this->warn("失败: {$failCount} 条");
        }

        if (!$execute && $successCount > 0) {
            $this->info('');
            $this->warn('这是 DRY-RUN 模式，数据未被修改。');
            $this->info('确认无误后，添加 --execute 参数真正执行：');
            if ($ids) {
                $this->info("  php artisan fix:options --ids={$ids} --execute");
            } else {
                $this->info("  php artisan fix:options --limit={$limit} --execute");
            }
        }

        return 0;
    }

    /**
     * 尝试修复双重编码的 JSON
     */
    private function tryFix(string $original): array
    {
        // 第一次解码
        $decoded = json_decode($original, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            return [
                'success' => false,
                'error' => 'JSON解码失败: ' . json_last_error_msg(),
                'fixed' => null,
            ];
        }

        // 如果解码后是字符串，说明是双重编码
        if (is_string($decoded)) {
            // 先尝试直接解码
            $secondDecode = json_decode($decoded, true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                // 解码失败，可能是 LaTeX 中的反斜杠问题
                // 问题：\times 中的 \t 是合法 JSON 转义(tab)，\frac 中的 \f 也是(form feed)
                // 解决：第一次解码后，所有反斜杠都是 LaTeX 的，全部转义为双反斜杠
                $escapedDecoded = str_replace('\\', '\\\\', $decoded);
                $secondDecode = json_decode($escapedDecoded, true);

                if (json_last_error() !== JSON_ERROR_NONE) {
                    return [
                        'success' => false,
                        'error' => '二次JSON解码失败: ' . json_last_error_msg(),
                        'fixed' => null,
                    ];
                }
            }

            $decoded = $secondDecode;
        }

        // 验证结果是数组
        if (!is_array($decoded)) {
            return [
                'success' => false,
                'error' => '解码结果不是数组',
                'fixed' => null,
            ];
        }

        // 重新编码为标准 JSON
        $fixed = json_encode($decoded, JSON_UNESCAPED_UNICODE);

        return [
            'success' => true,
            'error' => null,
            'fixed' => $fixed,
        ];
    }

}
