<?php

/**
 * 文件功能：双色球期次 Model
 *
 * 管理每期彩票的生命周期：open（购票中）→ closed（停售）→ settled（已开奖）。
 * 提供静态查询方法、奖级判定辅助及号码排序工具。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class LotteryIssue extends Model
{
    protected $fillable = [
        'issue_no',
        'status',
        'red1', 'red2', 'red3', 'blue',
        'pool_amount',
        'carry_amount',
        'is_super_issue',
        'no_winner_streak',
        'total_tickets',
        'payout_amount',
        'sell_closes_at',
        'draw_at',
    ];

    /**
     * 字段类型转换。
     */
    protected function casts(): array
    {
        return [
            'is_super_issue' => 'boolean',
            'pool_amount' => 'integer',
            'carry_amount' => 'integer',
            'payout_amount' => 'integer',
            'total_tickets' => 'integer',
            'sell_closes_at' => 'datetime',
            'draw_at' => 'datetime',
        ];
    }

    // ─── 关联 ──────────────────────────────────────────────────────────

    /**
     * 本期所有购票记录。
     */
    public function tickets(): HasMany
    {
        return $this->hasMany(LotteryTicket::class, 'issue_id');
    }

    /**
     * 本期奖池流水。
     */
    public function poolLogs(): HasMany
    {
        return $this->hasMany(LotteryPoolLog::class, 'issue_id');
    }

    // ─── 静态查询 ──────────────────────────────────────────────────────

    /**
     * 获取当前正在购票的期次（status=open）。
     */
    public static function currentIssue(): ?static
    {
        return static::query()->where('status', 'open')->latest()->first();
    }

    /**
     * 获取最新一期（不论状态）。
     */
    public static function latestIssue(): ?static
    {
        return static::query()->latest()->first();
    }

    /**
     * 生成下一期的期号（格式：年份 + 三位序号，如 2026001）。
     */
    public static function nextIssueNo(): string
    {
        $year = now()->year;
        $last = static::query()
            ->whereYear('created_at', $year)
            ->latest()
            ->first();

        $seq = $last ? ((int) substr($last->issue_no, -3)) + 1 : 1;

        return $year.str_pad($seq, 3, '0', STR_PAD_LEFT);
    }

    // ─── 业务方法 ──────────────────────────────────────────────────────

    /**
     * 判断当前期次是否仍在售票中。
     */
    public function isOpen(): bool
    {
        return $this->status === 'open' && now()->lt($this->sell_closes_at);
    }

    /**
     * 距离开奖剩余秒数。
     */
    public function secondsUntilDraw(): int
    {
        if (! $this->draw_at) {
            return 0;
        }

        return max(0, (int) now()->diffInSeconds($this->draw_at, false));
    }

    /**
     * 判断给定号码是否与开奖号码匹配并返回奖级（0=未中）。
     *
     * @param  int  $r1  用户红球1（已排序）
     * @param  int  $r2  用户红球2
     * @param  int  $r3  用户红球3
     * @param  int  $b  用户蓝球
     */
    public function calcPrizeLevel(int $r1, int $r2, int $r3, int $b): int
    {
        $userReds = [$r1, $r2, $r3];
        $drawReds = [$this->red1, $this->red2, $this->red3];
        $redMatches = count(array_intersect($userReds, $drawReds));
        $blueMatch = ($b === $this->blue);

        return match (true) {
            $redMatches === 3 && $blueMatch => 1, // 一等奖
            $redMatches === 3 && ! $blueMatch => 2, // 二等奖
            $redMatches === 2 && $blueMatch => 3, // 三等奖
            $redMatches === 2 && ! $blueMatch => 4, // 四等奖
            $redMatches === 1 && $blueMatch => 5, // 五等奖
            default => 0,                           // 未中奖
        };
    }

    /**
     * 返回奖级的中文标签。
     */
    public static function prizeLevelLabel(int $level): string
    {
        return match ($level) {
            1 => '一等奖',
            2 => '二等奖',
            3 => '三等奖',
            4 => '四等奖',
            5 => '五等奖',
            default => '未中奖',
        };
    }
}
