<?php

/**
 * 文件功能：赛马竞猜局次模型
 *
 * 代表一场赛马比赛，包含参赛马匹信息、场次状态、
 * 注池统计以及赛果信息。提供当前场次查询和赔率计算方法。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Models;

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

class HorseRace extends Model
{
    protected $fillable = [
        'status',
        'bet_opens_at',
        'bet_closes_at',
        'race_starts_at',
        'race_ends_at',
        'horses',
        'winner_horse_id',
        'total_bets',
        'total_pool',
        'settled_at',
    ];

    /**
     * 属性类型转换。
     */
    protected function casts(): array
    {
        return [
            'bet_opens_at' => 'datetime',
            'bet_closes_at' => 'datetime',
            'race_starts_at' => 'datetime',
            'race_ends_at' => 'datetime',
            'settled_at' => 'datetime',
            'horses' => 'array',
            'winner_horse_id' => 'integer',
            'total_bets' => 'integer',
            'total_pool' => 'integer',
        ];
    }

    /**
     * 本场所有下注记录。
     */
    public function bets(): HasMany
    {
        return $this->hasMany(HorseBet::class, 'race_id');
    }

    /**
     * 判断当前是否在押注时间窗口内。
     */
    public function isBettingOpen(): bool
    {
        return $this->status === 'betting'
            && now()->between($this->bet_opens_at, $this->bet_closes_at);
    }

    /**
     * 查询当前正在进行的场次（状态为 betting 且押注未截止）。
     */
    public static function currentRace(): ?static
    {
        return static::query()
            ->whereIn('status', ['betting', 'running'])
            ->latest()
            ->first();
    }

    /**
     * 生成参赛马匹列表（根据马匹数量随机选名）。
     *
     * @param  int  $count  马匹数量
     * @return array<int, array{id: int, name: string, emoji: string}>
     */
    public static function generateHorses(int $count): array
    {
        // 可用马匹名池（原版竞技风格）
        $namePool = [
            ['name' => '赤兔', 'emoji' => '🐎'],
            ['name' => '乌骓', 'emoji' => '🐴'],
            ['name' => '的卢', 'emoji' => '🎠'],
            ['name' => '绝影', 'emoji' => '🦄'],
            ['name' => '紫骍', 'emoji' => '🐎'],
            ['name' => '爪黄', 'emoji' => '🐴'],
            ['name' => '汗血', 'emoji' => '🎠'],
            ['name' => '飞电', 'emoji' => '⚡'],
        ];

        // 随机打乱并取前 N 个
        shuffle($namePool);
        $selected = array_slice($namePool, 0, $count);

        $horses = [];
        foreach ($selected as $i => $horse) {
            $horses[] = [
                'id' => $i + 1,
                'name' => $horse['name'],
                'emoji' => $horse['emoji'],
            ];
        }

        return $horses;
    }

    /**
     * 计算本场可派奖总池。
     *
     * 可派奖池 = 系统初始化资金池 + 玩家总下注 - 抽水，
     * 且至少不低于中奖马匹总下注，避免出现“押中反亏”的体验。
     *
     * @param  array<int, int|float>  $horseBetAmounts
     */
    public static function calcDistributablePool(array $horseBetAmounts, int $housePercent, int $seedPool = 0, int $winnerPool = 0): float
    {
        $totalPool = array_sum($horseBetAmounts);
        $netPlayerPool = $totalPool * (1 - $housePercent / 100);

        return max($netPlayerPool + max(0, $seedPool), $winnerPool);
    }

    /**
     * 根据注池计算各马匹实时赔率（含系统初始化资金池）。
     *
     * @param  array<int, int|float>  $horseBetAmounts  各马匹的注额数组 [horse_id => amount]
     * @return array<int, float> horse_id => 赔率（含本金）
     */
    public static function calcOdds(array $horseBetAmounts, int $housePercent, int $seedPool = 0): array
    {
        $totalPool = array_sum($horseBetAmounts);

        if ($totalPool <= 0) {
            return array_map(fn () => 1.0, $horseBetAmounts);
        }

        $distributablePool = static::calcDistributablePool($horseBetAmounts, $housePercent, $seedPool);
        $odds = [];

        foreach ($horseBetAmounts as $horseId => $amount) {
            if ($amount <= 0) {
                $odds[$horseId] = round($distributablePool, 2);
            } else {
                $odds[$horseId] = round($distributablePool / $amount, 2);
            }
        }

        return $odds;
    }
}
