<?php

namespace Kylin\AntiAddiction\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Kylin\AntiAddiction\Enums\AntiAddictionErrorCode;
use Kylin\AntiAddiction\Exceptions\AntiAddictionException;
use Kylin\AntiAddiction\Models\Holiday;

/**
 * 节假日管理服务
 *
 * 管理法定节假日数据，用于防沉迷时段判断。
 * 未成年人可在法定节假日的允许时段内游戏。
 *
 * 数据来源：
 * 1. 数据库（手动维护）
 * 2. 国务院公开 API（自动同步）
 * 3. 本地缓存（减少查询）
 */
class HolidayService
{
    /**
     * 判断指定日期是否为法定节假日
     */
    public function isHoliday(string $date, string $country = 'CN'): bool
    {
        return Cache::remember(
            "kylin:holiday:{$country}:{$date}",
            86400,
            fn (): bool => Holiday::isHoliday($date, $country),
        );
    }

    /**
     * 获取指定年份的所有节假日
     *
     * @return array<int, array{name: string, dates: array<string>}>
     */
    public function getHolidaysByYear(int $year, string $country = 'CN'): array
    {
        return Cache::remember(
            "kylin:holidays:{$country}:{$year}",
            86400 * 30,
            function () use ($year, $country): array {
                $holidays = Holiday::where('year', $year)
                    ->where('country', $country)
                    ->get();

                if ($holidays->isEmpty()) {
                    // 尝试从远程 API 同步
                    $this->syncFromRemote($year, $country);
                    $holidays = Holiday::where('year', $year)
                        ->where('country', $country)
                        ->get();
                }

                return $holidays->map(fn (Holiday $holiday) => [
                    'name' => $holiday->name,
                    'dates' => $holiday->dates,
                ])->all();
            },
        );
    }

    /**
     * 获取指定年份所有节假日日期（扁平化）
     *
     * @return array<string>
     */
    public function getHolidayDatesByYear(int $year, string $country = 'CN'): array
    {
        return Cache::remember(
            "kylin:holiday_dates:{$country}:{$year}",
            86400 * 30,
            fn (): array => Holiday::getDatesByYear($year, $country),
        );
    }

    /**
     * 从远程 API 同步节假日数据
     *
     * 对接国务院公开的节假日安排 API。
     * 同步成功后写入数据库并清除缓存。
     */
    public function syncFromRemote(int $year, string $country = 'CN'): bool
    {
        try {
            // 对接节假日 API（如 timor.tech 或自建服务）
            $response = Http::get("https://timor.tech/api/holiday/year/{$year}", [
                'holiday' => 'true',
            ]);

            if (! $response->successful()) {
                Log::warning('节假日 API 请求失败', [
                    'year' => $year,
                    'status' => $response->status(),
                ]);

                return false;
            }

            $data = $response->json();
            $holidays = $data['holiday'] ?? [];

            if (empty($holidays)) {
                return false;
            }

            // 按节假日名称分组日期
            $grouped = [];
            foreach ($holidays as $dateStr => $info) {
                if (($info['holiday'] ?? false) === true) {
                    $name = $info['name'] ?? '未知节假日';
                    $grouped[$name][] = $dateStr;
                }
            }

            // 写入数据库
            foreach ($grouped as $name => $dates) {
                sort($dates);
                Holiday::updateOrCreate(
                    ['year' => $year, 'name' => $name, 'country' => $country],
                    ['dates' => $dates],
                );
            }

            // 清除缓存
            $this->clearCache($year, $country);

            Log::info('节假日数据同步成功', [
                'year' => $year,
                'count' => count($grouped),
            ]);

            return true;
        } catch (\Throwable $e) {
            Log::error('节假日数据同步异常', [
                'year' => $year,
                'message' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * 手动创建节假日
     */
    public function createHoliday(int $year, string $name, array $dates, string $country = 'CN'): Holiday
    {
        sort($dates);

        $holiday = Holiday::updateOrCreate(
            ['year' => $year, 'name' => $name, 'country' => $country],
            ['dates' => $dates],
        );

        $this->clearCache($year, $country);

        return $holiday;
    }

    /**
     * 清除节假日缓存
     */
    public function clearCache(int $year, string $country = 'CN'): void
    {
        Cache::forget("kylin:holidays:{$country}:{$year}");
        Cache::forget("kylin:holiday_dates:{$country}:{$year}");

        // 清除该年每个日期的缓存
        $dates = Holiday::getDatesByYear($year, $country);
        foreach ($dates as $date) {
            Cache::forget("kylin:holiday:{$country}:{$date}");
        }
    }
}
