package com.liquidnet.service.account.wallet.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.account.common.ErrorConstants;
import com.liquidnet.service.account.wallet.bo.FinWalletBalanceBo;
import com.liquidnet.service.account.wallet.dto.*;
import com.liquidnet.service.account.wallet.dto.base.WalletCallResult;
import com.liquidnet.service.account.wallet.dto.base.WalletContextParam;
import com.liquidnet.service.account.wallet.entity.FinWallet;
import com.liquidnet.service.account.wallet.service.FinWalletService;
import com.liquidnet.service.account.wallet.service.processor.WalletAccountEditProcessor;
import com.liquidnet.service.account.wallet.service.processor.WalletAccountQueryProcessor;
import com.liquidnet.service.account.wallet.service.processor.WalletAccountRegisterProcessor;
import com.liquidnet.service.account.wallet.vo.WalletAccountInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

/**
 * WalletController.class
 *
 * @author zhanggb
 * Created by IntelliJ IDEA at 2020/10/21
 */
@Api(tags = "Wallet Manage")
@RestController
@RequestMapping("wl/account")
public class WalletAccountController {
    private static final Logger log = LoggerFactory.getLogger(WalletAccountController.class);
    @Autowired
    private FinWalletService walletService;
    @Autowired
    private WalletAccountRegisterProcessor accountRegisterProcessor;
    @Autowired
    private WalletAccountEditProcessor accountEditProcessor;
    @Autowired
    private WalletAccountQueryProcessor accountQueryProcessor;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "Register wallet account")
    @PostMapping("register")
    public WalletRegisterResult register(@RequestBody WalletRegisterParam parameter) {
        if (null == parameter) {
            return new WalletRegisterResult(ErrorConstants.PARAMS_VALUE_ERROR_CODE, ErrorConstants.PARAMS_VALUE_ERROR_DESC);
        }
        log.info("Call {}:[{}]", parameter.getClass().getSimpleName(), JsonUtils.toJson(parameter));
        WalletContextParam contextParam = WalletContextParam.getNew();
        BeanUtils.copyProperties(parameter, contextParam);
        contextParam.setTradeType(parameter.getClass().getSimpleName());
        WalletRegisterResult result = null;
        try {
            WalletCallResult<?> rst = accountRegisterProcessor.service(contextParam);
            result = rst instanceof WalletRegisterResult ? (WalletRegisterResult) rst
                    : new WalletRegisterResult(rst.getCode(), rst.getMessage());
        } catch (Exception e) {
            log.error("Call {} handle exception:[{}]", parameter.getClass().getSimpleName(), JsonUtils.toJson(parameter), e);
            result = new WalletRegisterResult(ErrorConstants.WALLET_CREATE_ERROR_CODE, ErrorConstants.WALLET_CREATE_ERROR_DESC);
        }
        log.info("Call {}:[{}]", result.getClass().getSimpleName(), JsonUtils.toJson(result));
        return result;
    }

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "Edit wallet account")
    @PostMapping("edit")
    public WalletEditResult edit(@RequestBody WalletEditParam parameter) {
        if (null == parameter) {
            return new WalletEditResult(ErrorConstants.PARAMS_VALUE_ERROR_CODE, ErrorConstants.PARAMS_VALUE_ERROR_DESC);
        }
        log.info("Call {}:[{}]", parameter.getClass().getSimpleName(), JsonUtils.toJson(parameter));
        WalletContextParam contextParam = WalletContextParam.getNew();
        BeanUtils.copyProperties(parameter, contextParam);
        contextParam.setTradeType(parameter.getClass().getSimpleName());
        WalletEditResult result = null;
        try {
            WalletCallResult<?> rst = accountEditProcessor.service(contextParam);
            result = rst instanceof WalletEditResult ? (WalletEditResult) rst
                    : new WalletEditResult(rst.getCode(), rst.getMessage());
        } catch (Exception e) {
            log.error("Call {} handle exception:[{}]", parameter.getClass().getSimpleName(), JsonUtils.toJson(parameter), e);
            result = new WalletEditResult(ErrorConstants.WALLET_EDIT_ERROR_CODE, ErrorConstants.WALLET_EDIT_ERROR_DESC);
        }
        log.info("Call {}:[{}]", result.getClass().getSimpleName(), JsonUtils.toJson(result));
        return result;
    }

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "Query wallet list")
    @PostMapping("query")
    public WalletQueryResult query(@RequestBody WalletQueryParam parameter) {
        if (null == parameter) {
            return new WalletQueryResult(ErrorConstants.PARAMS_VALUE_ERROR_CODE, ErrorConstants.PARAMS_VALUE_ERROR_DESC);
        }
        log.info("Call {}:[{}]", parameter.getClass().getSimpleName(), JsonUtils.toJson(parameter));
        WalletContextParam contextParam = WalletContextParam.getNew();
        BeanUtils.copyProperties(parameter, contextParam);
        contextParam.setTradeType(parameter.getClass().getSimpleName());
        contextParam.setStrList(parameter.getWalletNoList());
        WalletQueryResult result = null;
        try {
            WalletCallResult<?> rst = accountQueryProcessor.service(contextParam);
            result = rst instanceof WalletQueryResult ? (WalletQueryResult) rst
                    : new WalletQueryResult(rst.getCode(), rst.getMessage());
        } catch (Exception e) {
            log.error("Call {} handle exception:[{}]", parameter.getClass().getSimpleName(), JsonUtils.toJson(parameter), e);
            result = new WalletQueryResult(ErrorConstants.WALLET_QUERY_ERROR_CODE, ErrorConstants.WALLET_QUERY_ERROR_DESC);
        }
        log.info("Call {}:[{}]", result.getClass().getSimpleName(), result.isSuccess());
        return result;
    }

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "Query one for wallet")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "query", dataType = "String", name = "walletNo", value = "Wallet number [11]", required = true),
    })
    @GetMapping("queryOne")
    public WalletAccountInfoVo queryOne(String walletNo) {
        log.info("Call wl/account/query:[walletNo={}]", walletNo);
        if (!StringUtils.isEmpty(walletNo)) {
            try {
                FinWallet wallet = walletService.query(walletNo);
                if (null != wallet) {
                    WalletAccountInfoVo vo = WalletAccountInfoVo.getNew().copy(wallet);

                    FinWalletBalanceBo balanceBo = walletService.queryBalance(wallet.getFinId(), walletNo);

                    if (null != balanceBo) {
                        vo.setBalanceAvailable(balanceBo.getBalanceAvailable());
                        vo.setBalancePending(balanceBo.getBalancePending());
                        vo.setBalanceFrozen(balanceBo.getBalanceFrozen());
                    }
                    log.info("Call wl/account/query:[vo={}]", JsonUtils.toJson(vo));
                    return vo;
                }
            } catch (Exception e) {
                log.error("Call wl/account/query handle exception:[walletNo={}]", walletNo, e);
            }
        }
        return null;
    }
}
