package com.ff.api.controller;


import cn.hutool.core.util.NumberUtil;
import com.dtflys.forest.annotation.Post;
import com.ff.annotation.CheckHeader;
import com.ff.api.request.*;
import com.ff.base.constant.Constants;
import com.ff.base.core.controller.BaseController;
import com.ff.base.core.domain.AjaxResult;
import com.ff.base.core.page.TableDataInfo;
import com.ff.base.enums.OperationType;
import com.ff.base.utils.StringUtils;
import com.ff.common.domain.TenantGameQuotaFlow;
import com.ff.common.domain.TenantSecretKey;
import com.ff.common.dto.BalanceChangesDTO;
import com.ff.common.service.ITenantGameQuotaFlowService;
import com.ff.common.service.ITenantGameQuotaService;
import com.ff.config.KeyConfig;
import com.ff.game.api.IGamesService;
import com.ff.game.api.request.*;
import com.ff.game.domain.*;
import com.ff.game.service.*;
import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * api控制器
 *
 * @author shi
 * @date 2025/02/10
 */
@RestController
@CheckHeader
@RequestMapping("/api/game")
public class ApiGameController extends BaseController {


    @Autowired
    private Map<String, IGamesService> gamesService;


    @Resource
    private IGameService gameService;


    @Resource
    private KeyConfig keyConfig;

    @Resource
    private IGameSecretKeyService gameSecretKeyService;

    @Resource
    private IMemberService memberService;

    @Resource
    private IGamePlatformService gamePlatformService;


    @Resource
    private ITenantGameQuotaService tenantGameQuotaService;

    @Resource
    private ITenantGameQuotaFlowService tenantGameQuotaFlowService;

    @Resource
    private IGameBettingDetailsService gameBettingDetailsService;

    @Resource
    private IGameFreeRecordService gameFreeRecordService;


    /**
     * 登录
     *
     * @param memberCreateApiRequest 成员创建api请求
     * @return {@link AjaxResult }
     */
    @PostMapping("/login")
    public AjaxResult login(@Validated @RequestBody GameLoginRequest memberCreateApiRequest) {

        Game game = gameService.selectGameById(memberCreateApiRequest.getGameId());
        Assert.notNull(game, "游戏不存在");

        GamePlatform gamePlatform = gamePlatformService.selectGamePlatformById(game.getPlatformId());
        Assert.notNull(gamePlatform, "游戏平台不存在");


        IGamesService iGamesService = gamesService.get(gamePlatform.getPlatformCode() + Constants.SERVICE);


        TenantSecretKey tenantSecretKey = keyConfig.get();
        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gamePlatform.getPlatformCode(), memberCreateApiRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");

        GameSecretKey gameSecretKeyLang = gameSecretKeyService.findByPlatformAndSystemLangCode(gamePlatform.getPlatformCode(), memberCreateApiRequest.getLangCode());
        Assert.notNull(gameSecretKeyLang, "当前语言不存在");

        Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(memberCreateApiRequest.getAccount(), memberCreateApiRequest.getCurrencyCode() + tenantSecretKey.getTenantSn()));
        Assert.notNull(member, "会员不存在");

        GamesLogin gamesLogin = GamesLogin.builder()
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .account(member.getGameAccount())
                .gameId(game.getGameCode())
                .homeUrl(memberCreateApiRequest.getHomeUrl())
                .platform(memberCreateApiRequest.getPlatform())
                .disableFullScreen(memberCreateApiRequest.getDisableFullScreen())
                .lang(gameSecretKeyLang.getLang())
                .build();

        String login = iGamesService.loginWithoutRedirect(gamesLogin);

        return AjaxResult.success(login);
    }


    /**
     * 汇兑差额
     *
     * @param gameExchangeBalanceRequest 游戏兑换余额请求
     * @return {@link AjaxResult }
     */
    @PostMapping("/exchange/balance")
    @Transactional
    public AjaxResult exchangeBalance(@Validated @RequestBody GameExchangeBalanceRequest gameExchangeBalanceRequest) {


        IGamesService iGamesService = gamesService.get(gameExchangeBalanceRequest.getPlatformCode() + Constants.SERVICE);


        TenantSecretKey tenantSecretKey = keyConfig.get();
        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameExchangeBalanceRequest.getPlatformCode(), gameExchangeBalanceRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");


        Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameExchangeBalanceRequest.getAccount(), gameExchangeBalanceRequest.getCurrencyCode() + tenantSecretKey.getTenantSn()));
        Assert.notNull(member, "会员不存在");

        //操作租户额度
        boolean isOut = gameExchangeBalanceRequest.getTransferType() == 1;
        BigDecimal balanceRequestAmount = gameExchangeBalanceRequest.getAmount();
        //如果是增加不可以超过对应的额度
        if (isOut) {

            //获取第三方钱包余额
            MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
                    .accounts(member.getGameAccount())
                    .agentId(gameSecretKey.getCode())
                    .agentKey(gameSecretKey.getKey())
                    .build();
            balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance();
            //转入金额
            BigDecimal balanceInto = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder()
                    .isOut(Boolean.TRUE)
                    .tenantKey(tenantSecretKey.getTenantKey())
                    .memberId(member.getId())
                    .build());
            //转出金额
            BigDecimal balanceOut = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder()
                    .isOut(Boolean.FALSE)
                    .tenantKey(tenantSecretKey.getTenantKey())
                    .memberId(member.getId())
                    .build());
            //如果转入金额+本次转入金额 大于转出额度则取差值
            if (NumberUtil.add(balanceInto, balanceRequestAmount).compareTo(balanceOut) > 0) {
                balanceRequestAmount = NumberUtil.sub(balanceOut, balanceInto);
            }
        }
        //余额扣除
        tenantGameQuotaService.balanceChanges(BalanceChangesDTO.builder()
                .isOut(isOut)
                .tenantKey(tenantSecretKey.getTenantKey())
                .balance(balanceRequestAmount)
                .memberId(member.getId())
                .operationType(OperationType.API_BALANCE.getCode())
                .remark(OperationType.API_BALANCE.getDescription())
                .build());


        ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO = ExchangeTransferMoneyRequestDTO.builder()
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .account(member.getGameAccount())
                .quota(balanceRequestAmount)
                .amount(gameExchangeBalanceRequest.getAmount())
                .transferType(gameExchangeBalanceRequest.getTransferType())
                .orderId(gameExchangeBalanceRequest.getOrderId())
                .build();
        String transferByAgentId = iGamesService.exchangeTransferByAgentId(exchangeTransferMoneyRequestDTO);

        return AjaxResult.success(transferByAgentId);
    }


    /**
     * 赠送免费局数
     *
     * @param gameCreateFreeSpinRequest 游戏创建免费旋转请求
     * @return {@link AjaxResult }
     */
    @PostMapping("/create/free/spin")
    public AjaxResult createFreeSpin(@Validated @RequestBody GameCreateFreeSpinRequest gameCreateFreeSpinRequest) {


        IGamesService iGamesService = gamesService.get(gameCreateFreeSpinRequest.getPlatformCode() + Constants.SERVICE);
        Assert.notNull(iGamesService, "游戏平台不存在");


        TenantSecretKey tenantSecretKey = keyConfig.get();
        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameCreateFreeSpinRequest.getPlatformCode(), gameCreateFreeSpinRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");


        Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameCreateFreeSpinRequest.getAccount(), gameCreateFreeSpinRequest.getCurrencyCode() + tenantSecretKey.getTenantSn()));
        Assert.notNull(member, "会员不存在");
        CreateFreeSpinRequestDTO createFreeSpinRequestDTO = CreateFreeSpinRequestDTO.builder()
                .account(member.getGameAccount())
                .currency(gameCreateFreeSpinRequest.getCurrencyCode())
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .referenceId(gameCreateFreeSpinRequest.getReferenceId())
                .freeSpinValidity(gameCreateFreeSpinRequest.getFreeSpinValidity())
                .numberOfRounds(gameCreateFreeSpinRequest.getNumberOfRounds())
                .gameIds(gameCreateFreeSpinRequest.getGameIds())
                .betValue(gameCreateFreeSpinRequest.getBetValue())
                .startTime(gameCreateFreeSpinRequest.getStartTime())
                .build();


        return AjaxResult.success(iGamesService.createFreeSpin(createFreeSpinRequestDTO));
    }


    /**
     * 获取投注记录
     *
     * @param gameCreateFreeSpinRequest 游戏创建免费旋转请求
     * @return {@link AjaxResult }
     */
    @PostMapping("/get/bet/record")
    public TableDataInfo createFreeSpin(@Validated @RequestBody GameGetBetRecordRequest gameCreateFreeSpinRequest) {
        startPage();
        PageHelper.startPage(gameCreateFreeSpinRequest.getPageNo(), gameCreateFreeSpinRequest.getPageSize(), "wagers_time desc");
        GameBettingDetails gameBettingDetails = GameBettingDetails.builder()
                .platformCode(gameCreateFreeSpinRequest.getPlatformCode())
                .currencyCode(gameCreateFreeSpinRequest.getCurrencyCode())
                .build();
        Map<String, Object> params = gameBettingDetails.getParams();
        params.put("beginTime", gameCreateFreeSpinRequest.getBeginTime());
        params.put("endTime", gameCreateFreeSpinRequest.getEndTime());
        List<GameBettingDetails> bettingDetails = gameBettingDetailsService.selectGameBettingDetailsList(gameBettingDetails);
        return getDataTable(bettingDetails);
    }


    /**
     * 获取详细信息
     *
     * @param gameGetDetailRequest 游戏获取详细信息请求
     * @return {@link AjaxResult }
     */
    @PostMapping("/get/detail")
    public AjaxResult getDetail(@Validated @RequestBody GameGetDetailRequest gameGetDetailRequest) {

        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameGetDetailRequest.getPlatformCode(), gameGetDetailRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");


        IGamesService iGamesService = gamesService.get(gameGetDetailRequest.getPlatformCode() + Constants.SERVICE);
        Assert.notNull(iGamesService, "游戏平台不存在");

        GameSecretKey gameSecretKeyLang = gameSecretKeyService.findByPlatformAndSystemLangCode(gameGetDetailRequest.getPlatformCode(), gameGetDetailRequest.getLangCode());
        Assert.notNull(gameSecretKeyLang, "当前语言不存在");


        GetGameDetailResponseDTO gameDetail = iGamesService.getGameDetail(GetGameDetailRequestDTO.builder()
                .wagersId(gameGetDetailRequest.getWagersId())
                .lang(gameSecretKeyLang.getLang())
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .build());
        return AjaxResult.success(gameDetail);
    }

    /**
     * 踢腿队员
     *
     * @param gameKickMemeberRequest 游戏踢迷请求
     * @return {@link AjaxResult }
     */
    @PostMapping("/kick/member")
    public AjaxResult kickMember(@Validated @RequestBody GameKickMemeberRequest gameKickMemeberRequest) {
        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameKickMemeberRequest.getPlatformCode(), gameKickMemeberRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");

        TenantSecretKey tenantSecretKey = keyConfig.get();
        Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameKickMemeberRequest.getAccount(), gameKickMemeberRequest.getCurrencyCode() + tenantSecretKey.getTenantSn()));
        Assert.notNull(member, "会员不存在");

        IGamesService iGamesService = gamesService.get(gameKickMemeberRequest.getPlatformCode() + Constants.SERVICE);
        Assert.notNull(iGamesService, "游戏平台不存在");


        return AjaxResult.success(iGamesService.kickMember(KickMemberRequestDTO.builder()
                .account(member.getGameAccount())
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .build()));
    }

    @PostMapping("/kick/member/all")
    public AjaxResult kickMemberAll(@Validated @RequestBody GameKickMemeberAllRequest gameKickMemeberAllRequest) {
        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameKickMemeberAllRequest.getPlatformCode(), gameKickMemeberAllRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");

        IGamesService iGamesService = gamesService.get(gameKickMemeberAllRequest.getPlatformCode() + Constants.SERVICE);
        Assert.notNull(iGamesService, "游戏平台不存在");

        KickMemberAllDTO kickMemberAllDTO = KickMemberAllDTO.builder()
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .build();
        if (!ObjectUtils.isEmpty(gameKickMemeberAllRequest.getGameId())) {
            Game game = gameService.selectGameById(gameKickMemeberAllRequest.getGameId());
            Assert.notNull(game, "游戏不存在");
            kickMemberAllDTO.setGameId(game.getGameCode());
        }


        return AjaxResult.success(iGamesService.kickMemberAll(kickMemberAllDTO));

    }

    /**
     * 获得自由旋转气流
     *
     * @param gameGetFreeSpinDashflowRequest 游戏获得免费旋转dashflow请求
     * @return {@link TableDataInfo }
     */
    @PostMapping("/get/free/spin/dashflow")
    public TableDataInfo getFreeSpinDashflow(@Validated @RequestBody GameGetFreeSpinDashflowRequest gameGetFreeSpinDashflowRequest) {
        PageHelper.startPage(gameGetFreeSpinDashflowRequest.getPageNo(), gameGetFreeSpinDashflowRequest.getPageSize(), "free_update_time desc");
        List<GameFreeRecord> gameFreeRecords = gameFreeRecordService.selectGameFreeRecordList(GameFreeRecord.builder()
                .gameId(gameGetFreeSpinDashflowRequest.getGameId())
                .platformCode(gameGetFreeSpinDashflowRequest.getPlatformCode())
                .currencyCode(gameGetFreeSpinDashflowRequest.getCurrencyCode())
                .build());
        return getDataTable(gameFreeRecords);
    }


    /**
     * 取消自由旋转
     *
     * @param gameGetFreeSpinDashflowRequest 游戏获得免费旋转dashflow请求
     * @return {@link TableDataInfo }
     */
    @PostMapping("/cancel/free/spin")
    public AjaxResult cancelFreeSpin(@Validated @RequestBody GameCancelFreeSpinRequest gameGetFreeSpinDashflowRequest) {
        GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameGetFreeSpinDashflowRequest.getPlatformCode(), gameGetFreeSpinDashflowRequest.getCurrencyCode());
        Assert.notNull(gameSecretKey, "货币游戏平台不存在");

        IGamesService iGamesService = gamesService.get(gameGetFreeSpinDashflowRequest.getPlatformCode() + Constants.SERVICE);
        Assert.notNull(iGamesService, "游戏平台不存在");

        Boolean cancelFreeSpin = iGamesService.cancelFreeSpin(CancelFreeSpinRequestDTO.builder()
                .agentId(gameSecretKey.getCode())
                .agentKey(gameSecretKey.getKey())
                .referenceId(gameGetFreeSpinDashflowRequest.getReferenceId())
                .build());
        return AjaxResult.success(cancelFreeSpin);
    }
}
