package com.crm.pay.controller;

import com.crm.pay.entity.finance.withdraw.FinanceWithdrawApproveChannelEntity;
import com.crm.pay.entity.finance.withdraw.FinanceWithdrawApproveChannelSubmitEntity;
import com.crm.pay.service.CustomInfoService;
import com.crm.pay.service.FinanceWithdrawService;
import com.crm.pay.service.SysRemitChannelService;
import com.crm.pay.service.UserInfoService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.FeignClientAnnotation;
import com.crm.rely.backend.core.constant.PrefixEnum;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.entity.base.SingleLongEntity;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.model.constant.PayConstants;
import com.crm.rely.backend.model.dto.finance.withdraw.FinanceWithdrawDto;
import com.crm.rely.backend.model.dto.sys.remit.SysRemitChannelApiDto;
import com.crm.rely.backend.model.entity.custom.info.CustomInfoEntity;
import com.crm.rely.backend.model.entity.finance.withdraw.*;
import com.crm.rely.backend.model.pojo.table.CustomInfoTable;
import com.crm.rely.backend.model.pojo.table.UserInfoTable;
import com.crm.rely.backend.util.DateUtil;
import com.google.common.base.Strings;
import org.springframework.beans.factory.annotation.Autowired;
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 java.math.BigDecimal;
import java.util.Date;
import java.util.List;


/**
 * 出金
 */
@RestController
@RequestMapping("/withdraw")
public class FinanceWithdrawController {

    @Autowired
    private FinanceWithdrawService financeWithdrawService;
    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private SysRemitChannelService sysRemitChannelService;

    @Autowired
    private CustomInfoService customInfoService;

    @PostMapping("/cancel")
    public BaseResultDto<Object> cancel(@RequestBody FinanceWithdrawCancelEntity entity) throws Exception {

        return financeWithdrawService.cancel(entity);
    }

    @PostMapping("/remaining/reduction/number")
    public BaseResultDto<Object> remainingReductionNumber(CustomInfoEntity infoEntity) throws Exception {

        return BaseResultDto.success(financeWithdrawService.getRemainingReductionNumber(infoEntity.getCId()));
    }

    @PostMapping("/cancel/backstage")
    public BaseResultDto<Object> cancelBackstage(@RequestBody FinanceWithdrawCancelEntity entity) throws Exception {

        return financeWithdrawService.cancelBackstage(entity);
    }


    @PostMapping("/apply/bank")
    public BaseResultDto bank(@RequestBody @Validated FinanceWithdrawBankAddEntity entity, CustomInfoEntity infoEntity)
            throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(infoEntity.getStatus())) {
            return BaseResultDto.error(Constants.VALIDATION_DATA);
        }
        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.CHANNEL_TYPE_BANK);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        return financeWithdrawService.save(entity);
    }

    @PostMapping("/apply/bank/telegraphic")
    public BaseResultDto bankTelegraphic(@RequestBody @Validated FinanceWithdrawBankTelegraphicAddEntity entity,
                                         CustomInfoEntity infoEntity)
            throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(infoEntity.getStatus())) {
            return BaseResultDto.error(Constants.VALIDATION_DATA);
        }
        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.CHANNEL_TYPE_BANK_TELEGRAPHIC);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        return financeWithdrawService.save(entity);
    }

    @PostMapping("/apply/digital/currency")
    public BaseResultDto digitalCurrency(@RequestBody @Validated FinanceWithdrawDigitalCurrencyAddEntity entity,
                                         CustomInfoEntity infoEntity)
            throws Exception {

        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setEmail(infoEntity.getEmail());

        //financeWithdrawService.applyDigitalWithdrawValidateCode(entity);

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.CHANNEL_TYPE_DIGITAL_CURRENCY);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        //customBankService.validBankAddress(entity);

        return financeWithdrawService.save(entity);
    }

    @PostMapping("/apply/wallet")
    public BaseResultDto wallet(@RequestBody @Validated FinanceWithdrawWalletAddEntity entity, CustomInfoEntity infoEntity)
            throws Exception {

        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.CHANNEL_TYPE_WALLET);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        return financeWithdrawService.save(entity);
    }

    @PostMapping("/apply/ali/wallet")
    public BaseResultDto aliWallet(@RequestBody @Validated FinanceWithdrawWalletAddEntity entity, CustomInfoEntity infoEntity)
            throws Exception {

        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.CHANNEL_TYPE_ALI_WALLET);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        return financeWithdrawService.save(entity);
    }

    @PostMapping("/apply/digital/currency/send/code")
    public BaseResultDto applyDigitalWithdrawSendEmailCode(CustomInfoEntity infoEntity) throws ServiceException {
        FinanceApplyDigitalWithdrawSendEmailCodeEntity entity = new FinanceApplyDigitalWithdrawSendEmailCodeEntity();
        entity.setEmail(infoEntity.getEmail());
        entity.setCountry(infoEntity.getCountry());
        entity.setTime(new Date());
        entity.setIp(infoEntity.getLastIp());

        financeWithdrawService.applyDigitalWithdrawSendEmailCode(entity);

        return BaseResultDto.success();
    }

    @PostMapping("/apply/card")
    public BaseResultDto card(@RequestBody @Validated FinanceWithdrawCardAddEntity entity,
                              CustomInfoEntity infoEntity)
            throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(infoEntity.getStatus())) {
            return BaseResultDto.error(Constants.VALIDATION_DATA);
        }
        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.CHANNEL_TYPE_CARD);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        return financeWithdrawService.save(entity);
    }

    @PostMapping("/apply/ucard/wallet")
    public BaseResultDto ucardWallet(@RequestBody @Validated FinanceWithdrawWalletAddEntity entity, CustomInfoEntity infoEntity)
            throws Exception {
        if (!validateLogin(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_NOT_EMPTY);
        }

        entity.setCId(infoEntity.getCId());
        entity.setCustomId(infoEntity.getId());
        entity.setChannelType(PayConstants.UCARD_WALLET);

        if (!validateBalance(entity)) {
            return BaseResultDto.error(PayConstants.PAY_REMIT_AMOUNT_INSUFFICIENT);
        }

        return financeWithdrawService.save(entity);
    }

    private boolean validateLogin(FinanceWithdrawBaseAddEntity entity) {
        if (entity.getAmount() == null || entity.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return false;
        }
        return true;
    }

    private boolean validateBalance(FinanceWithdrawBaseAddEntity entity) {
        CustomInfoTable customInfoTable = customInfoService.getById(entity.getCustomId());
        if (customInfoTable.getBalance() == null || customInfoTable.getBalance().compareTo(entity.getAmount()) < 0) {
            return false;
        }
        return true;
    }

    @PostMapping("/manager/approve")
    @FeignClientAnnotation
    public BaseResultDto approve(@RequestBody @Validated FinanceWithdrawApproveEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
        if (PayConstants.PASSED_STATUS.equals(entity.getStatus())) {
            entity.setWithdrawStatus(PayConstants.MANAGER_PROCESSING_STATUS);
        } else {
            entity.setWithdrawStatus(PayConstants.MANAGER_PENDING_STATUS);
        }
        entity.setOperationType(PayConstants.OPERATION_TYPE_MANUAL);
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/sales/approve")
    @FeignClientAnnotation
    public BaseResultDto approveBySales(@RequestBody @Validated FinanceWithdrawApproveSalesEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }

        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/manager")
    @FeignClientAnnotation
    public BaseResultDto approveByManager(@RequestBody @Validated FinanceWithdrawApproveManagerEntity entity) throws Exception {
        if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(entity.getWithdrawStatus()) && !PayConstants.MANAGER_FAIL_STATUS.equals(entity.getWithdrawStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
        if (PayConstants.MANAGER_COMPLETED_STATUS.equals(entity.getWithdrawStatus()) && Strings.isNullOrEmpty(entity.getWithdrawTicket())) {
            return BaseResultDto.error(Constants.PARAMETER_ERROR);
        }
        if (PayConstants.MANAGER_COMPLETED_STATUS.equals(entity.getWithdrawStatus())) {

            entity.setCallbackStatus(PayConstants.CALLBACE_PROCESSING_STATUS);
        } else {
            entity.setWithdrawTicket(null);
            entity.setCallbackStatus(null);
        }
        financeWithdrawService.approve(entity);
        financeWithdrawService.sendFastWithdraw(entity);
        financeWithdrawService.vietnamFastWithdraw(entity.getId());
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/backstage")
    @FeignClientAnnotation
    public BaseResultDto approveByBackstage(@RequestBody @Validated FinanceWithdrawApproveBackstageEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getBackstageStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getBackstageStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
        financeWithdrawService.approve(entity);
        financeWithdrawService.vietnamFastWithdraw(entity.getId());
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/info")
    @FeignClientAnnotation
    public BaseResultDto approveByInfo(@RequestBody @Validated FinanceWithdrawApproveInfoEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getInfoStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getInfoStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/infos")
    @FeignClientAnnotation
    public BaseResultDto approveByInfos(@RequestBody @Validated FinanceWithdrawApproveInfosEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getInfoStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getInfoStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/submit/channel")
    @FeignClientAnnotation
    public BaseResultDto approveBySubmit(@RequestBody @Validated FinanceWithdrawApproveChannelSubmitEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getSubmitStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getSubmitStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
//        if (Constants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus()) && !Strings.isNullOrEmpty(entity
//        .getChannelSerial())) {
//            return BaseResultDto.error(Constants.NOT_PERMIT);
//        }
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/channel")
    public BaseResultDto approveByChannel(@RequestBody @Validated FinanceWithdrawApproveChannelEntity entity) throws Exception {
        if (!PayConstants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus()) && !PayConstants.CALLBACE_FAIL_STATUS.equals(entity.getCallbackStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
//        if (Constants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus()) && !Strings.isNullOrEmpty(entity
//        .getChannelSerial())) {
//            return BaseResultDto.error(Constants.NOT_PERMIT);
//        }
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/submits/channel")
    @FeignClientAnnotation
    public BaseResultDto approveBySubmits(@RequestBody @Validated FinanceWithdrawApproveChannelSubmitsEntity entity) throws Exception {
        if (!PayConstants.PASSED_STATUS.equals(entity.getSubmitStatus()) && !PayConstants.REJECTED_STATUS.equals(entity.getSubmitStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
//        if (Constants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus()) && !Strings.isNullOrEmpty(entity
//        .getChannelSerial())) {
//            return BaseResultDto.error(Constants.NOT_PERMIT);
//        }
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/approve/channels")
    public BaseResultDto approveByChannels(@RequestBody @Validated FinanceWithdrawApproveChannelsEntity entity) throws Exception {
        if (!PayConstants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus()) && !PayConstants.CALLBACE_FAIL_STATUS.equals(entity.getCallbackStatus())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
//        if (Constants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus()) && !Strings.isNullOrEmpty(entity
//        .getChannelSerial())) {
//            return BaseResultDto.error(Constants.NOT_PERMIT);
//        }
        financeWithdrawService.approve(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/manager/delete")
    @FeignClientAnnotation
    public BaseResultDto delete(@RequestBody @Validated FinanceWithdrawDeleteEntity entity) throws Exception {
        financeWithdrawService.delete(entity);
        return BaseResultDto.success();
    }

    @PostMapping("/custom/searcher/list")
    @FeignClientAnnotation
    public ResultWithPagerDto<FinanceWithdrawDto> customSearcherList(@RequestBody @Validated FinanceWithdrawSearchListEntity entity) throws Exception {
        if (entity.getChannelCodes() == null || entity.getChannelCodes().size() <= 0) {
            entity.setChannelCodes(null);
        }
        ResultWithPagerDto<FinanceWithdrawDto> resultWithPagerDto = financeWithdrawService.searchList(entity);
        return resultWithPagerDto;
    }


    @PostMapping("/manager/searcher/list")
    @FeignClientAnnotation
    public ResultWithPagerDto<FinanceWithdrawDto> searcherList(@RequestBody @Validated FinanceWithdrawSearchListEntity entity) throws Exception {

        if (entity.getStartDate() != null) {
            entity.setStartDate(DateUtil.parseDate(entity.getStartDate()));
        }
        if (entity.getEndDate() != null) {
            Date endDate = DateUtil.operationDay(entity.getEndDate(), 1);
            entity.setEndDate(DateUtil.parseDate(endDate));
        }

        if (entity.getStartSubmitDate() != null) {
            entity.setStartSubmitDate(DateUtil.parseDate(entity.getStartSubmitDate()));
        }
        if (entity.getEndSubmitDate() != null) {
            Date endDate = DateUtil.operationDay(entity.getEndSubmitDate(), 1);
            entity.setEndSubmitDate(DateUtil.parseDate(endDate));
        }

        if (entity.getChannelCodes() == null || entity.getChannelCodes().size() <= 0) {
            entity.setChannelCodes(null);
        }

        ResultWithPagerDto<FinanceWithdrawDto> resultWithPagerDto = financeWithdrawService.searchList(entity);
        return resultWithPagerDto;
    }

    @PostMapping("/manager/searcher/list/export")
    @FeignClientAnnotation
    public BaseResultDto<List<FinanceWithdrawDto>> searcherListExport(@RequestBody @Validated FinanceWithdrawSearchListEntity entity, CustomInfoEntity infoEntity) throws Exception {

        if (entity.getStartDate() != null) {
            entity.setStartDate(DateUtil.parseDate(entity.getStartDate()));
        }
        if (entity.getEndDate() != null) {
            Date endDate = DateUtil.operationDay(entity.getEndDate(), 1);
            entity.setEndDate(DateUtil.parseDate(endDate));
        }

        if (entity.getStartSubmitDate() != null) {
            entity.setStartSubmitDate(DateUtil.parseDate(entity.getStartSubmitDate()));
        }
        if (entity.getEndSubmitDate() != null) {
            Date endDate = DateUtil.operationDay(entity.getEndSubmitDate(), 1);
            entity.setEndSubmitDate(DateUtil.parseDate(endDate));
        }
        if (PrefixEnum.PREFIX_SALE.equals(infoEntity.getPrefix())) {
            entity.setStamp(infoEntity.getIbInfo().getStamp());
        } else {
            entity.setStamp(null);
        }

        if (entity.getChannelCodes() == null || entity.getChannelCodes().size() <= 0) {
            entity.setChannelCodes(null);
        }
        return financeWithdrawService.searchListExport(entity);
    }

    @PostMapping("/manager/export/ids")
    @FeignClientAnnotation
    public BaseResultDto<List<FinanceWithdrawDto>> searcherByIdsExport(@RequestBody @Validated FinanceWithdrawSearchByIdsEntity entity, CustomInfoEntity infoEntity) throws Exception {
        if (PrefixEnum.PREFIX_SALE.equals(infoEntity.getPrefix())) {
            entity.setStamp(infoEntity.getIbInfo().getStamp());
        } else {
            entity.setStamp(null);
        }
        return financeWithdrawService.searcherByIdsExport(entity);
    }

    @PostMapping("/manager/searcher/single")
    @FeignClientAnnotation
    public BaseResultDto<FinanceWithdrawDto> searcherSingle(@RequestBody @Validated SingleLongEntity entity) throws Exception {
        FinanceWithdrawDto financeWithdrawDto = financeWithdrawService.searchSingle(entity.getId());
        return BaseResultDto.success(financeWithdrawDto);
    }


    private void setSalesId(Long id, FinanceWithdrawBaseAddEntity entity) throws Exception {
        UserInfoTable userInfoTable = userInfoService.getById(id);
        entity.setSalesId(userInfoTable.getSalesId());
    }

    /**
     * 获取所有可出金通道
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/manager/remit/channel")
    @FeignClientAnnotation
    public BaseResultDto<List<SysRemitChannelApiDto>> remitChannel() throws Exception {

        return BaseResultDto.success(sysRemitChannelService.searchWithdrawApi());
    }

    /**
     * 身份认证获取web链接
     * @param entity
     * @return
     *//*
    @PostMapping("/getWebsdkLink")
    public BaseResultDto getWebsdkLink(@RequestBody WebsdkLinkAliEntity entity, CustomInfoEntity infoEntity) throws Exception {
        return financeWithdrawService.getWebsdkLink(entity, infoEntity.getId());
    }*/


}
