<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Sport as SportModel;
use App\Models\SportOdds as SportOddsModel;
use App\Services\SportClientService;
use Illuminate\Support\Facades\Log;
use App\Models\Config;
use Illuminate\Support\Facades\Cache;
use Throwable; // 使用 Throwable 可以捕获所有 PHP 7+ 的异常和错误

class SportOdds extends Command
{
    /**
     * 命令名称和签名
     *
     * @var string
     */
    protected $signature = 'sport:odds {is_live=0}';

    protected $is_live = 0;
    
    protected $long_status = [
        'Time To Be Defined' => 0,
        'Not Started' => 0,
        'First Half' => 1,
        'First Half, Kick Off' => 1,
        'Halftime' => 1,
        'Second Half' => 1,
        'Second Half, 2nd Half Started' => 1,
        'Extra Time' => 1,
        'Break Time' => 1,
        'Penalty In Progress' => 1,
        'Match Suspended' => 1,
        'Match Interrupted' => 4,
        'Match Finished' => 2,
        'Match Postponed' => 3,
        'Match Cancelled' => 4,
        'Match Abandoned' => 4,
        'Technical Loss' => 4,
        'WalkOver' => 4,
        'In Progress' => 1,
    ];        
    
    protected $fixture_status = [
        'First Half' => 1,
        'First Half, Kick Off' => 1,
        'Halftime' => 1,
        'Second Half' => 1,
        'Second Half, 2nd Half Started' => 1,
        'Extra Time' => 1,
        'Break Time' => 1,
        'Penalty In Progress' => 1,
    ];        

    /**
     * 命令描述
     *
     * @var string
     */
    protected $description = '赔率（直播赔率5秒更新一次，塞前赔率3小时更新一次）';
    /**
     * 执行命令
     *
     * @return int
     */
    public function handle()
    {
        $this->is_live = $this->argument('is_live');            
        $this->sportOddsData($this->is_live);
    }

    public function sportOddsData($is_live)
    {
        if ($is_live == 1) {
            // 直播赔率通常是一次获取全量，但也需要对整体更新逻辑做保护
            $data = SportClientService::oddsLive([]);
            if ($data) {
                // file_put_contents("oddsLive.json",json_encode($data));
                $this->updateOddsLive($data);
            }
        } else {
            $limit = 3000;
            //普通球赛是开赛前购买，更新数据
            $where['state'] = 0;  //比赛状态：0未开始1进行中2已完场3延期4取消
            $list = SportModel::where($where)->where('odds',null)->limit($limit)->get()->toArray();

            foreach ($list as $item) {
                // --- 关键优化：在循环内部嵌套 try-catch ---
                try {
                    $data = SportClientService::odds([
                        'fixture' => $item['data_id'],
                    ]);
                    $this->updateOdds($item['data_id'], $data);
                } catch (Throwable $e) {
                    // 记录具体哪条赛事出错了，但不抛出，让循环继续
                    Log::error($item['data_id'].",赛前赔率更新失败: " . $e->getMessage());
                    continue; 
                }
            }
        }
        
        return true;
    }

    public function updateOddsLive($data)
    {
        if (empty($data['response'])) return;

        //体育赛事结束前几(分钟)锁盘,90分钟结束
        $sport_locked = Config::where('field', 'sport_locked')->first()->val ?? 1;
        $responses = $data['response'];

        foreach ($responses as $item) {
            // --- 关键优化：直播赔率逐条更新也要包裹，防止单条数据格式问题挂掉全盘 ---
            try {
                $data_id = $item['fixture']['id'];
                $sport_info = SportModel::where('data_id',$data_id)->select('odds','odd_ids_locked')->first();
                
                if (!$sport_info) continue;

                $old_odd_ids_locked = $sport_info['odd_ids_locked'];
                $odds_data = $this->doOdds($item['odds'], $sport_info['odds']);
                $odds = $odds_data['odds'];
                $odds = !empty($odds) ? json_encode($odds) : null;
                $odd_ids_locked = array_merge($old_odd_ids_locked, $odds_data['odd_ids_locked']);
                
                $update_data = [
                    'is_send' => 0,
                    'is_roll' => 1,
                    'is_locked' => 0,
                    'odd_ids_locked' => array_unique($odd_ids_locked),
                    'odds' => $odds,
                    'error' => 0, //异常类型：0正常；1直播赔率的赛事时异常
                ];
                $odd_fixture_status = null;//直播赔率中的赛事时间和状态（与直播赛事信息中的赛事时间和状态存在较大差异）
                if (isset($item['fixture']['status']['long']) ) {
                    // $long = $item['fixture']['status']['long'];
                    // if (isset($this->fixture_status[$long])) {
                        $sport_info = SportModel::where('data_id',$data_id)->first();
                        $fixture_status = $sport_info['fixture_status'] ? json_decode($sport_info['fixture_status'],true) : [];
                        
                        $odd_fixture_status = $item['fixture']['status'];
                        $update_data['odd_fixture_status'] = json_encode($odd_fixture_status);
                        
                        //如果时间差距超过3分钟，则锁盘(赛事时间90分钟内)
                        if (isset($fixture_status['elapsed']) && $fixture_status['elapsed'] < 90 && isset($odd_fixture_status['elapsed'])) {
                            if (abs($fixture_status['elapsed'] - $odd_fixture_status['elapsed']) >= 3) {
                                
                                $update_data['error'] = 1;      //异常
                                $update_data['is_locked'] = 1; //锁盘
                                unset($update_data['odds']);//不更新赔率
                            } else {
                                $update_data['error'] = 0;
                            }
                        }
                    // } 
                }
                
                //锁盘
                if (isset($item['fixture']['status']['blocked']) && $item['fixture']['status']['blocked']) {
                    $update_data['is_locked'] = 1;
                }
                //提前锁盘(比赛进行时长，分钟)
                if (isset($item['fixture']['status']['elapsed'])) {
                    $elapsed = $item['fixture']['status']['elapsed'];
                    if ((int)$elapsed >= 90 - $sport_locked ) {
                       $update_data['is_locked'] = 1;
                    }
                }
                //已结束
                if (isset($item['fixture']['status']['finished']) && $item['fixture']['status']['finished']) {
                    $update_data['state'] = 2;
                }
                //如果赛事取消、延期等，标记需要退款
                if (isset($update_data['state']) && $update_data['state'] > 2) {
                    $update_data['refund_status'] = 1;
                }

                SportModel::where('data_id', $data_id)->update($update_data);

            } catch (Throwable $e) {
                Log::error("直播赔率单条更新失败 [ID: {$data_id}]: " . $e->getMessage());
                continue;
            }
        }
    }

    public function updateOdds($data_id, $data)
    {
        if (!empty($data['response'][0]['bookmakers'][0]['bets'])) {
            $odds = $data['response'][0]['bookmakers'][0]['bets'];
            SportModel::where('data_id',$data_id)->update(['odds' => json_encode($odds), 'is_send' => 0]);
        } 
    }

    //去掉无效的赔率
    private function doOdds($odds, $old_odds) {
        // 1. 获取赔率，缓存数据
        $sport_odds = cache('sport_odds');
        if (!$sport_odds) {
            $sport_odds = SportOddsModel::where('function_name', '<>', null)->get()->toArray();
            Cache::set('sport_odds', $sport_odds, 300); //有效期5分钟
        }
        $old_odds = $old_odds ? json_decode($old_odds, true) : [];
        $odds_ids = []; //新的玩法id集合

        $sport_odds = array_column($sport_odds, null,'odd_name_en');
        $new_odds = [];
        foreach($odds as $item) {
            if (!isset($sport_odds[$item['name']])) {
                continue;
            }
            $new_odds[] = $item;
            $odds_ids[] = $item['id'];
        }
        $odd_ids_locked = [];
        foreach($old_odds as $item) {
            if (!in_array($item['id'], $odds_ids)) {
                $new_odds[] = $item;
                //历史玩法如果没有了，数据保存，加锁
                $odd_ids_locked[] = $item['id'];
            }
        }
        return [
            'odds' => $new_odds,
            'odd_ids_locked' => $odd_ids_locked,
        ];
    }

}
