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

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.validation.Validator;

import com.trade.service.contract.util.SignPubUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.deepoove.poi.XWPFTemplate;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.file.ASopUtil;
import com.trade.common.validate.BeanValidators;
import com.trade.service.contract.config.ContractConfigProperties;
import com.trade.service.contract.constant.ContractConstant;
import com.trade.service.contract.dto.*;
import com.trade.service.contract.entity.SFileTemplate;
import com.trade.service.contract.service.ContractService;
import com.trade.service.contract.service.ISFileTemplateService;
import com.trade.service.contract.service.SignPlatformService;
import com.trade.service.filestorage.entity.TFileStorage;
import com.trade.service.filestorage.service.OSSFileService;
import com.trade.service.filestorage.util.FileUtil;

@Service("contractService")
public class ContractServiceImpl implements ContractService {

    private static final Logger logger = LogManager.getLogger(ContractServiceImpl.class);
    @Autowired
    private ContractConfigProperties contractConfigProperties;
    @Resource
    private Map<String, SignPlatformService> signPlatformServiceMap;
    @Resource
    private OSSFileService ossFileStorageService;
    @Resource
    protected Validator validator;
    @Resource
    private ISFileTemplateService sFileTemplateService;

    /**
     * 生成合同文本
     * 
     * @param input 生成入参
     * @return ContractGenOutput
     */
    @Override
    public ContractGenOutput generateContract(ContractGenInput input) {
        ContractGenOutput outputs = new ContractGenOutput();
        List<ContractGenOutputItem> items = new ArrayList<>();
        for (ContractGenInputItem item : input.getItems()) {
            ContractGenOutputItem outputItem = generateSingleContract(item, input.getUserId());
            items.add(outputItem);
        }
        outputs.setItems(items);
        return outputs;
    }

    /**
     * 生成单个合同
     * 
     * @param item 文件入参
     * @param userId 用户id
     * @return ContractGenOutputItem
     */
    @Override
    public ContractGenOutputItem generateSingleContract(ContractGenInputItem item, Long userId) {
        BeanValidators.validateWithException(validator, item);
        File pdfFile;
        String templateCode = item.getTemplateCode();
        SFileTemplate fileTemplate = sFileTemplateService.selectByCode(templateCode);
        String fileName = null == item.getContractName() ? fileTemplate.getDefaultName() : item.getContractName();
        try {
            String contractBaseDir = contractConfigProperties.getDir();
            // apache poi 版本至少需要5.2.2 否则报 NoClassDefFoundError
            XWPFTemplate template = getXwpfTemplate(item, fileTemplate.getSrcPath());
            String docFile = contractBaseDir.replaceAll("/+$", "") + File.separator + (null == userId ? -1L : userId)
                    + File.separator + templateCode + ".docx";
            FileUtil.createParentDirection(docFile);
            template.writeToFile(docFile);
            pdfFile = ASopUtil.doc2pdf(docFile, contractBaseDir + File.separator + fileName + ".pdf");
            FileUtil.remove(docFile);
        } catch (Exception e) {
            logger.error("生成合同失败", e);
            throw new ServiceException("生成合同失败");
        }
        // 保存未签署版本合同
        TFileStorage fileStorage = ossFileStorageService.uploadAndSaveDBRecord(pdfFile, fileTemplate.getDestDir());
        SignPubUtil.deleteFile(pdfFile);
        return new ContractGenOutputItem(item.getTemplateCode(), fileStorage.getId(), fileStorage.getPath());
    }

    private XWPFTemplate getXwpfTemplate(ContractGenInputItem item, String templateFilePath) {
        if (null != item.getConfig()) {
            // 自定义模板处理逻辑
            return XWPFTemplate.compile(templateFilePath, item.getConfig()).render(item.getParams());
        }
        return XWPFTemplate.compile(templateFilePath).render(item.getParams());
    }

    @Override
    public ContractSignOutput signContract(@Validated ContractSignInput signInputs) {
        return signPlatformServiceMap.get(ContractConstant.contractStrategyMap.get(signInputs.getSignPlatform()))
                .signContract(signInputs);
    }


}
