<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: your name
// +----------------------------------------------------------------------
namespace app\dice\model\reward_config;

use app\dice\helper\AdminScopeHelper;
use app\dice\helper\ConfigScopeEditHelper;
use app\dice\model\reward\DiceReward;
use app\dice\model\DiceModel;
use support\think\Cache;

/**
 * 奖励配置模型
 *
 * dice_reward_config 奖励配置；BIGWIN 档位使用本表 weight（0-10000，10000=100% 中大奖）
 *
 * @property  $id ID
 * @property  $grid_number 色子点数
 * @property  $ui_text 前端显示文本
 * @property  $ui_text_en 前端显示文本(英文)
 * @property  $real_ev 真实资金结算
 * @property  $tier 所属档位
 * @property  $weight 权重（仅 BIGWIN 使用，0-10000）
 * @property  $remark 备注
 * @property  $type 奖励类型 -2=唯一惩罚,-1=抽水,0=回本,1=再来一次,2=小赚,3=大奖格
 * @property  $create_time 创建时间
 * @property  $update_time 修改时间
 */
class DiceRewardConfig extends DiceModel
{
    /** 缓存键：彩金池奖励列表实例 */
    private const CACHE_KEY_INSTANCE = 'dice:reward_config:instance';

    private const CACHE_TTL = 86400 * 30;

    private static ?array $instance = null;

    protected $pk = 'id';

    protected $table = 'dice_reward_config';

    /**
     * 获取彩金池实例（含 list / by_tier / by_tier_grid），无则从库加载并写入缓存
     * 优先从共享缓存读取，保证多进程（如一键测试 worker）能拿到最新配置，与数据库一致
     * @return array{list: array, by_tier: array, by_tier_grid: array, min_real_ev: float}
     */
    public static function getCachedInstance(?int $deptId = null): array
    {
        if ($deptId === null) {
            $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
        }
        $cacheKey = self::cacheKeyForDept($deptId);
        $instance = Cache::get($cacheKey);
        if ($instance !== null && is_array($instance)) {
            return $instance;
        }
        self::refreshCache($deptId);
        $instance = Cache::get($cacheKey);
        return is_array($instance) ? $instance : self::buildEmptyInstance();
    }

    private static function cacheKeyForDept(int $deptId): string
    {
        return self::CACHE_KEY_INSTANCE . ':' . $deptId;
    }

    public static function getCachedList(?int $deptId = null): array
    {
        $inst = self::getCachedInstance($deptId);
        return $inst['list'] ?? [];
    }

    public static function getCachedById(int $id, ?int $deptId = null): ?array
    {
        $list = self::getCachedList($deptId);
        foreach ($list as $row) {
            if (isset($row['id']) && (int) $row['id'] === $id) {
                return $row;
            }
        }
        return null;
    }

    /**
     * 按渠道从数据库加载并写入缓存（避免多渠道配置混在同一缓存键）
     */
    public static function refreshCache(?int $deptId = null): void
    {
        if ($deptId === null) {
            $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
        }
        $query = (new self())->order('id', 'asc');
        ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
        $list = $query->select()->toArray();
        $byTier = [];
        $byTierGrid = [];
        foreach ($list as $row) {
            $tier = isset($row['tier']) ? (string) $row['tier'] : '';
            if ($tier !== '') {
                if (!isset($byTier[$tier])) {
                    $byTier[$tier] = [];
                }
                $byTier[$tier][] = $row;
                $gridNum = isset($row['grid_number']) ? (int) $row['grid_number'] : 0;
                if (!isset($byTierGrid[$tier])) {
                    $byTierGrid[$tier] = [];
                }
                if (!isset($byTierGrid[$tier][$gridNum])) {
                    $byTierGrid[$tier][$gridNum] = $row;
                }
            }
        }
        $minRealEv = empty($list) ? 0.0 : (float) min(array_column($list, 'real_ev'));
        $instance = [
            'list'         => $list,
            'by_tier'      => $byTier,
            'by_tier_grid' => $byTierGrid,
            'min_real_ev'  => $minRealEv,
        ];
        Cache::set(self::cacheKeyForDept($deptId), $instance, self::CACHE_TTL);
        if ($deptId === AdminScopeHelper::DEFAULT_TEMPLATE_DEPT) {
            self::$instance = $instance;
        }
    }

    private static function buildEmptyInstance(): array
    {
        return [
            'list'         => [],
            'by_tier'      => [],
            'by_tier_grid' => [],
            'min_real_ev'  => 0.0,
        ];
    }

    /**
     * 按档位+色子点数取一条（用于 BIGWIN）
     */
    public static function getCachedByTierAndGridNumber(string $tier, int $gridNumber, ?int $deptId = null): ?array
    {
        $inst = self::getCachedInstance($deptId);
        $byTierGrid = $inst['by_tier_grid'] ?? [];
        $tierData = $byTierGrid[$tier] ?? [];
        $row = $tierData[$gridNumber] ?? null;
        return is_array($row) ? $row : null;
    }

    public static function getCachedMinRealEv(): float
    {
        $inst = self::getCachedInstance();
        return (float) ($inst['min_real_ev'] ?? 0.0);
    }

    /**
     * 从缓存按档位取奖励列表（不含权重，仅配置）
     */
    public static function getCachedByTier(string $tier, ?int $deptId = null): array
    {
        $inst = self::getCachedInstance($deptId);
        $byTier = $inst['by_tier'] ?? [];
        return $byTier[$tier] ?? [];
    }

    /**
     * 按档位+方向取奖励列表（合并 dice_reward 权重，用于抽奖）
     * @param int $direction 0=顺时针, 1=逆时针
     * @return array 每行含 id, grid_number, real_ev, tier, weight 等
     */
    public static function getCachedByTierForDirection(string $tier, int $direction, ?int $deptId = null): array
    {
        $list = self::getCachedByTier($tier, $deptId);
        $weightMap = DiceReward::getCachedByTierAndDirection($tier, $direction, $deptId);
        foreach ($list as $i => $row) {
            $id = isset($row['id']) ? (int) $row['id'] : 0;
            $list[$i]['weight'] = $weightMap[$id] ?? 1;
        }
        return $list;
    }

    public static function clearRequestInstance(): void
    {
        self::$instance = null;
    }

    private static function refreshCacheForModel($model): void
    {
        $deptId = AdminScopeHelper::normalizeRecordDeptId(
            is_array($model) ? ($model['dept_id'] ?? null) : ($model->dept_id ?? null)
        );
        self::refreshCache($deptId);
    }

    public static function onAfterInsert($model): void
    {
        self::refreshCacheForModel($model);
    }

    public static function onAfterUpdate($model): void
    {
        self::refreshCacheForModel($model);
    }

    public static function onAfterDelete($model): void
    {
        self::refreshCacheForModel($model);
    }

    public function searchGridNumberMinAttr($query, $value)
    {
        if ($value !== '' && $value !== null) {
            $query->where('grid_number', '>=', $value);
        }
    }

    public function searchGridNumberMaxAttr($query, $value)
    {
        if ($value !== '' && $value !== null) {
            $query->where('grid_number', '<=', $value);
        }
    }

    public function searchUiTextAttr($query, $value)
    {
        if ($value !== '' && $value !== null) {
            $query->where('ui_text', 'like', '%' . $value . '%');
        }
    }

    public function searchRealEvMinAttr($query, $value)
    {
        if ($value !== '' && $value !== null) {
            $query->where('real_ev', '>=', $value);
        }
    }

    public function searchRealEvMaxAttr($query, $value)
    {
        if ($value !== '' && $value !== null) {
            $query->where('real_ev', '<=', $value);
        }
    }

    public function searchTierAttr($query, $value)
    {
        if ($value !== '' && $value !== null) {
            $query->where('tier', '=', $value);
        }
    }
}
