package com.liquidnet.service.adam.controller.web.transaction;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.common.swagger.config.SwaggerApiVersion;
import com.liquidnet.service.ResponseDto;
import com.liquidnet.service.account.wallet.dto.WalletTransactionQueryParam;
import com.liquidnet.service.account.wallet.vo.WalletTransactionInfoVo;
import com.liquidnet.service.adam.config.swagger.AdamSwaggerApiVersionConstant;
import com.liquidnet.service.adam.constant.AdamTransactionConstants;
import com.liquidnet.service.adam.dto.base.AdamCurrentUser;
import com.liquidnet.service.adam.dto.base.AdamResultDto;
import com.liquidnet.service.adam.dto.query.AdamTransactionQuery;
import com.liquidnet.service.adam.entity.AdamTransaction;
import com.liquidnet.service.adam.interceptor.annotation.NoAuth;
import com.liquidnet.service.adam.interceptor.annotation.RequiresPermissions;
import com.liquidnet.service.adam.service.IAdamSysCountryService;
import com.liquidnet.service.adam.service.IAdamTransactionApiService;
import com.liquidnet.service.adam.service.IAdamTransactionService;
import com.liquidnet.service.adam.service.feign.fin.IAdamFeignAccountService;
import com.liquidnet.service.adam.util.CurrentUserUtil;
import com.liquidnet.service.adam.util.EnumUtil;
import com.liquidnet.service.adam.vo.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 交易记录表 前端控制器
 * </p>
 *
 * @author liquidnet
 * @since 2020-10-30
 */
@Slf4j
@Api(tags = "web transaction")
@RestController
@RequestMapping("/adam-transaction")
public class AdamTransactionController {

    @Autowired
    private IAdamTransactionService adamTransactionService;

    @Autowired
    private IAdamTransactionApiService adamTransactionApiService;

    @Autowired
    private IAdamFeignAccountService adamFeignAccountService;

    @Autowired
    private IAdamSysCountryService sysCountryService;

    @NoAuth
    @ApiOperation(value = "enum list")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @GetMapping("/enum_list")
    public ResponseDto<AdamTransactionEnumVo> enumList() {
        AdamTransactionEnumVo vo = new AdamTransactionEnumVo();
        // 公司类型
        vo.setTypeList(EnumUtil.getList(AdamTransactionConstants.TypeEnum.values()));
        // 公司实体结构
        vo.setStatusList(EnumUtil.getList(AdamTransactionConstants.StatusEnum.values()));
        // 公司行业类别
        vo.setFundList(EnumUtil.getList(AdamTransactionConstants.FundsDirectionEnum.values()));
        // 国家/地区代码,电话代码
        vo.setSysCountryList(sysCountryService.selectList(null));
        return ResponseDto.success(vo);
    }

    @RequiresPermissions("773E1BDB")
    @GetMapping("/page")
    @ApiOperation(value = "page transaction")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "int", type = "query", name = "pageNum", value = "页码"),
            @ApiImplicitParam(dataType = "int", type = "query", name = "pageSize", value = "每页显示条数")
    })
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    public ResponseDto<Page<AdamTransactionVo>> pageTransaction(@ModelAttribute AdamTransactionQuery query,
                                                                @RequestParam(required = false, value = "pageNum", defaultValue = "1") Integer pageNum,
                                                                @RequestParam(required = false, value = "pageSize", defaultValue = "10") Integer pageSize,
                                                                HttpServletRequest request) {
        AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);
        String comId = currentUser.getComId();
        query.setComId(comId);
        Page<AdamTransaction> adamTransactionPage = adamTransactionService.queryPageList(pageNum, pageSize, query);

        List<AdamTransaction> list = adamTransactionPage.getRecords();
        List<AdamTransactionVo> recordsDisplay = Lists.newArrayList();
        List<String> strList = new ArrayList<>();

        list.forEach(r -> {
            AdamTransactionVo vo = new AdamTransactionVo();
            vo.conversion(r);
            recordsDisplay.add(vo);
            if (!StringUtils.isEmpty(r.getFinWalletTransactionId()) && (StringUtils.isEmpty(r.getFinWalletAvailableBalance()) || r.getFinWalletAvailableBalance().compareTo(BigDecimal.ZERO) <= 0)) {
                strList.add(r.getFinWalletTransactionId());
            }
        });

        if (strList.size() > 0) {
            WalletTransactionQueryParam param = new WalletTransactionQueryParam();
            param.setStrListType("0");
            param.setStrList(strList);

            AdamResultDto<List<WalletTransactionInfoVo>> resultDto = adamFeignAccountService.transactionQuery(param);

            if (resultDto.isSuccess() && !CollectionUtils.isEmpty(resultDto.getData())) {
                // 异步线程更新balance
                adamTransactionApiService.asyncUpdateBalance(resultDto.getData());

                List<WalletTransactionInfoVo> data = resultDto.getData();
                Map<String, WalletTransactionInfoVo> transactionInfoVoMap = data.stream().collect(Collectors.toMap(WalletTransactionInfoVo::getTracingNo, WalletTransactionInfoVo -> WalletTransactionInfoVo));
                recordsDisplay.forEach(r -> {
                    if (transactionInfoVoMap.containsKey(r.getFinWalletTransactionId())) {
                        WalletTransactionInfoVo walletTransactionInfoVo = transactionInfoVoMap.get(r.getFinWalletTransactionId());
                        r.setFinWalletAvailableBalance(walletTransactionInfoVo.getBalanceAvailable());
                        r.setFinWalletTotalBalance(walletTransactionInfoVo.getBalanceAvailable().add(walletTransactionInfoVo.getBalancePending()).add(walletTransactionInfoVo.getBalanceFrozen()));
                    }
                });

            }
        }

        Page<AdamTransactionVo> page = new Page<>();
        BeanUtils.copyProperties(adamTransactionPage, page);
        page.setRecords(recordsDisplay);
        return ResponseDto.success(page);
    }

    @GetMapping("/get")
    @ApiOperation(value = "get transaction detail by id")
    @ApiModelProperty
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    public ResponseDto getDetail(HttpServletRequest request,
                                 @RequestParam(value = "transactionId") String transactionId,
                                 @RequestParam(value = "type") String type) {

        ResponseDto responseDto = ResponseDto.success();
        AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);
        String comId = currentUser.getComId();
        AdamTransactionConstants.TypeEnum enumByCode = AdamTransactionConstants.TypeEnum.getEnumByCode(type);
        if (enumByCode == null) {
            return ResponseDto.failure(ErrorCode.ILLEGAL_ARGUMENT);
        }
        switch (enumByCode) {
            case PAYOUT:
                AdamPayoutDetailVo paymentDetail = adamTransactionService.getPayoutDetail(comId, transactionId);
                responseDto.setData(paymentDetail);
                break;
            case FUNDING:
                AdamFundingDetailVo fundingDetail = adamTransactionService.getFundingDetail(comId, transactionId);
                responseDto.setData(fundingDetail);
                break;
            case FX_CONVERSION:
                AdamConversionDetailVo conversionDetail = adamTransactionService.getConversionDetail(comId, transactionId);
                responseDto.setData(conversionDetail);
                break;
        }

        return responseDto;

    }

}
