<?php

namespace app\admin\controller;

use app\common\controller\Backend;

/**
 *
 *
 * @icon fa fa-circle-o
 */
class History extends Backend
{

    /**
     * History模型对象
     * @var \app\admin\model\History
     */
    protected $model = null;

    /**
     * 无需额外权限检查的方法（但仍在 admin 模块内，需要 admin 登录）
     * @var array
     */
    protected $noNeedRight = ['missingNum', 'trendData', 'hotColdNumbers', 'colorWaveAnalysis', 'zodiacAnalysis', 'oddEvenAnalysis', 'bigSmallAnalysis', 'specialTrend', 'consecutiveNumbers', 'tailNumbers', 'dashboard', 'specialHeatmap', 'specialHotColdAction', 'zoneTransition', 'colorWaveTransition', 'zoneToColorTransition', 'zodiacTransition', 'tailNumberTransition', 'headNumberTransition', 'predict', 'predictV2', 'predictV3', 'optimizeWeights', 'predictByNormalRelation'];

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\History;

    }

    /**
     * 查看开奖记录（支持按每月日号筛选）
     */
    public function index()
    {
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            return $this->view->fetch();
        }
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        // search_day 在 filter JSON 里，先提取出来再移除
        $filterStr = $this->request->get('filter', '[]', 'trim');
        $opStr = $this->request->get('op', '[]', 'trim');
        $filter = json_decode($filterStr, true) ?: [];
        $op = json_decode($opStr, true) ?: [];
        $searchDay = isset($filter['search_day']) ? $filter['search_day'] : '';
        unset($filter['search_day'], $op['search_day']);
        // 写回 Request 对象
        $ref = new \ReflectionProperty($this->request, 'get');
        $ref->setAccessible(true);
        $getData = $ref->getValue($this->request);
        if (is_array($getData)) {
            $getData['filter'] = json_encode($filter);
            $getData['op'] = json_encode($op);
            $ref->setValue($this->request, $getData);
        }

        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $list = $this->model->where($where);
        // 按每月日号筛选
        if ($searchDay !== '' && is_numeric($searchDay)) {
            $day = intval($searchDay);
            if ($day >= 1 && $day <= 31) {
                $list = $list->whereRaw('DAY(openTime) = ?', [$day]);
            }
        }
        $query = $list->order($sort, $order)->paginate($limit);
        $result = ['total' => $query->total(), 'rows' => $query->items()];
        return json($result);
    }


    /**
     * 查询遗漏号码
     * @return void
     */
    public function missingNum()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 10, 'intval');
            if ($periods < 1 || $periods > 100) {
                $this->error('期数范围必须在 1-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getMissingNumbers($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 获取走势图数据
     * @return void
     */
    public function trendData()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getTrendData($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 获取冷热号码
     * @return void
     */
    public function hotColdNumbers()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getHotColdNumbers($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 波色分析
     */
    public function colorWaveAnalysis()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getColorWaveAnalysis($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 生肖分析
     */
    public function zodiacAnalysis()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getZodiacAnalysis($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 奇偶分析
     */
    public function oddEvenAnalysis()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getOddEvenAnalysis($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 大小分析
     */
    public function bigSmallAnalysis()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getBigSmallAnalysis($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 特码走势
     */
    public function specialTrend()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $result = $this->model->getSpecialTrend($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 连号分析
     */
    public function consecutiveNumbers()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $result = $this->model->getConsecutiveNumbers($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 尾数分析
     */
    public function tailNumbers()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getTailNumbers($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 综合统计面板
     */
    public function dashboard()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $type = $this->request->get('type', 'all');
            if (!in_array($type, ['all', 'special'])) {
                $this->error('查询类型不正确');
            }
            $result = $this->model->getDashboardData($periods, $type);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 特码冷热列表（每期相对于前N期的冷热状态）
     */
    public function specialHotColdAction()
    {
        if ($this->request->isAjax()) {
            $lookback = $this->request->get('lookback', 30, 'intval');
            if ($lookback < 10 || $lookback > 100) {
                $this->error('向前期数范围必须在 10-100 之间');
            }
            $limit = $this->request->get('limit', 100, 'intval');
            if ($limit < 10 || $limit > 200) {
                $this->error('查询期数范围必须在 10-200 之间');
            }
            $result = $this->model->getSpecialHotColdList($lookback, $limit);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 特码热力图
     */
    public function specialHeatmap()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 30, 'intval');
            if ($periods < 10 || $periods > 100) {
                $this->error('期数范围必须在 10-100 之间');
            }
            $result = $this->model->getSpecialHeatmap($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 区域转移概率统计
     */
    public function zoneTransition()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 10 || $periods > 500) {
                $this->error('期数范围必须在 10-500 之间');
            }
            $result = $this->model->getZoneTransition($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 波色转移概率统计
     */
    public function colorWaveTransition()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 10 || $periods > 500) {
                $this->error('期数范围必须在 10-500 之间');
            }
            $result = $this->model->getColorWaveTransition($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 生肖转移概率统计
     */
    public function zodiacTransition()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 10 || $periods > 500) {
                $this->error('期数范围必须在 10-500 之间');
            }
            $result = $this->model->getZodiacTransition($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 尾号转移概率统计
     */
    public function tailNumberTransition()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 10 || $periods > 500) {
                $this->error('期数范围必须在 10-500 之间');
            }
            $result = $this->model->getTailNumberTransition($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 首号转移概率统计
     */
    public function headNumberTransition()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 10 || $periods > 500) {
                $this->error('期数范围必须在 10-500 之间');
            }
            $result = $this->model->getHeadNumberTransition($periods);
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 综合预测号码
     * 基于历史多维度转移概率分析，给出号码预测建议
     */
    public function predict()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 10 || $periods > 500) {
                $this->error('期数范围必须在 10-500 之间');
            }
            // 权重配置（可选）
            $weights = [];
            $weightStr = $this->request->get('weights', '', 'trim');
            if ($weightStr) {
                $weightsArr = json_decode($weightStr, true);
                if (is_array($weightsArr)) {
                    $weights = $weightsArr;
                }
            }
            // 目标期号（可选，用于验证历史预测成功率）
            $targetExpect = $this->request->get('target_expect', '', 'trim');
            $result = $this->model->getPrediction($periods, $weights, $targetExpect);
            if (isset($result['error'])) {
                $this->error($result['error']);
            }
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 改进版智能预测算法
     * 基于统计回归分析，包含遗漏回归、频率回归、区域平衡等多维度评分
     */
    public function predictV2()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 200, 'intval');
            if ($periods < 30 || $periods > 500) {
                $this->error('期数范围必须在 30-500 之间');
            }
            // 权重配置（可选）
            $weights = [];
            $weightStr = $this->request->get('weights', '', 'trim');
            if ($weightStr) {
                $weightsArr = json_decode($weightStr, true);
                if (is_array($weightsArr)) {
                    $weights = $weightsArr;
                }
            }
            // 目标期号（可选，用于验证历史预测成功率）
            $targetExpect = $this->request->get('target_expect', '', 'trim');
            // 回测期数（可选）
            $backtestCount = $this->request->get('backtest', 50, 'intval');
            if ($backtestCount < 10 || $backtestCount > 100) {
                $backtestCount = 50;
            }
            $result = $this->model->getPredictionV2($periods, $weights, $targetExpect, false, $backtestCount);
            if (isset($result['error'])) {
                $this->error($result['error']);
            }
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 多维度综合预测算法 V3
     * 新增维度：转移概率（马尔可夫链）、单双规律、大小规律、走势方向分析
     */
    public function predictV3()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 200, 'intval');
            if ($periods < 30 || $periods > 500) {
                $this->error('期数范围必须在 30-500 之间');
            }
            // 权重配置（可选）
            $weights = [];
            $weightStr = $this->request->get('weights', '', 'trim');
            if ($weightStr) {
                $weightsArr = json_decode($weightStr, true);
                if (is_array($weightsArr)) {
                    $weights = $weightsArr;
                }
            }
            // 目标期号（可选，用于验证历史预测成功率）
            $targetExpect = $this->request->get('target_expect', '', 'trim');
            // 回测期数（可选）
            $backtestCount = $this->request->get('backtest', 50, 'intval');
            if ($backtestCount < 10 || $backtestCount > 100) {
                $backtestCount = 50;
            }
            $result = $this->model->getPredictionV3($periods, $weights, $targetExpect, false, $backtestCount);
            if (isset($result['error'])) {
                $this->error($result['error']);
            }
            $this->success('查询成功', null, $result);
        }
    }

    /**
     * 权重网格搜索优化接口
     * 执行多权重配置回测，返回最优权重组合
     *
     * 参数说明:
     * - periods: 统计期数，范围50-500，默认200
     * - backtest: 回测期数，范围10-100，默认30
     * - timeout: 超时秒数，范围10-120，默认60
     *
     * 返回说明:
     * - best_weights: 最优权重配置
     * - best_hit_rate: 最优配置命中率
     * - all_results: 所有配置测试结果
     * - timed_out: 是否超时中断
     */
    public function optimizeWeights()
    {
        if ($this->request->isAjax()) {
            // 参数验证
            $periods = $this->request->get('periods', 200, 'intval');
            if ($periods < 50 || $periods > 500) {
                $this->error('期数范围必须在 50-500 之间');
            }

            $backtestCount = $this->request->get('backtest', 30, 'intval');
            if ($backtestCount < 10 || $backtestCount > 100) {
                $backtestCount = 30; // 使用默认值而非报错
            }

            $timeoutSeconds = $this->request->get('timeout', 60, 'intval');
            if ($timeoutSeconds < 10 || $timeoutSeconds > 120) {
                $timeoutSeconds = 60; // 使用默认值
            }

            // 执行优化
            $result = $this->model->_optimizeWeightsGridSearch($periods, $backtestCount, $timeoutSeconds);

            // 超时警告提示
            $message = '优化完成';
            if ($result['timed_out']) {
                $message = '优化超时中断，已完成' . count($result['all_results']) . '种配置测试';
            }

            $this->success($message, null, $result);
        }
    }

    /**
     * 基于正码关联规律的特码预测
     * 核心规律：
     * - 波色重复规律：90.67%特码波色与正码中某号码波色相同
     * - 距离规律：94.13%特码与最近正码距离<=10
     * - 区间覆盖规律：74.13%特码落在正码覆盖的区间
     * - 正码范围规律：70.67%特码在正码min-max之间
     */
    public function predictByNormalRelation()
    {
        if ($this->request->isAjax()) {
            $periods = $this->request->get('periods', 100, 'intval');
            if ($periods < 30 || $periods > 500) {
                $periods = 100;
            }
            $targetExpect = $this->request->get('target_expect', '', 'trim');
            $result = $this->model->getPredictionByNormalRelation($periods, $targetExpect);
            if (isset($result['error'])) {
                $this->error($result['error']);
            }
            $this->success('查询成功', null, $result);
        }
    }


}
