<?php

namespace App\Support;

use App\Models\Currency;
use App\Models\OddsItem;
use App\Models\PlayType;
use App\Models\OddsVersion;
use Illuminate\Support\Facades\DB;

/**
 * 界面文档 §5.5：每个玩法需具备的五档 prize_scope；odds_value = 乘数×10000。
 */
final class OddsStandardScopes
{
    /** @var array<string, int> */
    public const PRESET_ODDS_BY_SCOPE = [
        'first' => 250_000,
        'second' => 110_000,
        'third' => 55_000,
        'starter' => 22_000,
        'consolation' => 6_500,
    ];

    /** @var list<string> */
    public const SCOPE_KEYS = ['first', 'second', 'third', 'starter', 'consolation'];

    /**
     * 为指定赔率版本补全缺失的标准五档行（幂等）。
     *
     * 仅对「该版本里已出现过的 (play_code, currency_code)」补全，避免给从未配置过的玩法凭空加行。
     * 若版本下无任何 odds_items，则用当前全部玩法 × 首个可下注币种补全。
     * 
     * 佣金按维度（2D/3D/4D）配置：同一维度的所有玩法共享佣金率。
     */
    public static function syncMissingForVersion(OddsVersion $version): void
    {
        DB::transaction(function () use ($version): void {
            $vid = (int) $version->id;

            $pairs = OddsItem::query()
                ->where('version_id', $vid)
                ->select(['play_code', 'currency_code'])
                ->distinct()
                ->get();

            if ($pairs->isEmpty()) {
                $currencyCode = Currency::query()
                    ->where('is_bettable', true)
                    ->where('is_enabled', true)
                    ->orderBy('code')
                    ->value('code');
                if ($currencyCode === null || $currencyCode === '') {
                    return;
                }
                $pairs = PlayType::query()
                    ->orderBy('sort_order')
                    ->orderBy('play_code')
                    ->get(['play_code', 'dimension'])
                    ->map(fn (PlayType $pt) => (object) [
                        'play_code' => $pt->play_code,
                        'dimension' => $pt->dimension,
                        'currency_code' => $currencyCode,
                    ]);
            }

            // 按维度分组，获取每个维度的佣金率
            $dimensionCommissions = [];
            foreach ($pairs as $pair) {
                $dimension = $pair->dimension ?? null;
                $currencyCode = strtoupper((string) $pair->currency_code);
                $key = $dimension.'|'.$currencyCode;
                
                if (!isset($dimensionCommissions[$key])) {
                    // 从现有记录中获取该维度的佣金率
                    $anchor = OddsItem::query()
                        ->where('version_id', $vid)
                        ->where('currency_code', $currencyCode)
                        ->where('dimension', $dimension)
                        ->orderByDesc('id')
                        ->first();
                    
                    $dimensionCommissions[$key] = [
                        'rebate' => (float) ($anchor?->rebate_rate ?? 0),
                        'commission' => (float) ($anchor?->commission_rate ?? 0),
                    ];
                }
            }

            foreach ($pairs as $pair) {
                $playCode = (string) $pair->play_code;
                $dimension = $pair->dimension ?? null;
                $currencyCode = strtoupper((string) $pair->currency_code);
                $key = $dimension.'|'.$currencyCode;
                
                $rebate = $dimensionCommissions[$key]['rebate'] ?? 0;
                $commission = $dimensionCommissions[$key]['commission'] ?? 0;

                foreach (self::PRESET_ODDS_BY_SCOPE as $scope => $oddsValue) {
                    $exists = OddsItem::query()
                        ->where('version_id', $vid)
                        ->where('play_code', $playCode)
                        ->where('currency_code', $currencyCode)
                        ->where('prize_scope', $scope)
                        ->exists();
                    if ($exists) {
                        continue;
                    }

                    OddsItem::query()->create([
                        'version_id' => $vid,
                        'play_code' => $playCode,
                        'prize_scope' => $scope,
                        'dimension' => $dimension,
                        'odds_value' => $oddsValue,
                        'rebate_rate' => $rebate,
                        'commission_rate' => $commission,
                        'currency_code' => $currencyCode,
                        'extra_config_json' => null,
                    ]);
                }
            }
        });
    }
}
