package com.engine.salary.entity.salaryarchive.bo;

import com.cloudstore.eccom.constant.WeaBoolAttr;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.engine.salary.common.LocalDateRange;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.constant.SalaryItemConstant;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveItemDataDTO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveTaxAgentDataDTO;
import com.engine.salary.entity.salaryarchive.po.SalaryArchiveItemPO;
import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.taxagent.po.TaxAgentEmpChangePO;
import com.engine.salary.enums.salaryarchive.SalaryArchiveItemAdjustReasonEnum;
import com.engine.salary.enums.salaryarchive.SalaryArchiveStatusEnum;
import com.engine.salary.enums.taxagent.TaxAgentEmpChangeTypeEnum;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.google.common.collect.Lists;
import com.engine.salary.util.db.IdGenerator;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.math.NumberUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 薪资档案
 * @Author: wangxiangzhong
 * @Date: 2021-11-03 10:51
 */
public class SalaryArchiveBO {

    @Override
    public String toString() {
        return "SalaryArchiveBO{}";
    }

    /**
     * 添加日期范围
     * @param weaSearchCondition
     * @param employeeId
     * @param tenantKey
     */
//    public static void addDatePickerRangeOtherParams(WeaSearchCondition weaSearchCondition, String datePickerKey, Long employeeId, String tenantKey) {
//        WeaSearchConditionItem datePickerItem = weaSearchCondition.getItems().get(datePickerKey);
//        Map<String, Object> otherParams = Maps.newHashMap();
//        otherParams.put("isRange", true);
//        otherParams.put("type", "day");
//        otherParams.put("startPlaceholder", SalaryI18nUtil.getI18nLabel(tenantKey, employeeId, 90648, "开始日期"));
//        otherParams.put("endPlaceholder", SalaryI18nUtil.getI18nLabel(tenantKey, employeeId, 90649, "结束日期"));
//        datePickerItem.setOtherParams(otherParams);
//        weaSearchCondition.getItems().put(datePickerKey, datePickerItem);
//    }

    /**
     * 构建表格动态列
     *
     * @param salaryItems
     */
    public static List<WeaTableColumn> buildSalaryArchiveTable(List<SalaryItemPO> salaryItems) {
        // 表格表头
        List<WeaTableColumn> columns = new ArrayList<>();
        WeaTableColumn idColumn = new WeaTableColumn("100px", "id", "id");
        idColumn.setIsPrimarykey(WeaBoolAttr.TRUE);
        idColumn.setDisplay(WeaBoolAttr.FALSE);
        columns.add(idColumn);
        WeaTableColumn employeeIdColumn = new WeaTableColumn("100px", "人员信息表的主键id", "employeeId");
        employeeIdColumn.setDisplay(WeaBoolAttr.FALSE);
        columns.add(employeeIdColumn);
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(85429, "姓名"), "username"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"), "taxAgentName"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86185, "分部"), "subcompanyName"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86185, "部门"), "departmentName"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86185, "工号"), "workcode"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86186, "手机号"), "mobile"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86186, "证件号码"), "mobile"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "员工状态"), "employeeStatus"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "起始发薪日期"), "payStartDate"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "最后发薪日期"), "payEndDate"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "入职日期"), "companystartdate").setDisplay(WeaBoolAttr.FALSE));
//        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "离职日期"), "dismissdate").setDisplay(WeaBoolAttr.FALSE));
        for (SalaryItemPO salaryItem : salaryItems) {
            columns.add(new WeaTableColumn("100px", salaryItem.getName(), salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX));
        }
        columns.add(new WeaTableColumn("100px", "操作", "operate"));
        return columns;
    }

    /**
     * 构建薪资档案数据
     *
     * @param salaryArchiveList
     * @param salaryArchiveItemDataList
     * @param localDateRange
     * @param allEmployeeIds
     * @param isOnlyTaxAgent
     * @return
     */
    public static List<SalaryArchiveDataDTO> buildSalaryArchiveData(List<SalaryArchivePO> salaryArchiveList,
                                                                    List<SalaryArchiveItemPO> salaryArchiveItemDataList,
                                                                    LocalDateRange localDateRange,
                                                                    List<Long> allEmployeeIds,
                                                                    boolean isOnlyTaxAgent) {
//        // 开始日期
//        Date start = localDateRange.getFromDate();
//        // 结束日期
//        Date end = localDateRange.getEndDate();
//
//        List<SalaryArchiveDataDTO> list = new ArrayList<>();
//        allEmployeeIds.forEach(e -> {
//            // 同一个人的档案数据
//            List<SalaryArchivePO> salaryArchives = salaryArchiveList.stream().filter(f -> f.getEmployeeId().equals(e)).collect(Collectors.toList());
//            List<Long> salaryArchiveIds = salaryArchives.stream().map(SalaryArchivePO::getId).collect(Collectors.toList());
//            // 同一个人的薪资项目调整历史数据
//            List<SalaryArchiveItemPO> salaryArchiveItems = salaryArchiveItemDataList.stream().filter(d -> salaryArchiveIds.contains(d.getSalaryArchiveId())).collect(Collectors.toList());
//            List<Long> salaryArchiveItemIds = salaryArchiveItems.stream().map(SalaryArchiveItemPO::getSalaryItemId).distinct().collect(Collectors.toList());
//
//            SalaryArchiveDataDTO salaryArchiveData = new SalaryArchiveDataDTO();
//            salaryArchiveData.setEmployeeId(e);
//            List<SalaryArchiveTaxAgentDataDTO> taxAgents = new ArrayList<>();
//            // 按个税扣缴义务人生效日期时间段切割
//            for (SalaryArchivePO salaryArchive : salaryArchives) {
//                Date fromDate = salaryArchive.getPayStartDate();
//                Date endDate = salaryArchive.getPayEndDate();
//                // 起始发薪日不为空，且不能比结束日期晚，最后发薪日可空可不空，但是如果不为空，就不能比开始日期早，且起始发薪日不能晚于最后发薪日
//                boolean isEnable = fromDate != null && !fromDate.after(end) && (endDate == null || (!fromDate.after(endDate) && !endDate.before(start)));
//                if (isEnable) {
//                    SalaryArchiveTaxAgentDataDTO taxAgent = new SalaryArchiveTaxAgentDataDTO();
//                    taxAgent.setTaxAgentId(salaryArchive.getTaxAgentId());
////                    taxAgent.setIncomeCategory(salaryArchive.getIncomeCategory());
//                    taxAgent.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDate.before(start) ? start : fromDate)).endDate(endDate == null || endDate.after(end) ? end : endDate).build());
//                    // 薪资项目数据按个税扣缴义务人切割
//                    if (!isOnlyTaxAgent) {
//                        // 开始日期
//                        Date startItem = taxAgent.getEffectiveDateRange().getFromDate();
//                        // 结束日期
//                        Date endItem = taxAgent.getEffectiveDateRange().getEndDate();
//                        Date endTempItem = endItem;
//                        List<SalaryArchiveItemDataDTO> salaryItemValues = new ArrayList<>();
//                        for (Long salaryArchiveItemId : salaryArchiveItemIds) {
//                            for (SalaryArchiveItemPO salaryArchiveItem : salaryArchiveItems) {
//                                if (!salaryArchiveItemId.equals(salaryArchiveItem.getSalaryItemId()) || !salaryArchiveItem.getSalaryArchiveId().equals(salaryArchive.getId())) {
//                                    continue;
//                                }
//                                Date fromDateItem = salaryArchiveItem.getEffectiveTime();
//                                if (fromDateItem.after(endTempItem) || (!endTempItem.after(startItem) && !endTempItem.equals(startItem))) {
//                                    continue;
//                                }
//                                SalaryArchiveItemDataDTO salaryArchiveItemData = new SalaryArchiveItemDataDTO();
//                                salaryArchiveItemData.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDateItem.before(startItem) ? startItem : fromDateItem)).endDate(endTempItem).build());
//                                //fixme 排除1号调薪，之前的历史周期为2022-01-01-2022-01-01这种情况
//                                if (!salaryArchiveItemData.getEffectiveDateRange().getFromDate().before(salaryArchiveItemData.getEffectiveDateRange().getEndDate())) {
//                                    continue;
//                                }
//                                salaryArchiveItemData.setSalaryItemId(salaryArchiveItem.getSalaryItemId());
//                                salaryArchiveItemData.setValue(salaryArchiveItem.getItemValue());
//                                salaryItemValues.add(salaryArchiveItemData);
//                                endTempItem = fromDateItem;
//                            }
//                            endTempItem = endItem;
//                        }
//                        taxAgent.setSalaryItemValues(salaryItemValues);
//                    }
//                    taxAgents.add(taxAgent);
//                }
//            }
//            salaryArchiveData.setTaxAgents(taxAgents);
//            list.add(salaryArchiveData);
//        });
//
//        return list;


        // 开始日期
        Date start = localDateRange.getFromDate();
        // 结束日期
        Date end = localDateRange.getEndDate();

        List<SalaryArchiveDataDTO> list = new ArrayList<>();
        allEmployeeIds.forEach(e -> {
            // 同一个人的档案数据
            List<SalaryArchivePO> salaryArchives = salaryArchiveList.stream().filter(f -> f.getEmployeeId().equals(e)).collect(Collectors.toList());
            List<Long> salaryArchiveIds = salaryArchives.stream().map(SalaryArchivePO::getId).collect(Collectors.toList());
            // 同一个人的薪资项目调整历史数据
            List<SalaryArchiveItemPO> salaryArchiveItems = salaryArchiveItemDataList.stream().filter(d -> salaryArchiveIds.contains(d.getSalaryArchiveId())).collect(Collectors.toList());
            List<Long> salaryArchiveItemIds = salaryArchiveItems.stream().map(SalaryArchiveItemPO::getSalaryItemId).distinct().collect(Collectors.toList());

            SalaryArchiveDataDTO salaryArchiveData = new SalaryArchiveDataDTO();
            salaryArchiveData.setEmployeeId(e);
            List<SalaryArchiveTaxAgentDataDTO> taxAgents = new ArrayList<>();
            // 按个税扣缴义务人生效日期时间段切割
            for (SalaryArchivePO salaryArchive : salaryArchives) {
                Date fromDate = salaryArchive.getPayStartDate();
                Date endDate = salaryArchive.getPayEndDate();
                // 起始发薪日不为空，且不能比结束日期晚，最后发薪日可空可不空，但是如果不为空，就不能比开始日期早，且起始发薪日不能晚于最后发薪日
                boolean isEnable = fromDate != null && !fromDate.after(end) && (endDate == null || (!fromDate.after(endDate) && !endDate.before(start)));
                if (isEnable) {
                    SalaryArchiveTaxAgentDataDTO taxAgent = new SalaryArchiveTaxAgentDataDTO();
                    taxAgent.setTaxAgentId(salaryArchive.getTaxAgentId());
//                    taxAgent.setIncomeCategory(salaryArchive.getIncomeCategory());
//                    taxAgent.setSalarySobIds(salaryArchiveSobList.stream().filter(sob->sob.getSalaryArchiveId().equals(salaryArchive.getId())).map(SalaryArchiveSobPO::getSalarySobId).distinct().collect(Collectors.toList()));
                    taxAgent.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDate.before(start) ? start : fromDate)).endDate(endDate == null || endDate.after(end) ? end : endDate).build());
                    // 薪资项目数据按个税扣缴义务人切割
                    if (!isOnlyTaxAgent) {
                        // 开始日期
                        Date startItem = taxAgent.getEffectiveDateRange().getFromDate();
                        // 结束日期
                        Date endItem = taxAgent.getEffectiveDateRange().getEndDate();
                        Date endTempItem = endItem;
                        List<SalaryArchiveItemDataDTO> salaryItemValues = new ArrayList<>();
                        for (Long salaryArchiveItemId : salaryArchiveItemIds) {
                            boolean flag = false;
                            for (SalaryArchiveItemPO salaryArchiveItem : salaryArchiveItems) {
                                if (!salaryArchiveItemId.equals(salaryArchiveItem.getSalaryItemId()) || !salaryArchiveItem.getSalaryArchiveId().equals(salaryArchive.getId())) {
                                    continue;
                                }
                                Date fromDateItem = salaryArchiveItem.getEffectiveTime();
                                if (fromDateItem.after(endTempItem) || endTempItem.before(startItem)) {
                                    continue;
                                }
                                if (endTempItem.equals(startItem) && flag) {
                                    continue;
                                }
                                SalaryArchiveItemDataDTO salaryArchiveItemData = new SalaryArchiveItemDataDTO();
                                salaryArchiveItemData.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDateItem.before(startItem) ? startItem : fromDateItem)).endDate(endTempItem).build());
                                salaryArchiveItemData.setSalaryItemId(salaryArchiveItem.getSalaryItemId());
                                salaryArchiveItemData.setValue(salaryArchiveItem.getItemValue());
                                salaryItemValues.add(salaryArchiveItemData);
                                flag = true;
                                endTempItem = fromDateItem;
                            }
                            endTempItem = endItem;
                        }
                        taxAgent.setSalaryItemValues(salaryItemValues);
                    }
                    taxAgents.add(taxAgent);
                }
            }
            salaryArchiveData.setTaxAgents(taxAgents);
            list.add(salaryArchiveData);
        });

        return list;
    }

    /**
     * 构建增量数据
     *
     * @param taxAgentEmpChangeList
     * @param salaryArchiveList
     * @param salaryArchiveItemList
     * @param currentEmployeeId
     */
    public static ChangeData buildChangeData(List<TaxAgentEmpChangePO> taxAgentEmpChangeList, List<SalaryArchivePO> salaryArchiveList, List<SalaryArchiveItemPO> salaryArchiveItemList, Long currentEmployeeId) {
        List<Long> changeIds = taxAgentEmpChangeList.stream().map(TaxAgentEmpChangePO::getId).collect(Collectors.toList());
        // 根据个税扣缴义务人和人员以及增量类型分组
        Map<String, Long> changeTypeMap = taxAgentEmpChangeList.stream().collect(Collectors.groupingBy(change -> change.getTaxAgentId() + "-" + change.getEmployeeId() + "-" + change.getChangeType(), Collectors.counting()));
        // 顺序倒转
        Collections.reverse(taxAgentEmpChangeList);
        // 去重
        taxAgentEmpChangeList = taxAgentEmpChangeList.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getTaxAgentId() + "-" + f.getEmployeeId()))), ArrayList::new));
        List<TaxAgentEmpChangePO> taxAgentEmpChanges = taxAgentEmpChangeList
                .stream()
                // 不相等则保留，否则忽略
                .filter(change -> !Objects.equals(changeTypeMap.get(change.getTaxAgentId() + "-" + change.getEmployeeId() + "-" + TaxAgentEmpChangeTypeEnum.ADD.getValue())
                        , changeTypeMap.get(change.getTaxAgentId() + "-" + change.getEmployeeId() + "-" + TaxAgentEmpChangeTypeEnum.DEL.getValue())))
                .collect(Collectors.toList());

        Date now = new Date();
        Date today = new Date();
        List<String> stopStatus = Arrays.asList(SalaryArchiveStatusEnum.STOP_FROM_PENDING.getValue(), SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue());
        List<SalaryArchivePO> salaryArchiveAddTodoList = Lists.newArrayList();
        List<SalaryArchivePO> salaryArchiveUpdateTodoList = Lists.newArrayList();
        List<SalaryArchiveItemPO> salaryArchiveItemAddTodos = Lists.newArrayList();

        Map<String, SalaryArchivePO> salaryArchiveListMap = SalaryEntityUtil.convert2Map(salaryArchiveList, k -> k.getTaxAgentId() + "-" + k.getEmployeeId());
        taxAgentEmpChanges.forEach(change -> {
            SalaryArchivePO salaryArchive = salaryArchiveListMap.get(change.getTaxAgentId() + "-" + change.getEmployeeId());
            // 如果是新增 说明：如果没有档案，则新增，如果有档案而且是停薪，就挪到待定薪中，以个税扣缴义务人和人员id判断唯一
            if (change.getChangeType() == TaxAgentEmpChangeTypeEnum.ADD.getValue()) {
                if (salaryArchive != null) {
                    // 停薪中跳回待定薪：从a调动到b又调动到a，或者是删除待办后再覆盖
                    if (stopStatus.contains(salaryArchive.getRunStatus())) {
                        // 跳回待定薪
                        salaryArchive.setRunStatus(SalaryArchiveStatusEnum.PENDING.getValue());
                        if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue())) {
                            salaryArchive.setPayStartDate(today);
                            salaryArchive.setPayEndDate(null);
                        }
                        salaryArchiveUpdateTodoList.add(salaryArchive);
                        // 待停薪到停薪的就要复制最新的薪资项目
                        if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue())) {
                            // 拷贝最新的薪资项目数据
                            List<SalaryArchiveItemPO> salaryArchiveItemValuelList = salaryArchiveItemList.stream().filter(i -> i.getSalaryArchiveId().equals(salaryArchive.getId())).collect(Collectors.toList());
                            salaryArchiveItemValuelList.forEach(i -> {
                                salaryArchiveItemAddTodos.add(SalaryArchiveItemPO.builder()
                                        .id(IdGenerator.generate())
                                        .salaryArchiveId(salaryArchive.getId())
                                        .employeeId(salaryArchive.getEmployeeId())
                                        .effectiveTime(today)
                                        .adjustReason(SalaryArchiveItemAdjustReasonEnum.INIT.getValue())
                                        .salaryItemId(i.getSalaryItemId())
                                        .itemValue(i.getItemValue())
                                        .description("")
                                        // 不用设置操作人
                                        .operateTime(now)
                                        .createTime(now)
                                        .updateTime(now)
                                        .creator(currentEmployeeId)
                                        .deleteType(NumberUtils.INTEGER_ZERO)
                                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                                        .build());
                            });
                        }
                    }
                } else {
                    salaryArchiveAddTodoList.add(SalaryArchivePO.builder()
                            .id(IdGenerator.generate())
                            .employeeId(change.getEmployeeId())
                            .taxAgentId(change.getTaxAgentId())
                            .employeeType(change.getEmployeeType())
                            .runStatus(SalaryArchiveStatusEnum.PENDING.getValue())
//                            .incomeCategory(IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())
//                            .modifier(0L)
                            .createTime(now)
                            .updateTime(now)
                            .creator(currentEmployeeId)
                            .deleteType(NumberUtils.INTEGER_ZERO)
                            .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                            .build());
                }
                // 如果是删除 说明：如果有档案并且是在定薪列表才处理，没档案不用管
            } else if (change.getChangeType() == TaxAgentEmpChangeTypeEnum.DEL.getValue()) {
                if (salaryArchive != null) {
                    if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.FIXED.getValue())) {
                        // 跳到待停薪
                        salaryArchive.setRunStatus(SalaryArchiveStatusEnum.SUSPEND.getValue());
//                        salaryArchive.setPayEndDate(today);
                        salaryArchiveUpdateTodoList.add(salaryArchive);
                    } else if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.PENDING.getValue())) {
                        // 跳到停薪
                        salaryArchive.setRunStatus(SalaryArchiveStatusEnum.STOP_FROM_PENDING.getValue());
                        salaryArchiveUpdateTodoList.add(salaryArchive);
                    }
                }
            }
        });

        return ChangeData.builder()
                .salaryArchiveAddTodoList(salaryArchiveAddTodoList)
                .salaryArchiveUpdateTodoList(salaryArchiveUpdateTodoList)
                .salaryArchiveItemAddTodos(salaryArchiveItemAddTodos)
                .changeIds(changeIds)
                .build();
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ChangeData {

        /**
         * 批量修改薪资档案
         */
        private List<SalaryArchivePO> salaryArchiveAddTodoList;

        /**
         * 批量新增薪资档案
         */
        private List<SalaryArchivePO> salaryArchiveUpdateTodoList;

        /**
         * 落库处理薪资项目
         */
        private List<SalaryArchiveItemPO> salaryArchiveItemAddTodos;

        /**
         * 删除增量数据
         */
        private List<Long> changeIds;
    }


    public static boolean isNotExtEmp(SalaryArchivePO po) {
        return po.getEmployeeType() == null || po.getEmployeeType() == 1;
    }
}
