<?php
declare(strict_types=1);

namespace app\api\logic;

use app\api\cache\UserCache;
use app\dice\model\player\DicePlayer;
use app\dice\model\player_ticket_record\DicePlayerTicketRecord;
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
use plugin\saiadmin\exception\ApiException;
use support\think\Db;

/**
 * 购买抽奖券套餐：次数 => [消耗coin, 购买次数paid, 赠送次数free]
 * 仅支持 1、5、10 档
 */
class GameLogic
{
    public const PACKAGES = [
        1  => ['coin' => 1,  'paid' => 1,  'free' => 0],   // 1次/1coin
        5  => ['coin' => 5,  'paid' => 5,  'free' => 1],   // 5张/5coin（5购买+1赠送，共6次）
        10 => ['coin' => 10, 'paid' => 10, 'free' => 3],   // 10张/10coin（10购买+3赠送，共13次）
    ];

    /** 钱包流水类型：购买抽奖次数 */
    public const WALLET_TYPE_BUY_DRAW = 2;

    /**
     * 购买抽奖券
     * 先更新 Redis 玩家信息（后续游玩从 Redis 读），再用事务更新数据库；事务失败则回滚 Redis
     * @param int $playerId 玩家ID
     * @param int $count 购买档位：1 / 5 / 10
     * @return array 更新后的 coin, total_ticket_count, paid_ticket_count, free_ticket_count
     */
    public function buyLotteryTickets(int $playerId, int $count): array
    {
        if (!isset(self::PACKAGES[$count])) {
            throw new ApiException('Invalid lottery ticket purchase');
        }
        $pack = self::PACKAGES[$count];
        $cost = $pack['coin'];
        $addPaid = $pack['paid'];
        $addFree = $pack['free'];
        $addTotal = $addPaid + $addFree;

        $player = DicePlayer::find($playerId);
        if (!$player) {
            throw new ApiException('User not found');
        }
        $coinBefore = (float) $player->coin;
        if ($coinBefore < $cost) {
            throw new ApiException('Insufficient balance');
        }

        $coinAfter = round($coinBefore - $cost, 2);
        $totalBefore = (int) ($player->total_ticket_count ?? 0);
        $paidBefore = (int) ($player->paid_ticket_count ?? 0);
        $freeBefore = (int) ($player->free_ticket_count ?? 0);
        $totalAfter = $totalBefore + $addTotal;
        $paidAfter = $paidBefore + $addPaid;
        $freeAfter = $freeBefore + $addFree;

        $oldUserArr = $player->hidden(['password'])->toArray();
        $updatedUserArr = $oldUserArr;
        $updatedUserArr['coin'] = $coinAfter;
        $updatedUserArr['total_ticket_count'] = $totalAfter;
        $updatedUserArr['paid_ticket_count'] = $paidAfter;
        $updatedUserArr['free_ticket_count'] = $freeAfter;

        UserCache::setUser($playerId, $updatedUserArr);

        $adminId = ($player->admin_id ?? null) ? (int) $player->admin_id : null;
        $playerDeptId = isset($player->dept_id) && $player->dept_id !== null && $player->dept_id !== ''
            ? (int) $player->dept_id
            : null;
        try {
            Db::transaction(function () use (
                $player,
                $playerId,
                $playerDeptId,
                $adminId,
                $cost,
                $coinBefore,
                $coinAfter,
                $addTotal,
                $addPaid,
                $addFree,
                $totalAfter,
                $paidAfter,
                $freeAfter
            ) {
                $player->coin = $coinAfter;
                $player->total_ticket_count = $totalAfter;
                $player->paid_ticket_count = $paidAfter;
                $player->free_ticket_count = $freeAfter;
                $player->save();

                DicePlayerWalletRecord::create([
                    'player_id'          => $playerId,
                    'dept_id'            => $playerDeptId,
                    'admin_id'           => $adminId,
                    'coin'               => round(-$cost, 2),
                    'type'               => self::WALLET_TYPE_BUY_DRAW,
                    'wallet_before'      => $coinBefore,
                    'wallet_after'       => $coinAfter,
                    'total_ticket_count' => $addTotal,
                    'paid_ticket_count'  => $addPaid,
                    'free_ticket_count'  => $addFree,
                    'remark'             => "购买抽奖券{$addTotal}次（付费{$addPaid}次+赠送{$addFree}次）",
                ]);

                DicePlayerTicketRecord::create([
                    'player_id'          => $playerId,
                    'dept_id'            => $playerDeptId,
                    'admin_id'           => $adminId,
                    'use_coins'          => round($cost, 2),
                    'ante'              => 1,
                    'total_ticket_count' => $addTotal,
                    'paid_ticket_count'  => $addPaid,
                    'free_ticket_count'  => $addFree,
                    'remark'             => "购买抽奖券{$addTotal}次（付费{$addPaid}次+赠送{$addFree}次）",
                ]);
            });
        } catch (\Throwable $e) {
            UserCache::setUser($playerId, $oldUserArr);
            throw $e;
        }

        return [
            'coin'                => round((float) $coinAfter, 2),
            'total_ticket_count'  => (int) $totalAfter,
            'paid_ticket_count'   => (int) $paidAfter,
            'free_ticket_count'   => (int) $freeAfter,
        ];
    }
}
