<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
namespace app\dice\model\reward;

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

/**
 * 奖励对照模型
 *
 * dice_reward 奖励对照表（主键 id 自增）
 * 唯一约束 (direction, grid_number)，保证每个点数、每个方向各一条；end_index 关联 DiceRewardConfig.id
 *
 * @property  $id 主键
 * @property  $tier 档位 T1-T5/BIGWIN
 * @property  $direction 方向:0=顺时针,1=逆时针
 * @property  $end_index 结束索引（DiceRewardConfig.id）
 * @property  $weight 权重 1-10000，档位内按权重比抽取
 * @property  $grid_number 色子点数(摇取值)
 * @property  $start_index 起始索引(DiceRewardConfig.id)
 * @property  $ui_text 显示文本(来自config)
 * @property  $real_ev 实际中奖金额(来自config)
 * @property  $remark 备注(来自config)
 * @property  $type 奖励类型(来自config)
 */
class DiceReward extends DiceModel
{
    /** 方向：顺时针 */
    public const DIRECTION_CLOCKWISE = 0;
    /** 方向：逆时针 */
    public const DIRECTION_COUNTERCLOCKWISE = 1;

    /** 缓存键前缀：奖励对照实例（按渠道分键） */
    private const CACHE_KEY_INSTANCE = 'dice:reward:instance';

    private const CACHE_TTL = 86400 * 30;

    private static ?array $instance = null;

    private static ?int $requestDeptId = null;

    protected $table = 'dice_reward';

    /** 主键 id 自增，唯一约束 (direction, grid_number) */
    protected $pk = 'id';

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

    private static function resolveDeptId(?int $deptId): int
    {
        if ($deptId !== null) {
            return AdminScopeHelper::normalizeRecordDeptId($deptId);
        }
        if (self::$requestDeptId !== null) {
            return self::$requestDeptId;
        }
        return AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
    }

    /**
     * 请求级设置当前渠道（一键测试 worker 内调用 simulateOnePlay 前设置）
     */
    public static function setRequestDeptId(?int $deptId): void
    {
        self::$requestDeptId = $deptId !== null
            ? AdminScopeHelper::normalizeRecordDeptId($deptId)
            : null;
    }

    /**
     * 获取奖励对照实例（按档位+方向索引，用于抽奖与权重配比）
     */
    public static function getCachedInstance(?int $deptId = null): array
    {
        $deptId = self::resolveDeptId($deptId);
        $cacheKey = self::cacheKeyForDept($deptId);
        $instance = Cache::get($cacheKey);
        if ($instance !== null && is_array($instance)) {
            self::$instance = $instance;
            return $instance;
        }
        if (self::$instance !== null && self::$requestDeptId === $deptId) {
            return self::$instance;
        }
        self::refreshCache($deptId);
        $instance = Cache::get($cacheKey);
        self::$instance = is_array($instance) ? $instance : self::buildEmptyInstance();
        return self::$instance;
    }

    /**
     * 按档位+方向取权重列表（用于抽奖：该档位该方向下 end_index => weight）
     * @return array<int, int> end_index => weight
     */
    public static function getCachedByTierAndDirection(string $tier, int $direction, ?int $deptId = null): array
    {
        $inst = self::getCachedInstance($deptId);
        $byTierDirection = $inst['by_tier_direction'] ?? [];
        $list = $byTierDirection[$tier][$direction] ?? [];
        $result = [];
        foreach ($list as $row) {
            $endIndex = isset($row['end_index']) ? (int) $row['end_index'] : 0;
            $weight = isset($row['weight']) ? (int) $row['weight'] : 1;
            $result[$endIndex] = $weight;
        }
        return $result;
    }

    /**
     * 按渠道从数据库加载并写入缓存
     */
    public static function refreshCache(?int $deptId = null): void
    {
        $deptId = self::resolveDeptId($deptId);
        $query = (new self())->order('tier')->order('direction')->order('end_index');
        ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
        $list = $query->select()->toArray();
        $byTierDirection = [];
        foreach ($list as $row) {
            $tier = isset($row['tier']) ? (string) $row['tier'] : '';
            $direction = isset($row['direction']) ? (int) $row['direction'] : 0;
            if ($tier !== '') {
                if (!isset($byTierDirection[$tier])) {
                    $byTierDirection[$tier] = [0 => [], 1 => []];
                }
                if (!isset($byTierDirection[$tier][$direction])) {
                    $byTierDirection[$tier][$direction] = [];
                }
                $byTierDirection[$tier][$direction][] = $row;
            }
        }
        $instance = [
            'list'              => $list,
            'by_tier_direction' => $byTierDirection,
        ];
        self::$instance = $instance;
        Cache::set(self::cacheKeyForDept($deptId), $instance, self::CACHE_TTL);
    }

    private static function buildEmptyInstance(): array
    {
        return [
            'list'              => [],
            'by_tier_direction' => [],
        ];
    }

    public static function clearRequestInstance(): void
    {
        self::$instance = null;
        self::$requestDeptId = 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);
    }
}
