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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.WalletQueryParam;
import com.liquidnet.service.account.wallet.vo.WalletAccountInfoVo;
import com.liquidnet.service.adam.config.swagger.AdamSwaggerApiVersionConstant;
import com.liquidnet.service.adam.constant.AdamAccountConstants;
import com.liquidnet.service.adam.constant.AdamBankConstants;
import com.liquidnet.service.adam.dto.AdamAccountCreateParam;
import com.liquidnet.service.adam.dto.AdamAccountParam;
import com.liquidnet.service.adam.dto.AdamAccountWalletParam;
import com.liquidnet.service.adam.dto.base.AdamCurrentUser;
import com.liquidnet.service.adam.dto.base.AdamResultDto;
import com.liquidnet.service.adam.entity.AdamAccount;
import com.liquidnet.service.adam.entity.AdamAccountWallet;
import com.liquidnet.service.adam.entity.AdamWalletAccess;
import com.liquidnet.service.adam.interceptor.annotation.RequiresPermissions;
import com.liquidnet.service.adam.service.*;
import com.liquidnet.service.adam.service.feign.bank.IAdamFeignBankCcFundingService;
import com.liquidnet.service.adam.service.feign.fin.IAdamFeignAccountService;
import com.liquidnet.service.adam.util.CurrentUserUtil;
import com.liquidnet.service.adam.vo.AdamWalletDetailVo;
import com.liquidnet.service.bank.currencycloud.dto.BankCcFundingAccountDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 账户钱包 前端控制器
 * </p>
 *
 * @author liquidnet
 * @since 2020-10-19
 */
@Api(tags = "web wallet")
@Slf4j
@RestController
@RequestMapping("/adam-account-wallet")
public class AdamAccountWalletController {

    @Autowired
    IAdamAccountService adamAccountService;

    @Autowired
    IAdamAccountApiService adamAccountApiService;

    @Autowired
    IAdamAccountWalletService adamAccountWalletService;

    @Autowired
    IAdamComInfoService adamComInfoService;

    @Autowired
    IAdamFeignAccountService adamFeignAccountService;

    @Autowired
    IAdamFeignBankCcFundingService adamFeignBankCcFundingService;

    @Autowired
    IAdamWalletAccessService adamWalletAccessService;

    @RequiresPermissions("3E669FC2")
    @ApiOperation(value = "create wallet")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @PostMapping("/create")
    public ResponseDto createWallet(HttpServletRequest request,
                                    @ModelAttribute AdamAccountCreateParam param) {
        String logFx = "create wallet.";
        try {
            AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);
            param.setComId(currentUser.getComId());
            param.setUserId(currentUser.getId());
            param.setBankChannel(AdamBankConstants.BankChannelEnum.CURRENCY_CLOUD.getCode());
            param.setSource("user_create");
            log.info(logFx + "AdamAccountCreateParam=[{}]", JSON.toJSONString(param, SerializerFeature.WriteMapNullValue));
            AdamResultDto<AdamAccountWallet> accountWallet = adamAccountApiService.createAccountWallet(param);

            return AdamResultDto.getResponseDto(accountWallet);
        } catch (Exception e) {
            log.error(logFx + "error", e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
    }

    @RequiresPermissions("3E669FC2")
    @ApiOperation(value = "delete wallet")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "walletNo", value = "walletNo")
    })
    @PostMapping("/delete")
    public ResponseDto deleteWallet(HttpServletRequest request, @RequestParam String walletNo) {
        log.info("delete wallet,walletNo=[{}]", walletNo);
        try {
            AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);
            AdamResultDto adamResultDto = adamAccountApiService.deleteWallet(currentUser.getComId(), walletNo);
            return AdamResultDto.getResponseDto(adamResultDto);
        } catch (Exception e) {
            log.error("delete wallet error", e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
    }

    @RequiresPermissions("3E669FC2")
    @ApiOperation(value = "update wallet name")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "walletNo", value = "walletNo"),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "walletName", value = "wallet name")
    })
    @PostMapping("/update_name")
    public ResponseDto updateWalletName(HttpServletRequest request, @RequestParam String walletNo, @RequestParam String walletName) {
        log.info("update wallet name,walletNo=[{}],walletName=[{}]", walletNo, walletName);
        try {
            AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);
            AdamResultDto adamResultDto = adamAccountApiService.updateWalletName(currentUser.getComId(), walletNo, walletName);
            return AdamResultDto.getResponseDto(adamResultDto);
        } catch (Exception e) {
            log.error("update wallet name error", e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
    }

    @ApiOperation(value = "get wallet")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "walletNo", value = "walletNo")
    })
    @GetMapping("/get")
    public ResponseDto<WalletAccountInfoVo> getWallet(HttpServletRequest request, @RequestParam String walletNo) {
        try {
            AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);
            String comId = currentUser.getComId();
            AdamResultDto<WalletAccountInfoVo> resultDto = adamFeignAccountService.getWallet(comId, walletNo);
            // 查询account wallet
            AdamAccountWalletParam walletParam = new AdamAccountWalletParam();
            walletParam.setComId(comId);
            walletParam.setState(AdamAccountConstants.StateEnum.S2.getCode());
            walletParam.setFinWalletNo(walletNo);
            AdamAccountWallet adamAccountWallet = adamAccountWalletService.selectOne(walletParam);
            // 查询account
            AdamAccountParam accountParam = new AdamAccountParam();
            accountParam.setComId(comId);
            accountParam.setState(AdamAccountConstants.StateEnum.S2.getCode());
            accountParam.setBankChannel(adamAccountWallet.getBankChannel());
            AdamAccount adamAccount = adamAccountService.selectOne(accountParam);

            AdamWalletDetailVo vo = new AdamWalletDetailVo();
            vo.setWalletAccountInfo(resultDto.getData());
            if (AdamBankConstants.BankChannelEnum.CURRENCY_CLOUD.getCode().equals(adamAccount.getBankChannel())) {
                AdamResultDto<List<BankCcFundingAccountDto>> fundingAccountResult = adamFeignBankCcFundingService.getFundingAccount(adamAccount.getBankId(), adamAccountWallet.getCurrency());
                vo.setCcFundingAccountDtoList(fundingAccountResult.getData());
            }
            return AdamResultDto.getResponseDto(resultDto);

        } catch (Exception e) {
            log.error("get wallet error", e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
    }

    @RequiresPermissions("6FA22359")
    @ApiOperation(value = "list page wallets")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "search", value = "条件模糊搜索"),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "pageNo", value = "当前页"),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "pageSize", value = "页大小")
    })
    @GetMapping("/list_page")
    public ResponseDto<Page<WalletAccountInfoVo>> listPage(HttpServletRequest request,
                                                           @RequestParam(required = false) String search,
                                                           @RequestParam(required = false) String pageNo,
                                                           @RequestParam(required = false) String pageSize) {
        try {
            AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);

            // Filter user allowed access wallets
            List<AdamWalletAccess> allowedWalletList = adamWalletAccessService.queryByUserId(currentUser.getId());

            WalletQueryParam param = new WalletQueryParam();
            param.setUserExtId(currentUser.getComId());
            param.setWalletNoList(allowedWalletList.stream().map(AdamWalletAccess::getFinWalletNo).collect(Collectors.toList()));
            param.setFuzzySearch(search);
            param.setPageNum(StringUtils.isEmpty(pageNo) ? 1 : Integer.parseInt(pageNo));
            param.setPageSize(StringUtils.isEmpty(pageSize) ? 10 : Integer.parseInt(pageSize));
            AdamResultDto<Page<WalletAccountInfoVo>> pageAdamResultDto = adamFeignAccountService.listPage(param);

            return AdamResultDto.getResponseDto(pageAdamResultDto);
        } catch (Exception e) {
            log.error("list page wallets error", e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
    }

    @ApiOperation(value = "list wallets")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_1)
    @GetMapping("/list_wallets")
    public ResponseDto<List<WalletAccountInfoVo>> listWallets(HttpServletRequest request) {
        try {

            AdamCurrentUser currentUser = CurrentUserUtil.getCurrentUser(request);

            // Filter user allowed access wallets
            List<AdamWalletAccess> allowedWalletList = adamWalletAccessService.queryByUserId(currentUser.getId());

            WalletQueryParam param = new WalletQueryParam();
            param.setUserExtId(currentUser.getComId());
            param.setWalletNoList(allowedWalletList.stream().map(AdamWalletAccess::getFinWalletNo).collect(Collectors.toList()));
            param.setPageNum(1);
            param.setPageSize(1000);
            AdamResultDto<Page<WalletAccountInfoVo>> pageAdamResultDto = adamFeignAccountService.listPage(param);
            if (!pageAdamResultDto.isSuccess()) {
                return ResponseDto.failure(pageAdamResultDto.getCode(), pageAdamResultDto.getMessage());
            }
            return ResponseDto.success(pageAdamResultDto.getData().getRecords());
        } catch (Exception e) {
            log.error("list wallets error", e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
    }

}
