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

import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.entity.agency.po.PaymentAgencyPO;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.hrm.DeptInfo;
import com.engine.salary.entity.hrm.HrmStatus;
import com.engine.salary.entity.hrm.PositionInfo;
import com.engine.salary.entity.hrm.SubCompanyInfo;
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentListDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeListDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentSubAdminListDTO;
import com.engine.salary.entity.taxagent.param.TaxAgentManageRangeSaveParam;
import com.engine.salary.entity.taxagent.param.TaxAgentSaveParam;
import com.engine.salary.entity.taxagent.param.TaxAgentSubAdminRangeSaveParam;
import com.engine.salary.entity.taxagent.po.TaxAgentAdminPO;
import com.engine.salary.entity.taxagent.po.TaxAgentManageRangePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxagent.po.TaxAgentSubAdminPO;
import com.engine.salary.enums.salarysob.TargetTypeEnum;
import com.engine.salary.enums.taxagent.TaxAgentRangeTypeEnum;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.page.Column;
import com.engine.salary.util.page.PageInfo;
import com.google.common.base.Joiner;
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.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

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

/**
 * 个税扣缴义务人
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class TaxAgentBO {

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

    /**
     * 根据个税扣缴义务人id和用户id判断是否匹配
     *
     * @param taxAgentEmployees
     * @param taxAgentId
     * @param employeeId
     * @return
     */
    public static boolean checkTaxAgentAndEmployee(List<TaxAgentEmployeeDTO> taxAgentEmployees, Long taxAgentId, Long employeeId) {
        if (CollectionUtils.isEmpty(taxAgentEmployees) && taxAgentId == null) {
            return false;
        }
        return taxAgentEmployees.stream().anyMatch(t -> t.getTaxAgentId().equals(taxAgentId) && employeeId.equals(t.getEmployeeId()));
    }

    /**
     * 构建表格
     *
     * @param isOpenDevolution
     */
    public static void buildTaxAgentTable(PageInfo<Map<String, Object>> listPage, boolean isOpenDevolution) {
        // 表格表头
        List<Column> columns = new ArrayList<>();
        String name = SalaryI18nUtil.getI18nLabel(91558, "个税扣缴义务人名称");
        String employeeRange = SalaryI18nUtil.getI18nLabel(86125, "人员范围");
        String admins = SalaryI18nUtil.getI18nLabel(106259, "管理员");
        String subAdmins = SalaryI18nUtil.getI18nLabel(106283, "分管理员");
//        String paymentAgency = SalaryI18nUtil.getI18nLabel(112448, "社保福利代缴机构");
        String description = SalaryI18nUtil.getI18nLabel(84961, "备注");
        String sortedIndex = SalaryI18nUtil.getI18nLabel(84962, "显示顺序");
        if (isOpenDevolution) {
            columns.add(new Column(name, "name", "name%"));
            columns.add(new Column(employeeRange, "employeeRange", "employeeRange"));
            columns.add(new Column(admins, "admins", "admins%"));
//            columns.add(new Column(subAdmins, "subAdmins", "20%"));
//            columns.add(new Column(paymentAgency, "paymentAgency", "30%"));
            columns.add(new Column(description, "description", "name"));
            columns.add(new Column(sortedIndex, "sortedIndex", "sortedIndex"));
        } else {
            columns.add(new Column(name, "name", "name"));
            columns.add(new Column(employeeRange, "employeeRange", "employeeRange"));
//            columns.add(new WeaTableColumn(paymentAgency, "paymentAgency", "30%"));
            columns.add(new Column(description, "description", "description"));
            columns.add(new Column(sortedIndex, "sortedIndex", "sortedIndex"));
        }
        listPage.setColumns(columns);
    }

//    private static List<List<Permission>> getDefaultOperatesPermission(int operateSize, int recordSize) {
//        List<List<Permission>> permissionList = Lists.newArrayList();
//        for (int i = 0; i < recordSize; i++) {
//            List<Permission> permissions = Lists.newArrayList();
//            for (int j = 0; j < operateSize; j++) {
//                permissions.add(new Permission(true, false));
//            }
//            permissionList.add(permissions);
//        }
//        return permissionList;
//    }
//
//    private static List<Permission> getDefaultCheckBoxPermission(int recordSize) {
//        List<Permission> permissionList = Lists.newArrayList();
//        for (int i = 0; i < recordSize; i++) {
//            permissionList.add(new Permission(true, false));
//        }
//        return permissionList;
//    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @return
     */
    public static List<TaxAgentListDTO> convertToListDTO(Collection<TaxAgentPO> taxAgents) {
        if (CollectionUtils.isEmpty(taxAgents)) {
            return Collections.emptyList();
        }
        return taxAgents.stream()
                .map(e -> TaxAgentListDTO.builder()
                        .id(e.getId())
                        .name(e.getName())
                        .description(e.getDescription())
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @return
     */
    public static List<Map<String, Object>> convertToTableListDTO(List<TaxAgentPO> taxAgents, List<PaymentAgencyPO> paymentAgencyPOS, String setLabel) {
        return convertToTableListDTO(Boolean.FALSE, taxAgents, paymentAgencyPOS, null, null, setLabel);
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @return
     */
    public static List<Map<String, Object>> convertToTableListDTO(List<TaxAgentPO> taxAgents, List<PaymentAgencyPO> paymentAgencyPOS, List<TaxAgentAdminPO> taxAgentAdmins,
                                                                  List<DataCollectionEmployee> adminList,
                                                                  String setLabel) {
        return convertToTableListDTO(Boolean.TRUE, taxAgents, paymentAgencyPOS, taxAgentAdmins, adminList, setLabel);
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @param adminList
     * @return
     */
    public static List<Map<String, Object>> convertToTableListDTO(Boolean isDevolution, List<TaxAgentPO> taxAgents, List<PaymentAgencyPO> paymentAgencyPOS,
                                                                  List<TaxAgentAdminPO> taxAgentAdmins,
                                                                  List<DataCollectionEmployee> adminList, String setLabel) {
        if (CollectionUtils.isEmpty(taxAgents)) {
            return Collections.emptyList();
        }
        return taxAgents.stream()
                .map(e -> {
                    Map<String, Object> map = new LinkedHashMap<>();
                    map.put("id", e.getId());
                    map.put("name", e.getName());
                    map.put("employeeRange", setLabel);
                    if (isDevolution) {
                        List<Long> empIds = taxAgentAdmins.stream().filter(t -> t.getTaxAgentId().equals(e.getId())).map(TaxAgentAdminPO::getEmployeeId).collect(Collectors.toList());
                        List<String> admins = adminList.stream().filter(a -> empIds.contains(a.getEmployeeId())).map(DataCollectionEmployee::getUsername).collect(Collectors.toList());
                        map.put("admins", CollectionUtils.isEmpty(admins) ? "" : Joiner.on(",").join((Iterable<?>) admins));
                        map.put("subAdmins", setLabel);
                    }
                    map.put("paymentAgency", buildPaymentAgency(e.getPaymentAgency(), paymentAgencyPOS));
                    map.put("description", e.getDescription());
                    map.put("sortedIndex", e.getSortedIndex());
                    return map;
                }).collect(Collectors.toList());
    }

    public static List<Map<String, Object>> buildPaymentAgency(String originStr, List<PaymentAgencyPO> paymentAgencyPOS) {
        List<Map<String, Object>> paymentAgencyList = new ArrayList<>();
        if (CollectionUtils.isEmpty(paymentAgencyPOS)) {
            return paymentAgencyList;
        }
        originStr = StringUtils.isBlank(originStr) ? "" : originStr;
        String finalOriginStr = originStr;
        return paymentAgencyPOS.stream().map(e -> {
            HashMap<String, Object> temp = new HashMap<>();
            temp.put("id", e.getId());
            temp.put("agencyName", e.getAgencyName());
            if (finalOriginStr.contains(String.valueOf(e.getId()))) {
                temp.put("status", true);
            } else {
                temp.put("status", false);
            }
            return temp;
        }).collect(Collectors.toList());
    }

    /**
     * 保存参数转表数据
     *
     * @param saveParam
     * @param employeeId
     * @return
     */
    public static TaxAgentPO convertToPO(TaxAgentSaveParam saveParam, Long employeeId) {
        if (saveParam == null) {
            return null;
        }
        Date now = new Date();
        return TaxAgentPO.builder()
//                .id(saveParam.getId())
                .name(saveParam.getName())
                .description(saveParam.getDescription())
                .createTime(now)
                .updateTime(now)
                .creator(employeeId)
                .deleteType(0)
                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                .sortedIndex(saveParam.getSortedIndex())
                .build();
    }

    /**
     * 表数据转列表数据（分管理员）
     *
     * @param list
     * @param range
     * @param subAdminList
     * @return
     */
    public static List<TaxAgentSubAdminListDTO> convertToSubAdminListDTO(List<TaxAgentSubAdminPO> list, String range, List<DataCollectionEmployee> subAdminList) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream()
                .map(e -> {
                    Optional<String> optionalUsername = subAdminList.stream().filter(a -> e.getEmployeeId().equals(a.getEmployeeId())).map(DataCollectionEmployee::getUsername).findFirst();
                    return TaxAgentSubAdminListDTO.builder()
                            .id(e.getId())
                            .subAdmin(optionalUsername.isPresent() ? optionalUsername.get() : "")
                            .range(range)
                            .description(e.getRemark())
                            .build();
                })
                .collect(Collectors.toList());
    }

    /**
     * 管理范围列表转换
     *
     * @param taxAgentManageRanges
     * @param employeeComInfos
     * @param departmentComInfos
     * @param subDepartmentComInfos
     * @param positionComInfos
     * @param hrmStatusList
     * @return
     */
    public static List<TaxAgentManageRangeListDTO> convert2ListDTO(List<TaxAgentManageRangePO> taxAgentManageRanges, List<DataCollectionEmployee> employeeComInfos,
                                                                   List<DeptInfo> departmentComInfos, List<SubCompanyInfo> subDepartmentComInfos,
                                                                   List<PositionInfo> positionComInfos, List<HrmStatus> hrmStatusList) {
        if (CollectionUtils.isEmpty(taxAgentManageRanges)) {
            return Collections.emptyList();
        }
        Map<Long, String> employeeComInfoMap = SalaryEntityUtil.convert2Map(employeeComInfos, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getUsername);
        Map<Long, String> departmentComInfoMap = SalaryEntityUtil.convert2Map(departmentComInfos, DeptInfo::getId, DeptInfo::getName);
        Map<Long, String> subDepartmentComInfoMap = SalaryEntityUtil.convert2Map(subDepartmentComInfos, SubCompanyInfo::getId, SubCompanyInfo::getName);
        Map<Long, String> positionComInfoMap = SalaryEntityUtil.convert2Map(positionComInfos, PositionInfo::getId, PositionInfo::getName);

        Map<String, String> hrmStatusNameMap = SalaryEntityUtil.convert2Map(hrmStatusList, hrmStatus -> String.valueOf(hrmStatus.getId()), HrmStatus::getName);

        return taxAgentManageRanges.stream()
                .map(taxAgentManageRange -> {
                    TargetTypeEnum targetTypeEnum = TargetTypeEnum.parseByValue(taxAgentManageRange.getTargetType());
                    return TaxAgentManageRangeListDTO.builder()
                            .id(taxAgentManageRange.getId())
                            .targetType(targetTypeEnum)
                            .targetTypeName(Optional.ofNullable(targetTypeEnum)
                                    .map(e -> SalaryI18nUtil.getI18nLabel(e.getLabelId(), e.getDefaultLabel()))
                                    .orElse(StringUtils.EMPTY))
                            .targetId(taxAgentManageRange.getTargetId())
                            .targetName(buildTargetName(taxAgentManageRange, employeeComInfoMap, departmentComInfoMap, subDepartmentComInfoMap, positionComInfoMap))
                            .employeeStatus(buildEmployeeStatus(hrmStatusNameMap, taxAgentManageRange.getEmployeeStatus()))
                            .build();
                })
                .collect(Collectors.toList());
    }

    private static String buildEmployeeStatus(Map<String, String> hrmStatusNameMap, String employeeStatus) {
        List<String> employeeStatusList = JsonUtil.parseList(employeeStatus, String.class);
        if (CollectionUtils.isEmpty(employeeStatusList)) {
            return StringUtils.EMPTY;
        }
        return employeeStatusList.stream()
                .map(hrmStatusNameMap::get)
                .collect(Collectors.joining(","));
    }

    /**
     * 构建对象名
     *
     * @param taxAgentManageRange
     * @param employeeComInfoMap
     * @param departmentComInfoMap
     * @param subDepartmentComInfoMap
     * @param positionComInfoMap
     * @return
     */
    private static String buildTargetName(TaxAgentManageRangePO taxAgentManageRange, Map<Long, String> employeeComInfoMap, Map<Long, String> departmentComInfoMap,
                                          Map<Long, String> subDepartmentComInfoMap, Map<Long, String> positionComInfoMap) {
        TargetTypeEnum targetTypeEnum = TargetTypeEnum.parseByValue(taxAgentManageRange.getTargetType());
        if (Objects.isNull(targetTypeEnum)) {
            return StringUtils.EMPTY;
        }
        switch (targetTypeEnum) {
            case EMPLOYEE:
                return employeeComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case DEPT:
                return departmentComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case SUBCOMPANY:
                return subDepartmentComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case POSITION:
                return positionComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            default:
                return StringUtils.EMPTY;
        }
    }

    public static Result handleTaxAgentRange(List<TaxAgentManageRangePO> taxAgentManageRanges, TaxAgentManageRangeSaveParam saveParam, Long taxAgentId, Long employeeId, boolean isImport) {
        return handleManageRange(taxAgentManageRanges, saveParam, TaxAgentRangeTypeEnum.TAXAGENT, taxAgentId, 0L, employeeId, isImport);
    }

    public static Result handleSubAdminRange(List<TaxAgentManageRangePO> taxAgentManageRanges, TaxAgentManageRangeSaveParam saveParam, Long taxAgentId, Long subAdminId,
                                             Long employeeId, boolean isImport) {
        return handleManageRange(taxAgentManageRanges, saveParam, TaxAgentRangeTypeEnum.SUBADMIN, taxAgentId, subAdminId, employeeId, isImport);
    }

    /**
     * 处理前端传回的保存参数，转换成对应的po（如果保存参数中的人员、部门、岗位等之前就已经添加过了，就不需要再次保存了）
     *
     * @param taxAgentManageRanges
     * @param saveParam
     * @param taxAgentId
     * @param subAdminId
     * @param employeeId
     * @return
     */
    private static Result handleManageRange(List<TaxAgentManageRangePO> taxAgentManageRanges, TaxAgentManageRangeSaveParam saveParam,
                                            TaxAgentRangeTypeEnum rangeTypeEnum, Long taxAgentId, Long subAdminId, Long employeeId, boolean isImport) {
        Date now = new Date();
        Result handleResult = Result.builder()
                .needInsertTaxAgentManageRanges(Lists.newArrayList())
                .needUpdateTaxAgentManageRanges(Lists.newArrayList())
                .build();
        if (CollectionUtils.isEmpty(saveParam.getTargetParams())) {
            return handleResult;
        }
        Map<String, TaxAgentManageRangePO> taxAgentManageRangeMap = SalaryEntityUtil.convert2Map(taxAgentManageRanges,
                e -> e.getIncludeType() + "-" + e.getTargetType() + "-" + e.getTargetId() + "-" + e.getRangeType());
        for (TaxAgentSubAdminRangeSaveParam.TaxAgentSubAdminRangeTargetParam targetParam : saveParam.getTargetParams()) {
            String key = saveParam.getIncludeType() + "-" + targetParam.getTargetType().getValue() + "-" + targetParam.getTargetId() + "-" + rangeTypeEnum.getValue();
            if (taxAgentManageRangeMap.containsKey(key)) {
                TaxAgentManageRangePO taxAgentManageRange = taxAgentManageRangeMap.get(key);
                if(isImport){
                    taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(targetParam.getEmployeeStatus()));
                }else {
                    taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(saveParam.getEmployeeStatus()));
                }
                taxAgentManageRange.setUpdateTime(now);
                handleResult.getNeedUpdateTaxAgentManageRanges().add(taxAgentManageRange);
                continue;
            }
            TaxAgentManageRangePO taxAgentManageRange = TaxAgentManageRangePO.builder()
                    .id(IdGenerator.generate())
                    .taxAgentId(taxAgentId)
                    .taxAgentSubAdminId(subAdminId)
                    .rangeType(rangeTypeEnum.getValue())
                    .targetType(targetParam.getTargetType().getValue())
                    .targetId(targetParam.getTargetId())
                    .includeType(saveParam.getIncludeType())
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .deleteType(0)
                    .build();
            if(isImport){
                taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(targetParam.getEmployeeStatus()));
            }else {
                taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(saveParam.getEmployeeStatus()));
            }
            handleResult.getNeedInsertTaxAgentManageRanges().add(taxAgentManageRange);
        }
        return handleResult;
    }

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

        /**
         * 需要更新的人员范围
         */
        private Collection<TaxAgentManageRangePO> needUpdateTaxAgentManageRanges;

        /**
         * 需要新增的人员范围
         */
        private Collection<TaxAgentManageRangePO> needInsertTaxAgentManageRanges;
    }
}
