package com.ecep.contract.service.tasker;

import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;

import com.ecep.contract.CustomerFileType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.ds.contract.service.ContractService;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.ui.Tasker;
import com.fasterxml.jackson.databind.JsonNode;

public class CompanyCustomerNextSignDateTask extends Tasker<Object> implements WebSocketServerTasker {

    private CompanyCustomer customer;

    @Override
    public void init(JsonNode argsNode) {
        int customerId = argsNode.get(0).asInt();
        customer = getCachedBean(CompanyCustomerService.class).getById(customerId);
    }

    CompanyCustomerFileService getCompanyCustomerFileService() {
        return getCachedBean(CompanyCustomerFileService.class);
    }

    CompanyCustomerService getCompanyCustomerService() {
        return getCachedBean(CompanyCustomerService.class);
    }

    ContractService getContractService() {
        return getCachedBean(ContractService.class);
    }

    @Override
    protected Object execute(MessageHolder holder) throws Exception {
        holder.info("开始计算客户下一个评价日期");

        LocalDate nextSignDate = calculateNextSignDate(holder);

        if (nextSignDate != null) {
            holder.info("下一个评价日期：" + nextSignDate);
        } else {
            holder.warn("无法计算下一个评价日期");
        }

        return nextSignDate;
    }

    private LocalDate calculateNextSignDate(MessageHolder holder) {
        LocalDate miniContractDate = LocalDate.of(2022, 1, 1);

        // 检索全部合同
        ContractService contractService = getContractService();
        List<Contract> contractList = contractService.findAllByCompanyCustomer(customer, null, null);
        if (contractList.isEmpty()) {
            holder.error("未发现已登记的合同");
            return null;
        }

        holder.info("发现" + contractList.size() + "份合同");

        // 检索评估表
        List<CompanyCustomerFile> files = getCompanyCustomerFileService().findAllByCustomerAndType(customer,
                CustomerFileType.EvaluationForm);
        CompanyCustomerFile latestFile = files.stream()
                .filter(v -> v.getSignDate() != null && v.isValid())
                .max(Comparator.comparing(CompanyCustomerFile::getSignDate))
                .orElse(null);

        // 没有有效的评估表的评价日期
        if (latestFile == null) {
            holder.warn("未发现有效的评估表");
            // 返回最早的合同日期
            Contract firstContract = contractList.stream()
                    .filter(v -> v.getSetupDate() != null && !v.getSetupDate().isBefore(miniContractDate))
                    .min(Comparator.comparing(Contract::getSetupDate))
                    .orElse(null);

            if (firstContract == null) {
                holder.error("最早的合同不存在");
                return null;
            }

            LocalDate setupDate = firstContract.getSetupDate();
            holder.info("选择最早的合同：" + firstContract.getCode() + "，日期：" + setupDate);
            return setupDate.plusDays(-7);
        }

        // 有有效的评估表，计算下一个日期
        LocalDate lastSignDate = latestFile.getSignDate();
        holder.info("最近一次有效的评估表日期：" + lastSignDate);

        // 查找最近一次评估日期之后的合同
        Contract firstContractAfter = contractList.stream()
                .filter(v -> v.getSetupDate() != null && v.getSetupDate().isAfter(lastSignDate))
                .min(Comparator.comparing(Contract::getSetupDate))
                .orElse(null);

        if (firstContractAfter == null) {
            holder.warn("没有找到在" + lastSignDate + "之后的合同");
            // 返回当前日期作为建议
            return LocalDate.now();
        }

        LocalDate setupDate = firstContractAfter.getSetupDate();
        holder.info("找到最近一次评估日期后的第一个合同：" + firstContractAfter.getCode() + "，日期：" + setupDate);

        return setupDate.plusDays(-7);
    }
}