<?php

namespace App\Apps\Versionmgr\Services;

use App\Apps\Versionmgr\Models\SkipRecord;
use App\Apps\Versionmgr\Models\UpgradePackage;
use App\Http\Responses\ApiResponse;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class VersionCheckService
{
    protected function getApiUrl(): string
    {
        return rtrim(config('apps.market.api_url'), '/');
    }

    protected function getCacheTtl(): int
    {
        return config('apps.market.cache_ttl', 3600);
    }

    public function getCurrentVersion(): array
    {
        try {
            $current = \App\Apps\Versionmgr\Models\SystemVersion::getCurrentVersion();
        } catch (\Throwable $e) {
            Log::warning('获取当前版本失败', ['error' => $e->getMessage()]);
            $current = null;
        }

        if (!$current) {
            return ApiResponse::success([
                'version' => config('app.version', '5.0.1'),
                'build' => date('Ymd'),
                'install_time' => null,
                'changelog' => '初始版本',
            ]);
        }

        return ApiResponse::success([
            'version' => $current->version,
            'build' => $current->build,
            'install_time' => $current->create_time?->format('Y-m-d H:i:s'),
            'changelog' => $current->changelog,
        ]);
    }

    public function checkUpdate(): array
    {
        try {
            $current = \App\Apps\Versionmgr\Models\SystemVersion::getCurrentVersion();
        } catch (\Throwable $e) {
            Log::warning('获取当前版本失败', ['error' => $e->getMessage()]);
            $current = null;
        }
        $currentVersion = $current ? $current->version : config('app.version', '5.0.1');
        $currentBuild = $current ? $current->build : '';

        try {
            $latestInfo = $this->fetchLatestVersion();

            if (!$latestInfo) {
                return ApiResponse::success([
                    'has_update' => false,
                    'current_version' => $currentVersion,
                    'current_build' => $currentBuild,
                    'latest_version' => $currentVersion,
                    'latest_build' => $currentBuild,
                    'upgrade_path' => [],
                    'changelog' => '',
                    'is_skipped' => false,
                    'packages_ready' => true,
                ]);
            }

            $hasUpdate = version_compare($latestInfo['version'], $currentVersion, '>');
            if (!$hasUpdate) {
                return ApiResponse::success([
                    'has_update' => false,
                    'current_version' => $currentVersion,
                    'current_build' => $currentBuild,
                    'latest_version' => $currentVersion,
                    'latest_build' => $currentBuild,
                    'upgrade_path' => [],
                    'changelog' => '',
                    'is_skipped' => false,
                    'packages_ready' => true,
                ]);
            }

            $upgradePath = $this->calculateUpgradePath($currentVersion, $latestInfo['version']);

            $isSkipped = SkipRecord::isSkipped($latestInfo['version'], $latestInfo['build'] ?? '');

            $packagesReady = $this->checkPackagesReady($upgradePath);

            $changelog = $this->collectChangelog($upgradePath);

            return ApiResponse::success([
                'has_update' => true,
                'current_version' => $currentVersion,
                'current_build' => $currentBuild,
                'latest_version' => $latestInfo['version'],
                'latest_build' => $latestInfo['build'] ?? '',
                'upgrade_path' => $upgradePath,
                'changelog' => $changelog,
                'is_skipped' => $isSkipped,
                'packages_ready' => $packagesReady,
            ]);
        } catch (\Throwable $e) {
            Log::error('版本检查失败', ['error' => $e->getMessage()]);
            return ApiResponse::error(60011, '远程版本服务不可用');
        }
    }

    public function calculateUpgradePath(string $fromVersion, string $toVersion): array
    {
        $path = [];
        $current = $fromVersion;

        $remoteSteps = $this->fetchUpgradeSteps($fromVersion, $toVersion);

        foreach ($remoteSteps as $step) {
            $localPackage = UpgradePackage::findByVersions($step['from_version'], $step['to_version']);
            $path[] = [
                'from' => $step['from_version'],
                'to' => $step['to_version'],
                'build' => $step['build'] ?? '',
                'changelog' => $step['changelog'] ?? '',
                'download_url' => $step['download_url'] ?? '',
                'available' => true,
                'source' => $localPackage ? 'local' : 'remote',
            ];
            $current = $step['to_version'];
        }

        return $path;
    }

    public function getUpgradePathDetail(string $targetVersion): array
    {
        try {
            $current = \App\Apps\Versionmgr\Models\SystemVersion::getCurrentVersion();
        } catch (\Throwable $e) {
            Log::warning('获取当前版本失败', ['error' => $e->getMessage()]);
            $current = null;
        }
        $currentVersion = $current ? $current->version : config('app.version', '5.0.1');

        $path = $this->calculateUpgradePath($currentVersion, $targetVersion);

        $missingPackages = [];
        foreach ($path as $step) {
            if ($step['source'] === 'remote' && !$step['download_url']) {
                $missingPackages[] = $step['from'] . ' �?' . $step['to'];
            }
        }

        return ApiResponse::success([
            'from_version' => $currentVersion,
            'target_version' => $targetVersion,
            'path' => $path,
            'all_available' => empty($missingPackages),
            'missing_packages' => $missingPackages,
        ]);
    }

    protected function fetchLatestVersion(): ?array
    {
        if (!config('apps.market.enabled')) {
            return null;
        }

        return Cache::remember('versionmgr_latest', $this->getCacheTtl(), function () {
            try {
                $response = Http::withOptions(['verify' => false])
                    ->withHeaders(['Accept' => 'application/json'])
                    ->get($this->getApiUrl() . '/api/versionsvr/latest');

                if (!$response->successful()) {
                    return null;
                }

                $json = $response->json();
                return $json['data'] ?? null;
            } catch (\Throwable $e) {
                Log::error('获取最新版本失败', ['error' => $e->getMessage()]);
                return null;
            }
        });
    }

    protected function fetchUpgradeSteps(string $fromVersion, string $toVersion): array
    {
        if (!config('apps.market.enabled')) {
            return [];
        }

        $cacheKey = "versionmgr_steps_{$fromVersion}_{$toVersion}";

        return Cache::remember($cacheKey, $this->getCacheTtl(), function () use ($fromVersion, $toVersion) {
            try {
                $response = Http::withOptions(['verify' => false])
                    ->withHeaders(['Accept' => 'application/json'])
                    ->get($this->getApiUrl() . '/api/versionsvr/steps', [
                        'from' => $fromVersion,
                        'to' => $toVersion,
                    ]);

                if (!$response->successful()) {
                    return [];
                }

                $json = $response->json();
                return $json['data'] ?? [];
            } catch (\Throwable $e) {
                Log::error('获取升级步骤失败', ['error' => $e->getMessage()]);
                return [];
            }
        });
    }

    protected function checkPackagesReady(array $upgradePath): bool
    {
        foreach ($upgradePath as $step) {
            if ($step['source'] === 'remote' && empty($step['download_url'])) {
                return false;
            }
        }
        return true;
    }

    protected function collectChangelog(array $upgradePath): string
    {
        $logs = [];
        foreach ($upgradePath as $step) {
            if (!empty($step['changelog'])) {
                $logs[] = $step['to'] . ': ' . $step['changelog'];
            }
        }
        return implode("\n", $logs);
    }

    public function skipVersion(string $version, string $build): array
    {
        $exists = SkipRecord::where('version', $version)->where('build', $build)->exists();
        if (!$exists) {
            SkipRecord::create([
                'version' => $version,
                'build' => $build,
                'operator_id' => auth('admin')->id(),
            ]);
        }

        return ApiResponse::success(null, '已跳过此版本提醒');
    }
}
