package com.zksy.web.controller.basicData;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.common.core.domain.AjaxResult;
import com.zksy.system.basicData.domain.*;
import com.zksy.system.basicData.domain.vo.CheckResultVo;
import com.zksy.system.basicData.mapper.*;
import com.zksy.system.basicData.service.CrmOverviewDataService;
import com.zksy.system.config.StrMapperMap;
import com.zksy.utils.SearchUtil;
import lombok.SneakyThrows;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/crmOverviewData")
public class CrmOverviewDataController {
    @Autowired
    private CrmOverviewDataService crmOverviewDataService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private StrMapperMap strMapperMap;
    @Autowired
    private CrmHighTechZoneEnterprisesMapper crmHighTechZoneEnterprisesMapper;
    @Autowired
    private CrmEnterpriseTaxPaymentInfoMapper crmEnterpriseTaxPaymentInfoMapper;

    @SneakyThrows
    @GetMapping("/checkByList")
    public AjaxResult checkByList(String listJSON, Integer pageNum, Integer pageSize, String conditionJson) {
        List list = objectMapper.readValue(listJSON, List.class);
        Page<CrmHighTechZoneEnterprises> page = crmHighTechZoneEnterprisesMapper.selectPage(new Page<CrmHighTechZoneEnterprises>(pageNum, pageSize), SearchUtil.parseWhereSql(conditionJson));
        List<CrmHighTechZoneEnterprises> enterprises = page.getRecords();
//        List<CrmHighTechZoneEnterprises> enterprises = crmHighTechZoneEnterprisesMapper.selectList(null);
        List<CheckResultVo> vos = enterprises.stream().map(q -> {
            CheckResultVo vo = new CheckResultVo();
            vo.setEnterpriseName(q.getEnterpriseName());
            vo.setUniCode(q.getUnifiedSocialCreditCode());
            return vo;
        }).collect(Collectors.toList());
        list.forEach(q -> {
            Object mapper = strMapperMap.contianer.get(q);
            if (mapper != null) {
                processCase((String) q, mapper, vos);
            }
        });
        AjaxResult result = new AjaxResult(200, "success", vos);
        result.put("total", page.getTotal());
        return result;
//        return crmOverviewDataService.checkByList(list);
    }
    private void processCase(String q, Object mapper, List<CheckResultVo> vos) {
        switch (q) {
            case "a":
                processA(mapper, vos);
                break;
            case "b1":
                processCrmOutputValue(vos, q, CrmOutputValue::getFirstQuarterAmount, CheckResultVo::setB1);
                break;
            case "b2":
                processCrmOutputValue(vos, q, CrmOutputValue::getSecondQuarterAmount, CheckResultVo::setB2);
                break;
            case "b3":
                processCrmOutputValue(vos, q, CrmOutputValue::getThirdQuarterAmount, CheckResultVo::setB3);
                break;
            case "b4":
                processCrmOutputValue(vos, q, CrmOutputValue::getFourthQuarterAmount, CheckResultVo::setB4);
                break;
            case "c1":
                processCrmEnterpriseTaxPaymentInfo(vos, q, CrmEnterpriseTaxPaymentInfo::getFirstQuarterAmount, CheckResultVo::setC1);
                break;
            case "c2":
                processCrmEnterpriseTaxPaymentInfo(vos, q, CrmEnterpriseTaxPaymentInfo::getSecondQuarterAmount, CheckResultVo::setC2);
                break;
            case "c3":
                processCrmEnterpriseTaxPaymentInfo(vos, q, CrmEnterpriseTaxPaymentInfo::getThirdQuarterAmount, CheckResultVo::setC3);
                break;
            case "c4":
                processCrmEnterpriseTaxPaymentInfo(vos, q, CrmEnterpriseTaxPaymentInfo::getFourthQuarterAmount, CheckResultVo::setC4);
                break;
            case "dd":
                processDd(mapper, vos);
                break;
            case "de":
                processDe(mapper, vos);
                break;
            case "df":
                processDf(mapper, vos);
                break;
            case "dg":
                processDg(mapper, vos);
                break;
            case "dh":
                processDh(mapper, vos);
                break;
            case "di":
                processDi(mapper, vos);
                break;
            case "dj":
                processDj(mapper, vos);
                break;
            case "dk":
                processDk(mapper, vos);
                break;
            case "dl":
                processDl(mapper, vos);
                break;
            case "dm":
                processDm(mapper, vos);
                break;
            case "dn":
                processDn(mapper, vos);
                break;
            case "dp":
                processDp(mapper, vos);
                break;
            case "dq":
                processDq(mapper, vos);
                break;
            case "dr":
                processDr(mapper, vos);
                break;
            case "ds":
                processDs(mapper, vos);
                break;
            case "dt":
                processDt(mapper, vos);
                break;
            case "du":
                processDu(mapper, vos);
                break;
            case "dv":
                processDv(mapper, vos);
                break;
            default:
                // 处理默认情况
                break;
        }
    }

    private void processA(Object mapper, List<CheckResultVo> vos) {
        CrmHighTechZoneEnterprisesMapper o = (CrmHighTechZoneEnterprisesMapper) mapper;
        List<String> deductionPoints = o.getDeductionPoints();
        vos.forEach(w1 -> {
            deductionPoints.forEach(e -> {
                if (Objects.equals(w1.getUniCode(), e)) {
                    w1.setA(w1.getA() + 1);
                }
            });
        });
    }

    private void processCrmOutputValue(
            List<CheckResultVo> vos,
            String q,
            Function<CrmOutputValue, String> amountFunction,
            BiConsumer<CheckResultVo, String> setterFunction
    ) {
        CrmOutputValueMapper o = (CrmOutputValueMapper) strMapperMap.contianer.get(q);
        LambdaQueryWrapper<CrmOutputValue> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrmOutputValue::getAnnualAmount, LocalDate.now().getYear());
        List<CrmOutputValue> crmOutputValues = o.selectList(wrapper);
        Map<String, CrmOutputValue> crmOutputValueMap = crmOutputValues.stream()
                .collect(Collectors.toMap(CrmOutputValue::getUnifiedSocialCreditCode, v -> v));
        vos.forEach(w1 -> {
            CrmOutputValue crmOutputValue = crmOutputValueMap.get(w1.getUniCode());
            if (crmOutputValue != null) {
                setterFunction.accept(w1, amountFunction.apply(crmOutputValue));
            }
        });
    }

    private void processCrmEnterpriseTaxPaymentInfo(
            List<CheckResultVo> vos,
            String q,
            Function<CrmEnterpriseTaxPaymentInfo, String> amountFunction,
            BiConsumer<CheckResultVo, String> setterFunction
    ) {
        CrmEnterpriseTaxPaymentInfoMapper o = (CrmEnterpriseTaxPaymentInfoMapper) strMapperMap.contianer.get(q);
        LambdaQueryWrapper<CrmEnterpriseTaxPaymentInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrmEnterpriseTaxPaymentInfo::getAnnualAmount, LocalDate.now().getYear());
        List<CrmEnterpriseTaxPaymentInfo> list = o.selectList(wrapper);
        Map<String, CrmEnterpriseTaxPaymentInfo> map = list.stream()
                .collect(Collectors.toMap(CrmEnterpriseTaxPaymentInfo::getUnifiedSocialCreditCode, v -> v));
        vos.forEach(w1 -> {
            CrmEnterpriseTaxPaymentInfo value = map.get(w1.getUniCode());
            if (value != null) {
                setterFunction.accept(w1, amountFunction.apply(value));
            }
        });
    }
    private void processDd(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmChangeRecordInformationMapper.class,
                CrmChangeRecordInformation::getUnifiedSocialCreditCode,
                CheckResultVo::setDd);
    }

    private void processDe(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmAdministrativeLicenseMapper.class,
                CrmAdministrativeLicense::getUnifiedSocialCreditCode,
                CheckResultVo::setDe);
    }

    private void processDf(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmAdministrativeConfirmationMapper.class,
                CrmAdministrativeConfirmation::getUnifiedSocialCreditCode,
                CheckResultVo::setDf);
    }

    private void processDg(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmListedCompanyMapper.class,
                CrmListedCompany::getUnifiedSocialCreditCode,
                CheckResultVo::setDg);
    }

    private void processDh(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmNewEnterpriseRecognitionDetailsMapper.class,
                CrmNewEnterpriseRecognitionDetails::getUnifiedSocialCreditCode,
                CheckResultVo::setDh);
    }

    private void processDi(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmEnterpriseTechnologyRndSummaryMapper.class,
                CrmEnterpriseTechnologyRndSummary::getUnifiedSocialCreditCode,
                CheckResultVo::setDi);
    }
    private void processDj(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmTechnologyEnterprisesMapper.class,
                CrmTechnologyEnterprises::getUnifiedSocialCreditCode,
                CheckResultVo::setDj);
    }

    private void processDk(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmCertifiedTechnologyEnterpriseMapper.class,
                CrmCertifiedTechnologyEnterprise::getUnifiedSocialCreditCode,
                CheckResultVo::setDk);
    }

    private void processDl(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmSoftwareCopyrightInformationMapper.class,
                CrmSoftwareCopyrightInformation::getUnifiedSocialCreditCode,
                CheckResultVo::setDl);
    }

    private void processDm(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmPatentInformationMapper.class,
                CrmPatentInformation::getUnifiedSocialCreditCode,
                CheckResultVo::setDm);
    }

    private void processDn(Object mapper, List<CheckResultVo> vos) {
        processCommon(mapper, vos, CrmCreditRedlistInfoMapper.class,
                CrmCreditRedlistInfo::getUnifiedSocialCreditCode,
                CheckResultVo::setDn);
    }

    private void processDp(Object mapper, List<CheckResultVo> vos) {
        CrmEnterpriseTaxClassificationInfoMapper crmEnterpriseTaxClassificationInfoMapper = (CrmEnterpriseTaxClassificationInfoMapper) mapper;
        List<CrmEnterpriseTaxClassificationInfo> list = crmEnterpriseTaxClassificationInfoMapper.selectList(null);
        Map<String, String> map = list.stream()
                .collect(Collectors.toMap(CrmEnterpriseTaxClassificationInfo::getUnifiedSocialCreditCode,
                        CrmEnterpriseTaxClassificationInfo::getTaxCreditRating));
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(w1::setDp));
    }

    private void processDq(Object mapper, List<CheckResultVo> vos) {
        CrmAbnormalTaxInformationMapper crmAbnormalTaxInformationMapper = (CrmAbnormalTaxInformationMapper) mapper;
        List<CrmAbnormalTaxInformation> list = crmAbnormalTaxInformationMapper.selectList(null);
        Map<String, String> map = list.stream()
                .collect(Collectors.toMap(CrmAbnormalTaxInformation::getUnifiedSocialCreditCode,
                        CrmAbnormalTaxInformation::getIsAbnormalTaxpayer));
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(w1::setDq));
    }

    private void processDr(Object mapper, List<CheckResultVo> vos) {
        CrmEnterpriseSocialSecurityInfoMapper crmEnterpriseSocialSecurityInfoMapper = (CrmEnterpriseSocialSecurityInfoMapper) mapper;
        List<CrmEnterpriseSocialSecurityInfo> list = crmEnterpriseSocialSecurityInfoMapper.selectList(null);
        Map<String, String> map = list.stream()
                .filter(q->q.getRemarks().contains(String.valueOf(LocalDate.now().getYear())))
                .collect(Collectors.toMap(CrmEnterpriseSocialSecurityInfo::getUnifiedSocialCreditCode,
                        CrmEnterpriseSocialSecurityInfo::getAvgInsuredPersonsBand));
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(q->{
                    w1.setDr(Long.parseLong(q));
                }));
    }

    private void processDs(Object mapper, List<CheckResultVo> vos) {
        CrmEnvironmentalCreditEvaluationNotificationMapper crmEnvironmentalCreditEvaluationNotificationMapper = (CrmEnvironmentalCreditEvaluationNotificationMapper) mapper;
        List<CrmEnvironmentalCreditEvaluationNotification> list = crmEnvironmentalCreditEvaluationNotificationMapper.selectList(null);
        Map<String, String> map = list.stream()
                .collect(Collectors.toMap(CrmEnvironmentalCreditEvaluationNotification::getUnifiedSocialCreditCode,
                        CrmEnvironmentalCreditEvaluationNotification::getCreditRating));
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(w1::setDs));
    }

    private void processDt(Object mapper, List<CheckResultVo> vos) {
        CrmNationalPublicCreditEvaluationInformationMapper crmNationalPublicCreditEvaluationInformationMapper = (CrmNationalPublicCreditEvaluationInformationMapper) mapper;
        List<CrmNationalPublicCreditEvaluationInformation> list = crmNationalPublicCreditEvaluationInformationMapper.selectList(null);
        Map<String, String> map = list.stream()
                .collect(Collectors.toMap(CrmNationalPublicCreditEvaluationInformation::getUnifiedSocialCreditCode,
                        CrmNationalPublicCreditEvaluationInformation::getEvaluationGrade));
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(w1::setDt));
    }

    private void processDu(Object mapper, List<CheckResultVo> vos) {
        CrmRatingAgencyInfoMapper crmRatingAgencyInfoMapper = (CrmRatingAgencyInfoMapper) mapper;
        List<CrmRatingAgencyInfo> list = crmRatingAgencyInfoMapper.selectList(null);
        Map<String, Long> map = list.stream()
                .filter(q->q.getRatingDate().contains(String.valueOf(LocalDate.now().getYear())))
                .filter(q->"AAA".equals(q.getCreditRating()))
                .collect(
                        Collectors.groupingBy(
                                CrmRatingAgencyInfo::getUnifiedSocialCreditCode,
                                Collectors.counting()
                        )
                );
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(w1::setDu));
    }

    private void processDv(Object mapper, List<CheckResultVo> vos) {
        CrmEnterpriseCreditRatingMapper crmEnterpriseCreditRatingMapper = (CrmEnterpriseCreditRatingMapper) mapper;
        List<CrmEnterpriseCreditRating> list = crmEnterpriseCreditRatingMapper.selectList(null);
        Map<String, Long> map = list.stream()
                .collect(Collectors.toMap(CrmEnterpriseCreditRating::getUnifiedSocialCreditCode,
                        CrmEnterpriseCreditRating::getRatingScore));
        vos.forEach(w1 -> Optional.ofNullable(map.get(w1.getUniCode()))
                .ifPresent(w1::setDv));
    }

    private <T extends BaseMapper<R>, R> void processCommon(Object mapper, List<CheckResultVo> vos, Class<T> mapperClass,
                                                               Function<R, String> keyExtractor,
                                                               BiConsumer<CheckResultVo, Long> setter) {
        T typedMapper = mapperClass.cast(mapper);
        List<R> list = typedMapper.selectList(null);
        Map<String, Long> map = list.stream()
                .collect(Collectors.groupingBy(keyExtractor, Collectors.counting()));

        vos.forEach(w1 -> {
            Optional.ofNullable(map.get(w1.getUniCode()))
                    .ifPresent(count -> setter.accept(w1, count));
        });
    }
}
