package com.zksy.system.basicData.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.common.core.domain.AjaxResult;
import com.zksy.common.utils.DeleteTableUtils;
import com.zksy.system.basicData.domain.CrmOutputValue;
import com.zksy.system.basicData.domain.vo.MonitorVo;
import com.zksy.system.basicData.domain.vo.QuarterYoYVo;
import com.zksy.system.basicData.mapper.CrmOutputValueMapper;
import com.zksy.system.basicData.service.CrmOutputValueService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.time.Year;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 企业产值Service业务层处理
 *
 * @author sy
 * @date 2024-06-04
 */
@Service
public class CrmOutputValueServiceImpl extends ServiceImpl<CrmOutputValueMapper, CrmOutputValue> implements CrmOutputValueService {
    @Resource
    private CrmOutputValueMapper mapper;
    private static final String CURRENT_YEAR = String.valueOf(Year.now().getValue());
    private static final String LAST_YEAR = String.valueOf(Year.now().getValue() - 1);


    @Override
    @Transactional
    public AjaxResult deleteAll() {
        DeleteTableUtils<CrmOutputValue> utils = new DeleteTableUtils<>();
        utils.del(CrmOutputValue::getId, mapper);
        return AjaxResult.success("全部删除成功");
    }

    @Override
    public AjaxResult getListYearOrQuarter() {
        ArrayList<MonitorVo> resVo = new ArrayList<>();
        for (CrmOutputValue crmOutputValue : this.list()) {
            MonitorVo monitorVo = new MonitorVo();
            monitorVo.setEnterpriseName(crmOutputValue.getEnterpriseName());
            monitorVo.setUnifiedSocialCreditCode(crmOutputValue.getUnifiedSocialCreditCode());
            Double firstQuarterAmount = Optional.ofNullable(crmOutputValue.getFirstQuarterAmount())
                    .filter(s -> !s.isEmpty())
                    .map(Double::valueOf)
                    .orElse(0.0);
            Double secondQuarterAmount = Optional.ofNullable(crmOutputValue.getSecondQuarterAmount())
                    .filter(s -> !s.isEmpty())
                    .map(Double::valueOf)
                    .orElse(0.0);
            Double thirdQuarterAmount = Optional.ofNullable(crmOutputValue.getThirdQuarterAmount())
                    .filter(s -> !s.isEmpty())
                    .map(Double::valueOf)
                    .orElse(0.0);
            Double fourthQuarterAmount = Optional.ofNullable(crmOutputValue.getFourthQuarterAmount())
                    .filter(s -> !s.isEmpty())
                    .map(Double::valueOf)
                    .orElse(0.0);
            Double total = firstQuarterAmount + secondQuarterAmount + thirdQuarterAmount + fourthQuarterAmount;
            Optional.ofNullable(crmOutputValue.getAnnualAmount())
                    .ifPresent(annualAmount -> {
                        if (CURRENT_YEAR.equals(annualAmount)) {
                            monitorVo.setCurrentYearTotal(total);
                        } else if (LAST_YEAR.equals(annualAmount)) {
                            monitorVo.setLastYearTotal(total);
                        }
                    });
            resVo.add(monitorVo);
        }
        LinkedHashMap<String, MonitorVo> map = new LinkedHashMap<>();
        for (MonitorVo vo : resVo) {
            if (!map.containsKey(vo.getUnifiedSocialCreditCode())) {
                map.put(vo.getUnifiedSocialCreditCode(), vo);
            } else {
                MonitorVo existingVo = map.get(vo.getUnifiedSocialCreditCode());
                Optional.ofNullable(vo.getCurrentYearTotal()).ifPresent(existingVo::setCurrentYearTotal);
                Optional.ofNullable(vo.getLastYearTotal()).ifPresent(existingVo::setLastYearTotal);
            }
        }
        List<MonitorVo> vos = new ArrayList<>(map.values())
                .stream()
                .sorted(
                        (a, b) ->
                                (Optional.ofNullable(b.getLastYearTotal()).map(Double::intValue).orElse(0)) - (Optional.ofNullable(a.getLastYearTotal()).map(Double::intValue).orElse(0))
                )
                .collect(Collectors.toList());
        return AjaxResult.success(vos);
    }

    @Override
    public AjaxResult getListByQuarterYoY(Integer quarter) {
//        int lastQuarter = LocalDate.now().get(IsoFields.QUARTER_OF_YEAR)-1 == 0?4:LocalDate.now().get(IsoFields.QUARTER_OF_YEAR)-1;
        int lastQuarter = quarter;
        ArrayList<QuarterYoYVo> resList = new ArrayList<>();
        List<CrmOutputValue> valueList = this.list();
        @SuppressWarnings("unchecked")
        List<MonitorVo> monitorVos = (List<MonitorVo>) this.getListYearOrQuarter().get("data");
        monitorVos.forEach(q->{
            QuarterYoYVo quarterYoYVo = new QuarterYoYVo();
            quarterYoYVo.setEnterpriseName(q.getEnterpriseName());
            quarterYoYVo.setUnifiedSocialCreditCode(q.getUnifiedSocialCreditCode());
            if(lastQuarter == 1){
                setYoY(q, valueList, quarterYoYVo, "firstQuarterAmount");
            }else if(lastQuarter == 2){
                setYoY(q, valueList, quarterYoYVo, "secondQuarterAmount");
            }else if(lastQuarter == 3){
                setYoY(q, valueList, quarterYoYVo, "thirdQuarterAmount");
            }else if(lastQuarter == 4){
                setYoY(q, valueList, quarterYoYVo, "fourthQuarterAmount");
            }
            resList.add(quarterYoYVo);
        });
        resList.sort( (a,b)->(Optional.ofNullable(b.getLastQuarterLastTotal()).map(Double::intValue).orElse(0)) - (Optional.ofNullable(a.getLastQuarterLastTotal()).map(Double::intValue).orElse(0)));
        return AjaxResult.success(resList);
    }

    private static void setYoY(MonitorVo q, List<CrmOutputValue> valueList, QuarterYoYVo quarterYoYVo,String field) {
        valueList.stream()
                .filter(c-> Objects.equals(c.getAnnualAmount(), CURRENT_YEAR))
                .filter(c-> Objects.equals(c.getUnifiedSocialCreditCode(), q.getUnifiedSocialCreditCode()))
                .findFirst()
                .ifPresent(w->{
                    Double k1 = getQuarterAmount(w, field);
                    quarterYoYVo.setLastQuarterCurrentTotal(k1);
                });
        valueList.stream()
                .filter(c-> Objects.equals(c.getAnnualAmount(), LAST_YEAR))
                .filter(c-> Objects.equals(c.getUnifiedSocialCreditCode(), q.getUnifiedSocialCreditCode()))
                .findFirst()
                .ifPresent(w->{
                    Double k2 = getQuarterAmount(w, field);
                    quarterYoYVo.setLastQuarterLastTotal(k2);
                });
    }
    private static String getFieldValue(CrmOutputValue w, String fieldName) {
        try {
            Field field = w.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return (String) field.get(w);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            return null;
        }
    }
    private static Double getQuarterAmount(CrmOutputValue w, String quarterFieldName) {
        return Optional.ofNullable(getFieldValue(w, quarterFieldName))
                .filter(s -> !s.isEmpty())
                .map(Double::valueOf)
                .orElse(0.0);
    }
}
