package com.trade.service.contract.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.trade.common.constant.HttpStatus;
import com.trade.common.exception.ServiceException;
import com.trade.service.contract.dto.*;
import com.trade.service.contract.entity.FddAccount;
import com.trade.service.contract.entity.FddSignFile;
import com.trade.service.contract.service.FddAccountService;
import com.trade.service.contract.service.FddSignFileService;
import com.trade.service.contract.service.SignAccountCreator;
import com.trade.service.contract.util.SignPubUtil;
import com.trade.service.contract.util.fadada.FaDaDaUtil;
import com.trade.service.contract.util.fadada.dto.FaDaDaSignCallback;
import com.trade.service.contract.util.fadada.entity.FddSignData;
import com.trade.service.filestorage.entity.TFileStorage;
import com.trade.service.filestorage.service.TFileStorageService;
import com.trade.service.filestorage.util.oss.OSSUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import com.trade.service.contract.constant.ContractConstant;
import com.trade.service.contract.service.SignPlatformService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;

@Slf4j
@Service(ContractConstant.CONTRACT_PLATFORM_SERVICE_NAME_FADADA)
public class FaDaDaContractServiceImpl implements SignPlatformService, SignAccountCreator {

    @Resource
    private FddAccountService fddAccountService;
    @Resource
    private OSSUtil ossUtil;
    @Resource
    private TFileStorageService tFileStorageService;
    @Resource
    private FddSignFileService fddSignFileService;

    @Override
    @Transactional
    public ContractSignOutput signContract(ContractSignInput signInput) {
        log.info("进入法大大合同签署流程,业务场景:{},签署失效时长:{}hour", signInput.getBizScene(), signInput.getSignValidTime());
        ContractSignOutput output = new ContractSignOutput();
        // 先统一创建账号，有任意创建失败则直接失败，不再进行后续操作
        String flowId = UUID.randomUUID().toString().replaceAll("-", "");
        Map<String, String> accountMap = getAccountMap(signInput.getSigneInfoList());
        // 上传签署文件
        output.setItems(uploadSignFileAndSetPositions(signInput, flowId, accountMap));
        output.setFlowId(flowId);
        log.info("法大大合同签署发起成功");
        return output;
    }

    private List<ContractSignOutputItem> uploadSignFileAndSetPositions(ContractSignInput signInput, String flowId,
            Map<String, String> accountMap) {
        for (ContractSignInfo signInfo : signInput.getSigneInfoList()) {
            TFileStorage fileStorage = tFileStorageService.getById(signInfo.getFileId());
            if (null == fileStorage) {
                throw new ServiceException("文件不存在！", HttpStatus.BAD_REQUEST);
            }
            String localFilePath = "/data/tmpFile/" + fileStorage.getName();
            File tempFile = ossUtil.download2LocalFile(fileStorage.getPath(), localFilePath);
            // 上传签署文件
            String contractId = UUID.randomUUID().toString().replaceAll("-", "");
            FaDaDaUtil.uploadContract(contractId, fileStorage.getOriginalName(), tempFile);
            fddSignFileService.save(FddSignFile.builder().rawFileId(signInfo.getFileId()).thirdFileId(contractId)
                    .fileName(fileStorage.getName()).flowId(flowId).build());
            // 删除临时文件
            SignPubUtil.deleteFile(tempFile);
        }
        // todo 待开发中间服务
        accountMap.forEach((key, value) -> {
            FaDaDaUtil.manualBatchSign(value, getSignFileList(key), signInput.getBizScene());
        });
        return null;
    }

    private List<FddSignData> getSignFileList(String key) {
        // todo 待实现
        return null;
    }

    public Map<String, String> getAccountMap(List<ContractSignInfo> signeInfoList) {
        return SignPubUtil.getAccountMapFromSignInfo(signeInfoList, this);
    }

    @Override
    public void handleCallback(ContractSignCallBack callback) {
        if (null == callback) {
            throw new ServiceException("回调参数为空！", HttpStatus.BAD_REQUEST);
        }
        FaDaDaSignCallback data = (FaDaDaSignCallback) callback;
        if (!"1".equals(data.getSignStatus())) {
            log.warn("回调状态非法，跳过处理");
            return;
        }
        // todo
        // 下载文件
        FaDaDaUtil.downloadContract(data.getContractId());
    }

    @Override
    public String creatPersonalAccount(ContractSigner contractSigner) {
        return creatFddAccount(contractSigner.getSignerIdNo(), contractSigner.getSignerIdType(),
                contractSigner.getSigner(), contractSigner.getMobile(), FaDaDaUtil.ACCOUNT_TYPE_PERSONAL);
    }

    @Override
    public String createOrgAccount(ContractSeal contractSeal) {
        if (null == contractSeal || StrUtil.isBlank(contractSeal.getSealName())
                || StrUtil.isBlank(contractSeal.getSealIdNo())) {
            log.error(JSON.toJSONString(contractSeal));
            throw new ServiceException("机构帐号信息不全！", HttpStatus.BAD_REQUEST);
        }
        return creatFddAccount(contractSeal.getSealIdNo(), contractSeal.getSealIdType(), contractSeal.getSealName(),
                contractSeal.getSigner().getMobile(), FaDaDaUtil.ACCOUNT_TYPE_COMPANY);
    }

    private String creatFddAccount(String idNo, String idType, String name, String phone, String accountType) {
        FddAccount fddAccount = fddAccountService.getByIdNo(idNo);
        if (null != fddAccount) {// 如果没有认证通过，先制定一个临时方案解决，后续再优化
            return fddAccount.getThirdAccountId();
        }
        // 注册企业账号
        String accountId = FaDaDaUtil.registerAccount(idNo, accountType);
        // String authUrl = FaDaDaUtil.getAuthUrlByIdentityInfo(accountId, accountType, name, idNo, phone);
        String authUrl = FaDaDaUtil.getAuthUrl(accountType, accountId, null);
        System.out.println(authUrl);
        // 通过短信发送认证链接
        // todo 配置短信模板...
        // 保存账号信息
        fddAccount = FddAccount.builder().idNo(idNo).idType(idType).name(name).phone(phone).thirdAccountId(accountId)
                .build();
        fddAccountService.save(fddAccount);
        return accountId;
    }
}
