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

use plugin\saiadmin\basic\think\BaseModel;
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 BaseModel
{
    /** 方向：顺时针 */
    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;

    protected $table = 'dice_reward';

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

    /**
     * 获取奖励对照实例（按档位+方向索引，用于抽奖与权重配比）
     * @return array{list: array, by_tier_direction: array}
     */
    public static function getCachedInstance(): array
    {
        if (self::$instance !== null) {
            return self::$instance;
        }
        $instance = Cache::get(self::CACHE_KEY_INSTANCE);
        if ($instance !== null && is_array($instance)) {
            self::$instance = $instance;
            return $instance;
        }
        self::refreshCache();
        $instance = Cache::get(self::CACHE_KEY_INSTANCE);
        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): array
    {
        $inst = self::getCachedInstance();
        $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(): void
    {
        $list = (new self())->order('tier')->order('direction')->order('end_index')->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;
            }
        }
        self::$instance = [
            'list'              => $list,
            'by_tier_direction' => $byTierDirection,
        ];
        Cache::set(self::CACHE_KEY_INSTANCE, self::$instance, self::CACHE_TTL);
    }

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

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

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

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

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