<?php

require_once __DIR__ . '/Activity/ActInterface.php';
$actModelDir = __DIR__ . '/Activity';
$dh = opendir($actModelDir);
while ($file = readdir($dh)) {
    if (in_array($file, ['.', '..'])) continue;
    require_once __DIR__ . '/Activity/' . $file;
}

class ActBaseModel
{
    const ACT_LIST = [
        SURPRISE_CARD,
        MAYA_WHEEL,
        TAROT,
        CLUB_FARM,
        TRAFFIC_PERMIT,
        LUCKY_DICE,
        COIN_PUSH_MANIA,
        SURPRISE_COLLECT,
        JACKPOT,
    ];

    static $actGroupMapping = [];
    static $multiNumTypeReward = [
        '随机金卡',
        '随机黑金卡',
        '随机限时金卡',
        '随机限时黑金卡',
        '金币'
    ];
    static $rewardNames = [
        "木质宝箱" => 1,
        "白银宝箱" => 2,
        "黄金宝箱" => 3,
        "魔幻宝箱" => 4,
        "宠物经验" => 8,
        "宠物食物" => 9,
        "随机金卡" => 13,
        "金币" => 14,
        "体力" => 15,
        "小丑卡" => 18,
        "通行证经验" => 38,
        "拼图碎片" => 44,
        "玛雅转盘代币" => 45,

        "随机黑金卡" => 48,
        "随机限时金卡" => 49,
        "随机限时黑金卡" => 50,
        "幸运狐狸代币" => 51,
        "超级扭蛋代币" => 60,
        "随机工会表情" => 61,
        "随机公会表情" => 61,
        "皮纳塔代币" => 62,
        "幸运旅途代币" => 65,
        "塔罗牌代币" => 70,
        "推币机代币"  =>72,

    ];
    static $needSkinRewards = [
        "皮肤宝箱" => 19,
        "头像框" => 23,
        "建筑大师活动" => 25,
        "气球活动" => 26,
        "体力加速活动" => 27,
        "金币大爆炸活动" => 28,
        "疯狂加倍" => 31,
        "建筑打折" => 32,
        "卡片爆炸" => 33,
        "商场优惠" => 34,
        "超级收集活动" => 35,
        "超级气球活动" => 36,
        "首冲优惠" => 37,
        "通行证倍率活动" => 39,
        "收集翻倍活动" => 40,
        "四选一活动" => 41,
        "金币老虎机活动" => 43,
        "疯狂的卡组" => 46,


        "疯狂建造活动" => 52,
        "超级炸弹活动" => 53,
        "回归签到" => 54,
        "完美偷袭活动" => 55,
        "小丑卡保底值" => 56,
        "完美打活动" => 57,
        "皮肤宝箱最大体力" => 58,
        "richking最大金币" => 59,
        "四选一活动-农场大冒险" => 63,
        "限次数建造打折" => 64,
        "幸运骰子活动券" => 71,
    ];

    static $actModels = [];

    protected $goodSku;

    function __construct()
    {
        $this->goodSku = oo::cfg('sku');
    }

    static function getActModel(string $actType): ActInterface
    {
        if (isset(self::$actModels[$actType]) && self::$actModels[$actType] instanceof ActInterface) return self::$actModels[$actType];
        switch ($actType) {
            case SURPRISE_CARD:
                self::$actModels[$actType] = new SurpriseCardActModel();
                break;
            case MAYA_WHEEL:
                self::$actModels[$actType] = new MayaActModel();
                break;
            case TAROT:
                self::$actModels[$actType] = new TarotActModel();
                break;
            case CLUB_FARM:
                self::$actModels[$actType] = new ClubFarmActModel();
                break;
            case TRAFFIC_PERMIT:
                self::$actModels[$actType] = new TrafficPermitActModel();
                break;
            case LUCKY_DICE:
                self::$actModels[$actType] = new LuckDiceActModel();
                break;
            case COIN_PUSH_MANIA:
                self::$actModels[$actType] = new CoinPushManiaActModel();
                break;
            case SURPRISE_COLLECT:
                self::$actModels[$actType] = new SurpriseCollectModel();
                break;
            case JACKPOT:
                self::$actModels[$actType] = new JackpotActModel();
                break;
            default:
                self::response(__LINE__, "活动类型model不存在：" . $actType);
        }
        return self::$actModels[$actType];
    }

    static function response($ret = 0, $msg = '', array $data = array(), $type = false): string
    {
        header('Content-type:text/json');
        $result = [
            'ret' => $ret,
            'msg' => $msg,
            'data' => $data,
            'state' => $ret ? "error" : 'success'
        ];
        if ($type) {
            die(json_encode($result));
        } else {
            die(json_encode($result, JSON_NUMERIC_CHECK));
        }
        return '';
    }

    // 解析三层映射关系 等级 => 体力 => 数数分组 3层嵌套
    public function parseLvSpinsShushuStagesMapping(array $stagesMappingArray): array
    {
        $rewardsConfig = $idxMapping = [];

        foreach ($stagesMappingArray as $k => $item) {
            if (empty($k)) continue;
            list($idx, $lvMin, $lvMax, $spinsMin, $spinsMax, $ssGroup) = $item;
            $lvKey = "{$lvMin}-$lvMax";
            $spinsKey = "{$spinsMin}-{$spinsMax}";

            $lvIdx = $this->getGroupMappingIdx(CONDITION_TYPE_LV, $lvKey);
            $spinsIdx = $this->getGroupMappingIdx(CONDITION_TYPE_SPINS, $spinsKey, $lvIdx);
            $ssIdx = $this->getGroupMappingIdx(CONDITION_TYPE_SHUSHU, $ssGroup, "{$spinsIdx}_{$lvIdx}");

            if (empty($rewardsConfig[$lvIdx]))
                $rewardsConfig[$lvIdx] = [
                    'stages' => [],
                    'lvStart' => $lvMin,
                    'lvEnd' => $lvMax,
                    'start' => $lvMin,
                    'end' => $lvMax,
                ];
            if (empty($rewardsConfig[$lvIdx]['stages'][$spinsIdx]))
                $rewardsConfig[$lvIdx]['stages'][$spinsIdx] = [
                    'stages' => [],
                    'spinsStart' => $spinsMin,
                    'spinsEnd' => $spinsMax,
                    'start' => $spinsMin,
                    'end' => $spinsMax,
                ];

            $shushus = $this->parseShushuGroups($ssGroup);
            if (empty($rewardsConfig[$lvIdx]['stages'][$spinsIdx]['stages'][$ssIdx]))
                $rewardsConfig[$lvIdx]['stages'][$spinsIdx]['stages'][$ssIdx] = [
                    'stages' => [],
                    'shushu' => $shushus,
                ];


            $idxMapping[$idx] = [$lvIdx, $spinsIdx, $ssIdx];
        }


        return [$rewardsConfig, $idxMapping];
    }

    public function parseLvCoinYShushuStagesMapping(array $stagesMappingArray): array
    {
        $rewardsConfig = $idxMapping = [];

        foreach ($stagesMappingArray as $k => $item) {
            if (empty($k)) continue;
            list($idx, $lvMin, $lvMax, $coinsyMin, $coinsyMax, $ssGroup) = $item;
            $lvKey = "{$lvMin}-$lvMax";
            $coinsyKey = "{$coinsyMin}-{$coinsyMax}";

            $lvIdx = $this->getGroupMappingIdx(CONDITION_TYPE_LV, $lvKey);
            $coinsyIdx = $this->getGroupMappingIdx(CONDITION_TYPE_COIN_Y, $coinsyKey, $lvIdx);
            $ssIdx = $this->getGroupMappingIdx(CONDITION_TYPE_SHUSHU, $ssGroup, "{$coinsyIdx}_{$lvIdx}");

            if (empty($rewardsConfig[$lvIdx]))
                $rewardsConfig[$lvIdx] = [
                    'stages' => [],
                    'lvStart' => $lvMin,
                    'lvEnd' => $lvMax,
                    'start' => $lvMin,
                    'end' => $lvMax,
                ];
            if (empty($rewardsConfig[$lvIdx]['stages'][$coinsyIdx]))
                $rewardsConfig[$lvIdx]['stages'][$coinsyIdx] = [
                    'stages' => [],
                    'coinsyStart' => $coinsyMin,
                    'coinsyEnd' => $coinsyMax,
                    'start' => $coinsyMin,
                    'end' => $coinsyMax,
                ];

            $shushus = $this->parseShushuGroups($ssGroup);
            if (empty($rewardsConfig[$lvIdx]['stages'][$coinsyIdx]['stages'][$ssIdx]))
                $rewardsConfig[$lvIdx]['stages'][$coinsyIdx]['stages'][$ssIdx] = [
                    'stages' => [],
                    'shushu' => $shushus,
                ];


            $idxMapping[$idx] = [$lvIdx, $coinsyIdx, $ssIdx];
        }


        return [$rewardsConfig, $idxMapping];
    }

    // 解析两层映射关系 等级 => 体力 2层嵌套
    public function parseLvSpinsStagesMapping(array $stagesMappingArray): array
    {
        $rewardsConfig = $idxMapping = [];

        for ($i = 1; $i < count($stagesMappingArray); $i++) {
            $item = $stagesMappingArray[$i];
            if (empty(array_filter($item))) continue;

            list($idx, $lvMin, $lvMax, $spinsMin, $spinsMax) = $item;
            $lvKey = "{$lvMin}-$lvMax";
            $spinsKey = "{$spinsMin}-{$spinsMax}";
            $lvIdx = $this->getGroupMappingIdx(CONDITION_TYPE_LV, $lvKey);
            $spinsIdx = $this->getGroupMappingIdx(CONDITION_TYPE_SPINS, $spinsKey, $lvIdx);

            if (empty($rewardsConfig[$lvIdx]))
                $rewardsConfig[$lvIdx] = [
                    'stages' => [],
                    'lvStart' => $lvMin,
                    'lvEnd' => $lvMax,
                    'start' => $lvMin,
                    'end' => $lvMax,
                ];
            if (empty($rewardsConfig[$lvIdx]['stages'][$spinsIdx]))
                $rewardsConfig[$lvIdx]['stages'][$spinsIdx] = [
                    'stages' => [],
                    'spinsStart' => $spinsMin,
                    'spinsEnd' => $spinsMax,
                    'start' => $spinsMin,
                    'end' => $spinsMax,
                ];

            $idxMapping[$idx] = [$lvIdx, $spinsIdx];
        }

        return [$rewardsConfig, $idxMapping];
    }

    public function parseLvStagesMapping(array $stagesMappingArray): array
    {
        $rewardsConfig = $idxMapping = [];
        for ($i = 1; $i < count($stagesMappingArray); $i++) {
            $item = $stagesMappingArray[$i];
            if (empty(array_filter($item))) continue;

            list($idx, $lvMin, $lvMax) = $item;
            $lvKey = "{$lvMin}-$lvMax";
            $lvIdx = $this->getGroupMappingIdx(CONDITION_TYPE_LV, $lvKey);

            if (empty($rewardsConfig[$lvIdx]))
                $rewardsConfig[$lvIdx] = [
                    'stages' => [],
                    'lvStart' => $lvMin,
                    'lvEnd' => $lvMax,
                    'start' => $lvMin,
                    'end' => $lvMax,
                ];

            $idxMapping[$idx] = [$lvIdx];
        }

        return [$rewardsConfig, $idxMapping];
    }

    // 解析两层映射关系 等级 => 数数分组 2层嵌套
    public function parseLvShushuStagesMapping(array $stagesMappingArray): array
    {
        $rewardsConfig = $idxMapping = [];

        for ($i = 1; $i < count($stagesMappingArray); $i++) {
            $item = $stagesMappingArray[$i];
            if (empty(array_filter($item))) continue;

            list($idx, $lvMin, $lvMax, $shushuGroups) = $item;
            $lvKey = "{$lvMin}-$lvMax";
            $lvIdx = $this->getGroupMappingIdx(CONDITION_TYPE_LV, $lvKey);
            $ssIdx = $this->getGroupMappingIdx(CONDITION_TYPE_SHUSHU, $shushuGroups, $lvIdx);

            if (empty($rewardsConfig[$lvIdx]))
                $rewardsConfig[$lvIdx] = [
                    'stages' => [],
                    'lvStart' => $lvMin,
                    'lvEnd' => $lvMax,
                    'start' => $lvMin,
                    'end' => $lvMax,
                ];
            if (empty($rewardsConfig[$lvIdx]['stages'][$ssIdx]))
                $rewardsConfig[$lvIdx]['stages'][$ssIdx] = [
                    'stages' => [],
                    'shushu' => $this->parseShushuGroups($shushuGroups),
                ];

            $idxMapping[$idx] = [$lvIdx, $ssIdx];
        }

        return [$rewardsConfig, $idxMapping];
    }


    # 通过奖励名 解析奖励类型以及皮肤id
    public function parseRewardTypeAndSkinId($rewardName, $line = 0)
    {
        #常规奖励 无皮肤
        if (!empty(self::$rewardNames[$rewardName])) {
            return [self::$rewardNames[$rewardName], ''];
        }
        $prizeList = oo::commonOprModel('config')->getPropsConfigFromLocal();
        foreach ($prizeList as $item) {
            if (empty($item['skinList'])) continue;
            foreach ($item['skinList'] as $skinItem) {
                if ($skinItem['name'] == $rewardName && !empty(self::$needSkinRewards[$item['name']])) {
                    return [self::$needSkinRewards[$item['name']], $skinItem['id']];
                }
            }
        }
        #判断奖励是否存在
        self::response(-1, "第{$line}行,奖励或皮肤不存在:'{$rewardName}'", $prizeList);
    }

    # 通过分组名，解析分组id
    public function parseShushuGroups($shushuGroups, $line = 0)
    {
        if (empty($shushuGroups)) self::response(-1, $line . '行，数数分组为空');
        if (is_string($shushuGroups)) {
            $shushuGroups = strtr($shushuGroups, ['，' => ',']);
            $shushuGroups = explode(',', $shushuGroups);
        }
        $allGroups = array_column(oo::commonOprModel('config')->getUserGroupConfigByCid(5), 'name', 'id');
        $allGroups = oo::commonOprModel('config')->hideSSGroup($allGroups);;
        $shushuGroupIds = [];
        foreach ($shushuGroups as $shushuGroup) {
            if (!in_array($shushuGroup, $allGroups)) self::response(-1, "第{$line}行,数数分组不存在:'{$shushuGroup}'");
            $shushuGroupIds[] = array_search($shushuGroup, $allGroups);
        }
        return $shushuGroupIds;
    }

    # 通过虎机概率分组名，解析 老虎机概率分组id
    public function parseSlotWeightGroups(string $slotWeightGroupName, $line = 0): int
    {
        if (empty($slotWeightGroupName)) self::response(-1, $line . '行，老虎机概率分组为空');

        $groupsTbl = otable::slotWeightGroups();
        $groups = oo::commonOprDb('slavedb')->getOne("select * from {$groupsTbl} where `name`='{$slotWeightGroupName}'");
        if (empty($groups['id'])) self::response(-1, "第{$line}行,老虎机概率分组不存在:'{$slotWeightGroupName}'");
        return intval($groups['id']);
    }

    # 解析分层映射的每层idx
    public function getGroupMappingIdx($type, $val, $parentsKey = 0)
    {
        self::$actGroupMapping[$type] = self::$actGroupMapping[$type] ?? [];
        self::$actGroupMapping[$type][$parentsKey] = self::$actGroupMapping[$type][$parentsKey] ?? [];
        if (empty(self::$actGroupMapping[$type][$parentsKey][$val])) {
            self::$actGroupMapping[$type][$parentsKey][$val] = count(self::$actGroupMapping[$type][$parentsKey]) + 1;
        }
        return intval(self::$actGroupMapping[$type][$parentsKey][$val]);
    }

    # 解析一行奖励
    public function parseLineRewards(array $rewards, $line = 0)
    {
        $rewardsTemp = [];
        $i = 0;
        while ($i < count($rewards)) {
            $reward = $rewards[$i++];
            $isFixNum = $rewards[$i++];
            $rewardNum = intval($rewards[$i++]);
            if (!empty($reward)) {
                if (!in_array($reward, self::$multiNumTypeReward)) $isFixNum = '是';   #非金币奖励，全部固定值奖励
                $isFixNum = ($isFixNum == '是') ? 1 : 2;#固定值奖励 1 按等级取值 2
                list($type, $skin) = $this->parseRewardTypeAndSkinId($reward, $line);

                if (empty($rewardNum)) self::response(-1, "第{$line}行,奖励数为空", $rewards);
                $currentId = count($rewardsTemp) + 1;
                $rewardsTemp[] = [
                    'id' => $currentId,
                    "num" => $rewardNum,
                    "type" => $type,
                    "rtype" => $isFixNum,
                    "skin" => intval($skin)
                ];
            }
        }
        return $rewardsTemp;
    }

    # 解析是否 是 1 否 0
    public function parseYesOrNo($text)
    {
        return $text == '是' ? 1 : 0;
    }

    public function writeActCacheCommonLvSpinsShushu(array $actConfig, string $configColumn = 'reward_info'): bool
    {
        $conditionKeys = okeys::activityConditionKeys($actConfig['aid']);
        $stageRewardKeys = okeys::activityRewardsStageKeys($actConfig['aid']);
        $rewardInfo = json_decode($actConfig[$configColumn], true);
        foreach ($rewardInfo as $idx1 => $item1) {
            foreach ($item1['stages'] as $idx2 => $item2) {
                foreach ($item2['stages'] as $idx3 => $item3) {
                    $stageKey = "{$idx1}_{$idx2}_{$idx3}";
                    $stageConditions = $this->getStageConditionLvSpinsShushu($item1, $item2, $item3);
                    oo::commonOprRedis('games')->hset($conditionKeys, $stageKey, json_encode($stageConditions, JSON_NUMERIC_CHECK));
                    oo::commonOprRedis('games')->hset($stageRewardKeys, $stageKey, json_encode($item3, JSON_NUMERIC_CHECK));
                }
            }
        }

        $expireTime = max($actConfig['end_time'], time() + 60);#redis最少一分钟
        oo::commonOprRedis('games')->expireAt($conditionKeys, oo::redisRandomExpire($expireTime));
        oo::commonOprRedis('games')->expireAt($stageRewardKeys, oo::redisRandomExpire($expireTime));
        return true;
    }

    protected function getStageConditionLvSpinsShushu(array $lvItem, $spinsItem, $shushuItem): array
    {
        return [
            [
                "start" => $lvItem['lvStart'] ?? $lvItem['start'],
                "end" => $lvItem['lvEnd'] ?? $lvItem['end'],
                "shushu" => [],
                "type" => CONDITION_TYPE_LV
            ],
            [
                "start" => $spinsItem['spinsStart'] ?? $spinsItem['start'],
                "end" => $spinsItem['spinsEnd'] ?? $spinsItem['end'],
                "shushu" => [],
                "type" => CONDITION_TYPE_SPINS
            ],
            [
                "start" => 0,
                "end" => 0,
                "shushu" => $shushuItem['shushu'],
                "type" => CONDITION_TYPE_SHUSHU
            ],

        ];
    }

    protected function getStageConditionLvSpins(array $lvItem, $spinsItem): array
    {
        return [
            [
                "start" => $lvItem['lvStart'] ?? $lvItem['start'],
                "end" => $lvItem['lvEnd'] ?? $lvItem['end'],
                "shushu" => [],
                "type" => CONDITION_TYPE_LV
            ],
            [
                "start" => $spinsItem['spinsStart'] ?? $spinsItem['start'],
                "end" => $spinsItem['spinsEnd'] ?? $spinsItem['end'],
                "shushu" => [],
                "type" => CONDITION_TYPE_SPINS
            ]

        ];
    }

    //
    protected function getSkuByPrice($price, $allowedFree = false): string
    {
        foreach ($this->goodSku as $skuPrice) {
            if ($skuPrice['price'] == $price) {
                return $skuPrice['sku'];
            }
        }
        if ($allowedFree) return '';
        return $this->response(__LINE__, '价格配置价格：' . $price);
    }

    protected function saveTokenGoods(array &$actConfig, string $savedColumn)
    {
        foreach ($actConfig['tokenGoods'] as $k => $tokenGood) {
            $actConfig['tokenGoods'][$k] = $this->formatTokenGoods($actConfig['type'], $tokenGood);
        }
        $actConfig[$savedColumn] = $actConfig['tokenGoods'];
        unset($actConfig['tokenGoods']);
    }

    // 代币商品格式化
    protected function formatTokenGoods(string $actType, array $tokenGoods): array
    {
        switch ($actType) {
            case MAYA_WHEEL:
                $propId = 45;
                break;
            case LUCKY_FOX:
                $propId = 51;
                break;
            case SUPER_GASHAPON:
                $propId = 60;
                break;
            case PINATA:
                $propId = 62;
                break;
            case LUCKY_JOURNEY:
                $propId = 65;
                break;
            case TAROT:
                $propId = 70;
                break;
            default:
                self::response(__LINE__, '不支持代币弹窗的活动：' . $actType);
        }
        $goods = [
            'exceed' => $tokenGoods['exceed'],
            'goods' => []
        ];
        foreach ($tokenGoods['goods'] as $tokenGood) {
            $tokenGood['prize'] = [
                [
                    "id" => "1",
                    "rtype" => "1",
                    "num" => $tokenGood['tokenNum'],
                    "type" => $propId,
                ]
            ];
            $goods['goods'][] = $tokenGood;
        }
        return $goods;
    }

    // 代币商品格式化
    protected function formatTokenGoodsSheet(array &$actConfig, $noTokenConfigArray, $idxMapping)
    {
        $gtype = 0;
        switch ($actConfig['type']) {
            case MAYA_WHEEL:
                $gtype = 128;
                break;
            case LUCKY_FOX:
                $gtype = 126;
                break;
            case SUPER_GASHAPON:
                $gtype = 127;
                break;
            case PINATA:
                $gtype = 125;
                break;
            case LUCKY_JOURNEY:
                $gtype = 129;
                break;
            case TAROT:
                $gtype = 130;
                break;
            default:
                self::response(__LINE__, '不支持代币弹窗的活动：' . $actConfig['type']);
        }

        $tokenGoods = [];
        foreach ($noTokenConfigArray as $k => $item) {
            if (empty($k)) continue;
            if (empty(array_filter($item))) continue;
            @list($idx, $stage, $price, $discount, $tokenNum, $exceed) = $item;
            if (empty($idxMapping[$idx])) self::response(__LINE__, '索引id不存在：' . $idx);
            $stageKey = $this->getStageKey($idxMapping[$idx]);
            $tokenGoods[$stageKey] = $tokenGoods[$stageKey] ?? [
                'exceed' => $exceed,
                'goods' => [],
            ];
            $sku = $this->getSkuByPrice($price);
            $goodsLen = count($tokenGoods[$stageKey]['goods']);
            $tokenGoods[$stageKey]['goods'][$goodsLen] = [
                'id' => $goodsLen + 1,
                'gid' => $gtype * 10000 + $goodsLen,
                'price' => $price,
                'sku' => $sku,
                'gtype' => $gtype,
                'discount' => $discount,
                'tokenNum' => $tokenNum,
            ];
        }
        $actConfig['tokenGoods'] = $tokenGoods;
    }

    protected function getStageKey(array $idxMapping): string
    {
        $stageKey = '';
        foreach ($idxMapping as $k) {
            if (strlen($stageKey) == 0) $stageKey .= $k;
            else $stageKey .= '_' . $k;
        }
        return $stageKey;
    }

    public static function parseExtraBasicConfig($fieldMapping, $sheetData): array
    {
        $baseConfig = [];
        foreach ($sheetData as $line) {
            $configField = $fieldMapping[$line[0]];
            if (!empty($configField)) {
                $baseConfig[$configField] = $line[1];
            }
        }
        return $baseConfig;
    }

    public function getActBasicConfig(): array
    {
        return [];
    }

}