<?php

namespace App\Apps\Versionmgr\Jobs;

use App\Apps\Versionmgr\Services\UpgradeService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class UpgradeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 1;

    public int $timeout = 3600;

    protected string $taskId;

    public function __construct(string $taskId)
    {
        $this->taskId = $taskId;
    }

    public function handle(UpgradeService $upgradeService): void
    {
        $task = $this->getTask();
        if (!$task) {
            Log::error('升级任务不存在', ['task_id' => $this->taskId]);
            $this->forceClearLock();
            return;
        }

        $upgradePath = $task['upgrade_path'];
        $totalSteps = count($upgradePath);

        for ($i = 0; $i < $totalSteps; $i++) {
            $success = $upgradeService->executeUpgradeStep($this->taskId, $i);

            if (!$success) {
                // 读取失败原因
                $failedTask = $this->getTask();
                $errorMsg = $failedTask['error_message'] ?? "步骤 {$i} 执行失败";

                Log::error('升级步骤失败，已中止', [
                    'task_id' => $this->taskId,
                    'step' => $i,
                    'error' => $errorMsg,
                ]);

                // 确保状态已更新为 failed
                $this->updateTaskStatus('failed', $errorMsg);
                $this->forceClearLock();
                return;
            }
        }

        $this->updateTaskStatus('success');
        $this->forceClearLock();

        Log::info('升级任务完成', ['task_id' => $this->taskId]);
    }

    public function failed(\Throwable $exception): void
    {
        Log::error('升级任务异常', [
            'task_id' => $this->taskId,
            'error' => $exception->getMessage(),
        ]);

        $this->updateTaskStatus('failed', $exception->getMessage());
        $this->forceClearLock();
    }

    protected function getTask(): ?array
    {
        $taskFile = storage_path('app_versionmgr/upgrade_task.json');
        if (!file_exists($taskFile)) {
            return null;
        }

        $task = json_decode(file_get_contents($taskFile), true);
        return $task && $task['task_id'] === $this->taskId ? $task : null;
    }

    protected function updateTaskStatus(string $status, ?string $errorMessage = null): void
    {
        $taskFile = storage_path('app_versionmgr/upgrade_task.json');
        if (!file_exists($taskFile)) {
            return;
        }

        $task = json_decode(file_get_contents($taskFile), true);
        if (!$task || $task['task_id'] !== $this->taskId) {
            return;
        }

        $task['status'] = $status;
        if ($errorMessage) {
            $task['error_message'] = $errorMessage;
        }

        file_put_contents($taskFile, json_encode($task, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    }

    /**
     * 强制清除升级锁，不依赖 lock->release()
     */
    protected function forceClearLock(): void
    {
        // 清缓存 key
        Cache::forget('system_upgrade');

        // 直接删除 cache_locks 表记录
        try {
            $store = Cache::getStore();
            if ($store instanceof \Illuminate\Cache\DatabaseStore) {
                $store->getConnection()->table('cache_locks')->where('key', 'like', '%system_upgrade%')->delete();
            }
        } catch (\Throwable $e) {
            Log::warning('强制清除升级锁失败', ['error' => $e->getMessage()]);
        }
    }
}
