<?php

namespace app\admin\model;

use think\Model;

use app\admin\model\Num;


class History extends Model
{





    // 表名
    protected $name = 'history';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = false;

    // 定义时间戳字段名
    protected $createTime = false;
    protected $updateTime = false;
    protected $deleteTime = false;

    // 追加属性
    protected $append = [

    ];

    /**
     * 获取走势图数据
     * @param int $periods 查询最近多少期
     * @param string $type 查询类型 all=全部号码 special=仅特码
     * @return array {expects: [], data: [[num1,...], ...], colorMap: []}
     */
    public function getTrendData($periods = 30, $type = 'all')
    {
        // 查询波色映射
        $num_model = new Num();
        $colorMap = $num_model->column('color', 'num');

        $history = $this
            ->field('expect,num1,num2,num3,num4,num5,num6,num7,openTime')
            ->order('openTime', 'desc')
            ->limit($periods)
            ->select();

        if (empty($history)) {
            return ['expects' => [], 'data' => [], 'colorMap' => []];
        }

        $expects = [];
        $data = [];
        foreach ($history as $row) {
            $expects[] = (string)$row['expect'];
            if ($type === 'special') {
                $data[] = ['num7' => (int)$row['num7']];
            } else {
                $row_data = [];
                for ($i = 1; $i <= 7; $i++) {
                    $row_data['num' . $i] = (int)$row['num' . $i];
                }
                $data[] = $row_data;
            }
        }

        // 反转数组，使最远的数据在左边，最近的数据在右边（从左往右，从远到近）
        $expects = array_reverse($expects);
        $data = array_reverse($data);

        return [
            'expects' => $expects,
            'data' => $data,
            'colorMap' => $colorMap
        ];
    }

    /**
     * 获取冷热号码
     * @param int $periods 查询最近多少期
     * @param string $type 查询类型 all=全部号码 special=仅特码
     * @return array {hot: [], cold: [], all: []}
     */
    public function getHotColdNumbers($periods = 30, $type = 'all')
    {
        $num_model = new Num();
        $colorMap = $num_model->column('color', 'num');
        $animalMap = $num_model->column('animal', 'num');

        $history = $this
            ->field('expect,num1,num2,num3,num4,num5,num6,num7,openTime')
            ->order('openTime', 'desc')
            ->limit($periods)
            ->select();

        if (empty($history)) {
            return ['hot' => [], 'cold' => [], 'all' => []];
        }

        $fields = ($type === 'special') ? ['num7'] : ['num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7'];

        // 统计每个号码的出现次数
        $count = array_fill(1, 49, 0);
        $totalAppearances = 0;
        foreach ($history as $row) {
            foreach ($fields as $field) {
                $num = (int)$row[$field];
                if ($num >= 1 && $num <= 49) {
                    $count[$num]++;
                    $totalAppearances++;
                }
            }
        }

        $all = [];
        for ($num = 1; $num <= 49; $num++) {
            $percent = $totalAppearances > 0 ? round($count[$num] / $totalAppearances * 100, 1) : 0;
            $all[] = [
                'num' => $num,
                'count' => $count[$num],
                'percent' => $percent,
                'color' => $colorMap[$num] ?? '—',
                'animal' => $animalMap[$num] ?? '—'
            ];
        }

        // 按出现次数降序排序
        $sorted = $all;
        usort($sorted, function ($a, $b) {
            return $b['count'] - $a['count'];
        });

        // 热号: top 10, 冷号: bottom 10
        $hot = array_slice($sorted, 0, 10);
        $cold = array_slice($sorted, -10);
        $cold = array_reverse($cold);

        return ['hot' => $hot, 'cold' => $cold, 'all' => $all];
    }

    /**
     * 计算遗漏号码
     * @param int $periods 查询最近多少期
     * @param string $type 查询类型 all=全部号码 special=仅特码
     * @return array [{num: int, omit: int, color: string}, ...]
     */
    public function getMissingNumbers($periods = 10, $type = 'all')
    {
        // 查询最近 $periods 期开奖数据
        if ($type === 'special') {
            $history = $this
                ->field('expect,num7')
                ->order('openTime', 'desc')
                ->limit($periods)
                ->select();
        } else {
            $history = $this
                ->field('expect,num1,num2,num3,num4,num5,num6,num7')
                ->order('openTime', 'desc')
                ->limit($periods)
                ->select();
        }

        // 收集最近 $periods 期出现过的号码
        $appeared = [];
        foreach ($history as $row) {
            if ($type === 'special') {
                $fields = ['num7'];
            } else {
                $fields = ['num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7'];
            }
            foreach ($fields as $field) {
                if ($row[$field] !== null && $row[$field] !== '') {
                    $appeared[(int)$row[$field]] = true;
                }
            }
        }

        // 获取遗漏号码（1-49中未出现的）
        $missing = [];
        for ($num = 1; $num <= 49; $num++) {
            if (!isset($appeared[$num])) {
                $missing[] = $num;
            }
        }

        // 查询更多历史数据用于计算遗漏期数
        if ($type === 'special') {
            $allHistory = $this
                ->field('num7')
                ->order('openTime', 'desc')
                ->limit(500)
                ->select();
        } else {
            $allHistory = $this
                ->field('num1,num2,num3,num4,num5,num6,num7')
                ->order('openTime', 'desc')
                ->limit(500)
                ->select();
        }

        // 查询波色映射
        $num_model = new Num();
        $colorMap = $num_model->column('color', 'num');

        // 计算遗漏期数并组装结果
        $result = [];
        foreach ($missing as $num) {
            $omitCount = $this->calcOmitCount($num, $allHistory, $type);
            $result[] = [
                'num' => $num,
                'omit' => $omitCount,
                'color' => $colorMap[$num] ?? '—'
            ];
        }

        // 按遗漏期数降序排序
        usort($result, function ($a, $b) {
            return $b['omit'] - $a['omit'];
        });

        return $result;
    }

    /**
     * 计算某个号码的遗漏期数
     * @param int $num 号码
     * @param array $allHistory 历史数据（已按openTime DESC排序）
     * @param string $type 查询类型 all=全部号码 special=仅特码
     * @return int 遗漏期数
     */
    private function calcOmitCount($num, $allHistory, $type = 'all')
    {
        foreach ($allHistory as $idx => $row) {
            if ($type === 'special') {
                if ((int)$row['num7'] === $num) {
                    return $idx;
                }
            } else {
                for ($i = 1; $i <= 7; $i++) {
                    if ((int)$row['num' . $i] === $num) {
                        return $idx;
                    }
                }
            }
        }
        return count($allHistory);
    }

    /**
     * 波色分析
     */
    public function getColorWaveAnalysis($periods = 30, $type = 'all')
    {
        $num_model = new Num();
        $colorMap = $num_model->column('color', 'num');

        $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['red' => 0, 'blue' => 0, 'green' => 0, 'red_pct' => 0, 'blue_pct' => 0, 'green_pct' => 0, 'details' => []];

        $fields = ($type === 'special') ? ['num7'] : ['num1','num2','num3','num4','num5','num6','num7'];
        $colors = ['红' => 0, '蓝' => 0, '绿' => 0];
        $total = 0;
        foreach ($history as $row) {
            foreach ($fields as $f) {
                $num = (int)$row[$f];
                $color = $colorMap[$num] ?? '';
                if (strpos($color, '红') !== false) { $colors['红']++; $total++; }
                elseif (strpos($color, '蓝') !== false) { $colors['蓝']++; $total++; }
                elseif (strpos($color, '绿') !== false) { $colors['绿']++; $total++; }
            }
        }
        return [
            'red' => $colors['红'], 'blue' => $colors['蓝'], 'green' => $colors['绿'],
            'red_pct' => $total ? round($colors['红']/$total*100,1) : 0,
            'blue_pct' => $total ? round($colors['蓝']/$total*100,1) : 0,
            'green_pct' => $total ? round($colors['绿']/$total*100,1) : 0,
            'total' => $total
        ];
    }

    /**
     * 生肖分析
     */
    public function getZodiacAnalysis($periods = 30, $type = 'all')
    {
        $num_model = new Num();
        $animalMap = $num_model->column('animal', 'num');
        $colorMap = $num_model->column('color', 'num');

        $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['list' => []];

        $fields = ($type === 'special') ? ['num7'] : ['num1','num2','num3','num4','num5','num6','num7'];
        $counts = [];
        foreach ($history as $row) {
            foreach ($fields as $f) {
                $num = (int)$row[$f];
                $animal = $animalMap[$num] ?? '未知';
                if (!isset($counts[$animal])) $counts[$animal] = ['animal' => $animal, 'count' => 0, 'color' => $colorMap[$num] ?? '—'];
                $counts[$animal]['count']++;
            }
        }
        $list = array_values($counts);
        usort($list, function ($a, $b) { return $b['count'] - $a['count']; });
        $total = array_sum(array_column($list, 'count'));
        foreach ($list as &$item) { $item['percent'] = $total ? round($item['count']/$total*100, 1) : 0; }
        return ['list' => $list];
    }

    /**
     * 奇偶分析
     */
    public function getOddEvenAnalysis($periods = 30, $type = 'all')
    {
        $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['odd' => 0, 'even' => 0, 'odd_pct' => 0, 'even_pct' => 0, 'per_period' => []];

        $fields = ($type === 'special') ? ['num7'] : ['num1','num2','num3','num4','num5','num6','num7'];
        $odd = 0; $even = 0; $perPeriod = [];
        foreach ($history as $row) {
            $p_odd = 0; $p_even = 0;
            foreach ($fields as $f) {
                $num = (int)$row[$f];
                if ($num % 2 == 0) { $even++; $p_even++; } else { $odd++; $p_odd++; }
            }
            $perPeriod[] = ['expect' => $row['expect'], 'odd' => $p_odd, 'even' => $p_even];
        }
        $total = $odd + $even;
        return [
            'odd' => $odd, 'even' => $even,
            'odd_pct' => $total ? round($odd/$total*100, 1) : 0,
            'even_pct' => $total ? round($even/$total*100, 1) : 0,
            'per_period' => $perPeriod
        ];
    }

    /**
     * 大小分析（1-24为小，25-49为大）
     */
    public function getBigSmallAnalysis($periods = 30, $type = 'all')
    {
        $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['big' => 0, 'small' => 0, 'big_pct' => 0, 'small_pct' => 0, 'per_period' => []];

        $fields = ($type === 'special') ? ['num7'] : ['num1','num2','num3','num4','num5','num6','num7'];
        $big = 0; $small = 0; $perPeriod = [];
        foreach ($history as $row) {
            $p_big = 0; $p_small = 0;
            foreach ($fields as $f) {
                $num = (int)$row[$f];
                if ($num >= 25) { $big++; $p_big++; } else { $small++; $p_small++; }
            }
            $perPeriod[] = ['expect' => $row['expect'], 'big' => $p_big, 'small' => $p_small];
        }
        $total = $big + $small;
        return [
            'big' => $big, 'small' => $small,
            'big_pct' => $total ? round($big/$total*100, 1) : 0,
            'small_pct' => $total ? round($small/$total*100, 1) : 0,
            'per_period' => $perPeriod
        ];
    }

    /**
     * 特码走势
     */
    public function getSpecialTrend($periods = 30)
    {
        $num_model = new Num();
        $colorMap = $num_model->column('color', 'num');

        // 先取最近 $periods 条数据
        $history = $this->field('expect,num7,openTime')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['expects' => [], 'specials' => [], 'colors' => []];

        // 反转，使数据从左到右为从远到近
        $history = array_reverse($history);
        $expects = []; $specials = []; $colors = [];
        foreach ($history as $row) {
            $expects[] = (string)$row['expect'];
            $num = (int)$row['num7'];
            $specials[] = $num;
            $colors[] = $colorMap[$num] ?? '';
        }
        return ['expects' => $expects, 'specials' => $specials, 'colors' => $colors];
    }

    /**
     * 连号分析
     */
    public function getConsecutiveNumbers($periods = 30)
    {
        $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['pairs' => [], 'triples' => []];

        $pairCount = []; $tripleCount = [];
        foreach ($history as $row) {
            $nums = [];
            for ($i = 1; $i <= 7; $i++) $nums[] = (int)$row['num' . $i];
            sort($nums);
            // 找连号对
            for ($i = 0; $i < count($nums) - 1; $i++) {
                if ($nums[$i + 1] - $nums[$i] === 1) {
                    $pair = $nums[$i] . '-' . $nums[$i + 1];
                    $pairCount[$pair] = isset($pairCount[$pair]) ? $pairCount[$pair] + 1 : 1;
                }
            }
            // 找连号三连
            for ($i = 0; $i < count($nums) - 2; $i++) {
                if ($nums[$i + 1] - $nums[$i] === 1 && $nums[$i + 2] - $nums[$i + 1] === 1) {
                    $triple = $nums[$i] . '-' . $nums[$i + 1] . '-' . $nums[$i + 2];
                    $tripleCount[$triple] = isset($tripleCount[$triple]) ? $tripleCount[$triple] + 1 : 1;
                }
            }
        }
        arsort($pairCount); arsort($tripleCount);
        return ['pairs' => $pairCount, 'triples' => $tripleCount];
    }

    /**
     * 尾数分析
     */
    public function getTailNumbers($periods = 30, $type = 'all')
    {
        $num_model = new Num();
        $colorMap = $num_model->column('color', 'num');
        $animalMap = $num_model->column('animal', 'num');

        $history = $this->field('expect,num1,num2,num3,num4,num5,num6,num7')->order('openTime', 'desc')->limit($periods)->select();
        if (empty($history)) return ['tails' => [], 'all' => []];

        $fields = ($type === 'special') ? ['num7'] : ['num1','num2','num3','num4','num5','num6','num7'];
        $tailCount = array_fill(0, 10, 0);
        $all = [];
        foreach ($history as $row) {
            foreach ($fields as $f) {
                $num = (int)$row[$f];
                $tail = $num % 10;
                $tailCount[$tail]++;
            }
        }
        $total = array_sum($tailCount);
        for ($t = 0; $t <= 9; $t++) {
            $all[] = ['tail' => $t, 'count' => $tailCount[$t], 'percent' => $total ? round($tailCount[$t]/$total*100, 1) : 0];
        }
        usort($all, function ($a, $b) { return $b['count'] - $a['count']; });
        return ['all' => $all];
    }

    /**
     * 综合统计面板
     */
    public function getDashboardData($periods = 30, $type = 'all')
    {
        return [
            'hotcold' => $this->getHotColdNumbers($periods, $type),
            'colorwave' => $this->getColorWaveAnalysis($periods, $type),
            'zodiac' => $this->getZodiacAnalysis($periods, $type),
            'oddeven' => $this->getOddEvenAnalysis($periods, $type),
            'bigsmall' => $this->getBigSmallAnalysis($periods, $type),
            'special' => $this->getSpecialTrend($periods),
            'tailnumbers' => $this->getTailNumbers($periods, $type)
        ];
    }


}
