package com.izouma.nineth.web.mobile.v1;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.izouma.nineth.domain.TokenHistory;

import com.izouma.nineth.aspect.CipherParam;
import com.izouma.nineth.aspect.RequestCipher;
import com.izouma.nineth.domain.*;
import com.izouma.nineth.dto.AssetDTO;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.dto.PageWrapDTO;
import com.izouma.nineth.dto.UserHistory;
import com.izouma.nineth.enums.AccountStatus;
import com.izouma.nineth.enums.ItemType;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.lock.RedisLockException;
import com.izouma.nineth.repo.AssetRepo;
import com.izouma.nineth.repo.UserWareHouseRepo;
import com.izouma.nineth.service.*;
import com.izouma.nineth.service.pay.UniformPayConstants;
import com.izouma.nineth.service.pay.UniformPayUtil;
import com.izouma.nineth.utils.JpaUtils;
import com.izouma.nineth.utils.SecurityUtils;
import com.izouma.nineth.web.BaseController;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/asset/v1")
@Slf4j
@AllArgsConstructor
public class AssetControllerV1 extends BaseController {
    private AssetService assetService;
    private AssetRepo assetRepo;
    private UserService userService;
    private UserWareHouseRepo userWareHouseRepo;
    private AirDropService airDropService;
    private ProjectService projectService;
    private UserFundAccountForLianlianpayService userFundAccountForLianlianpayService;
    private UniformPayUtil uniformPayUtil;


    @PostMapping("/all")
    public PageWrapDTO<AssetDTO> all(@RequestBody PageQuery pageQuery) {
        //限定普通用户查询范围
        User user = currentUser();
        if(!user.isAdmin()){
            pageQuery.getQuery().put("userId", user.getId());
        }
        PageWrapDTO<Asset> assets = assetService.all(pageQuery);
        List<AssetDTO> list = assetService.convertToAssetDTO(assets.getContent());
        PageWrapDTO newPageWrapDTO = new PageWrapDTO(list, assets.getPageable(), assets.getTotalElements());
        newPageWrapDTO.setTotalAmount(assets.getTotalAmount());
        return newPageWrapDTO;
    }


    @GetMapping("/get/{id}")
    public AssetDTO get(@PathVariable Long id) {
        Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
        //假数据处理
        assetService.mockLimitData(asset);
        AssetDTO assetDTO = new AssetDTO(asset);
        PreEmptionPrivilege preEmptionPrivilege = assetService.preEmptionPrivilege(assetDTO);
        assetDTO.setPreEmptionPrivilege(preEmptionPrivilege);
        return assetDTO;
    }


    @PostMapping("/consignment")
    @ApiOperation("寄售")
    @RequestCipher
    public void consignment(@CipherParam String encrytorData) {
        JSONObject jsonObject = JSON.parseObject(encrytorData);
        String tradeCode = jsonObject.getString("tradeCode");
        Long id = jsonObject.getLong("id");
        String priceString = jsonObject.getString("price");
        BigDecimal price = new BigDecimal(priceString);
        User user = currentUser();
        userService.verifyTradeCode(SecurityUtils.getAuthenticatedUser().getId(), tradeCode);
        //是否需要开通钱包
        String defaultPayPlatform = uniformPayUtil.getDefaultPayPlatform();
        if(UniformPayConstants.NOTPAY_PLATFORM.equals(defaultPayPlatform)){
            //支付通道已关闭时，需要检查
            UserFundAccount lianlianAccount = userFundAccountForLianlianpayService.getAccount(user.getId());
            if(lianlianAccount == null || lianlianAccount.getAccountStatus() != AccountStatus.NORMAL){
                throw new BusinessException("请开通钱包后再寄售");
            }
        }

        assetService.consignment(user.getId(), id, price);
    }

    @PostMapping("/cancelConsignment")
    @ApiOperation("取消寄售")
    public void cancelConsignment(@RequestParam Long id) {
        User user  = currentUser();
        assetService.cancelConsignment(user.getId(), id);
    }


    @PostMapping("/openSurpriseBox")
    public SurpriseBoxLog openSurpriseBox(@RequestParam Long surpriseBoxId) {
        User user = currentUser();
        if (user == null) return null;
        return airDropService.openSurpriseBox(currentUser(), surpriseBoxId);
    }

    @PostMapping("/getSurpriseBox")
    public List<UserWareHouse> getSurpriseBox(@RequestParam Long assetId, Integer projectId) {
        if (assetId == null) {
            return userWareHouseRepo.findUserIdBox(currentUser().getId(), ItemType.SURPRISE_BOX.ordinal(), projectId);
        } else {
            return userWareHouseRepo.findUserIdBoxByAssetId(currentUser().getId(), assetId, ItemType.SURPRISE_BOX.ordinal());
        }
    }

    @GetMapping("/tokenHistory")
    @ApiOperation("交易历史")
    public List<TokenHistory> tokenHistory(@RequestParam(required = false) String tokenId, @RequestParam(required = false) Long assetId) {
        return assetService.tokenHistory(tokenId, assetId);
    }

    @PostMapping("/userHistory")
    @ApiOperation("交易历史")
    public Page<UserHistory> userHistory(@RequestBody PageQuery pageQuery) {
        return assetService.userHistory(SecurityUtils.getAuthenticatedUser().getId(),
                projectService.getProjectId(),
                Integer.valueOf((String) pageQuery.getQuery().get("type")),
                JpaUtils.toPageRequest(pageQuery));
    }
    /**
     * 手动开启盲盒
     *
     * @param assetId
     * @return
     */
    @PostMapping("/variableAsset")
    public Asset variableAsset(Long assetId) {
        try {
            return assetService.variableAsset(assetId, currentUser());
        } catch (RedisLockException err) {
            log.error("抽盲合没获取资产ID：{}", assetId);
            throw new BusinessException("用力过猛，请重试一次");
        }
    }


    /**
     * 用户个人藏品数量
     */
    @PostMapping("/userHoldNum")
    public Map<String, Object> userHoldNum(@RequestBody User user) {
        return assetService.userHoldNum(user.getId(),projectService.getProjectId());
    }


}


