package com.engine.salary.wrapper;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryBill.dto.SalarySendCheckDTO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctRecordBO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctEmployeeCountDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctRecordFormDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctRecordListDTO;
import com.engine.salary.entity.salaryacct.param.SalaryAcctRecordQueryParam;
import com.engine.salary.entity.salaryacct.param.SalaryAcctRecordSaveParam;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salarysob.dto.SalarySobCycleDTO;
import com.engine.salary.entity.salarysob.po.SalarySobPO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.service.*;
import com.engine.salary.service.impl.*;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.SalarySobUtil;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.wrapper.proxy.SalaryAcctRecordWrapperProxy;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.hrm.User;

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

/**
 * 薪资核算记录
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SalaryAcctRecordWrapper extends Service implements SalaryAcctRecordWrapperProxy {

    private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
        return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
    }

    private SalarySobService getSalarySobService(User user) {
        return ServiceUtil.getService(SalarySobServiceImpl.class, user);
    }

    private SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) {
        return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user);
    }

    private SalarySendService getSalarySendService(User user) {
        return ServiceUtil.getService(SalarySendServiceImpl.class, user);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    private SalaryItemService getSalaryItemService(User user) {
        return ServiceUtil.getService(SalaryItemServiceImpl.class, user);
    }

    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }

//    private ComInfoCache comInfoCache;

    public PageInfo<SalaryAcctRecordListDTO> listPage(SalaryAcctRecordQueryParam queryParam) {

        // 处理历史数据将薪资账套中将关联人员状态转换为List
        SalarySobUtil.handleEmployeeStatusHistory();
        // 处理工资单发放历史数据
        getSalarySendService(user).handleHistory();
        // 查询薪资核算记录（分页）
        PageInfo<SalaryAcctRecordPO> page = getSalaryAcctRecordService(user).listPageByParam(queryParam);
        PageInfo<SalaryAcctRecordListDTO> dtoPage = new PageInfo<SalaryAcctRecordListDTO>(SalaryAcctRecordListDTO.class);
        dtoPage.setPageNum(queryParam.getCurrent());
        dtoPage.setPageSize(queryParam.getPageSize());
        dtoPage.setTotal(page.getTotal());
        List<SalaryAcctRecordPO> list = page.getList();
        if (CollectionUtils.isNotEmpty(list)) {
            // 查询薪资账套
            Set<Long> salarySobIds = SalaryEntityUtil.properties(list, SalaryAcctRecordPO::getSalarySobId);
            List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByIds(salarySobIds);
            // 查询薪资核算记录的创建人员的人员信息
            List<Long> employeeIds = SalaryEntityUtil.properties(list, SalaryAcctRecordPO::getCreator, Collectors.toList());
            List<DataCollectionEmployee> employeeComInfos = getSalaryEmployeeService(user).getEmployeeByIdsAll(employeeIds);
            // 查询薪资核算人数的数量
            Set<Long> salaryAcctRecordIds = SalaryEntityUtil.properties(list, SalaryAcctRecordPO::getId);
            List<SalaryAcctEmployeeCountDTO> salaryAcctEmployeeCountDTOS = getSalaryAcctEmployeeService(user).countBySalaryAcctRecordId(salaryAcctRecordIds);
            // 查询工资单的查询情况
            List<SalarySendCheckDTO> salarySendCheckResult = getSalarySendService(user).getSalarySendCheckResult(salaryAcctRecordIds);

            Set<Long> taxAgentIds = SalaryEntityUtil.properties(salarySobPOS, SalarySobPO::getTaxAgentId);
            List<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds);

            // 转换成列表dto
            List<SalaryAcctRecordListDTO> salaryAcctRecordListDTOS = SalaryAcctRecordBO.convert2ListDTO(list, salarySobPOS, employeeComInfos, salaryAcctEmployeeCountDTOS, salarySendCheckResult, taxAgentPOS);
            dtoPage.setList(salaryAcctRecordListDTOS);
        }
//        WeaTable<SalaryAcctRecordListDTO> weaTable = SalaryFormatUtil.<SalaryAcctRecordListDTO>getInstance().buildTable(SalaryAcctRecordListDTO.class, dtoPage);
        // 只有未归档时可以"核算"、"删除"、"归档"
        // 归档后、申报后可以"查看"、"重新核算"
//        for (int i = 0; i < page.getRecords().size(); i++) {
//            SalaryAcctRecordPO salaryAcctRecord = page.getRecords().get(i);
//            List<Permission> permissions = weaTable.getOperatesPermission().get(i);
//            for (int j = 0; j < permissions.size(); j++) {
//                Permission permission = permissions.get(j);
//                if ((j == 0 || j == 1 || j == 3) && !Objects.equals(salaryAcctRecord.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())) {
//                    permission.setVisible(false);
//                    permission.setDisabled(false);
//                }
//                if ((j == 2 || j == 5) && Objects.equals(salaryAcctRecord.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())) {
//                    permission.setVisible(false);
//                    permission.setDisabled(false);
//                }
//            }
//        }
        return dtoPage;
    }

    /**
     * @description 处理历史数据给薪资项目都增加个默认排序
     * @return null
     * @author Harryxzy
     * @date 2023/5/29 14:37
     */
//    private void generateSalaryItemSortedIndex() {
//        // 查询所有薪资项目
//        List<SalaryItemPO> salaryItemList = getSalaryItemService(user).listByParamOrderById(SalaryItemSearchParam.builder().build());
//        Optional<SalaryItemPO> needGenerate = salaryItemList.stream().filter(item -> item.getSortedIndex() == null).findFirst();
//        if(needGenerate.isPresent()){
//            Map<Integer, List<SalaryItemPO>> salaryItemMap = SalaryEntityUtil.group2Map(salaryItemList, SalaryItemPO::getUseInEmployeeSalary);
//            for(Map.Entry<Integer, List<SalaryItemPO>> entry : salaryItemMap.entrySet()){
//                List<SalaryItemPO> values = entry.getValue();
//                if(CollectionUtils.isNotEmpty(values)){
//                    // 将系统薪资项目放到最后
//                    values = values.stream()
//                            .sorted(Comparator.comparing(SalaryItemPO::getSystemType))
//                            .collect(Collectors.toList());
//                    // 添加默认sortedIndex
//                    AtomicInteger index = new AtomicInteger(values.size());
//                    values.stream().forEach(value -> value.setSortedIndex(index.getAndDecrement()));
//                    // 保存排序
//                    getSalaryItemService(user).batchUpdateSortedIndex(values);
//                }
//            }
//        }
//    }

    /**
     * 薪资核算记录详情
     *
     * @param id 薪资核算记录id
     * @return
     */
    public Map<String, Object> getForm(Long id) {
        SalaryAcctRecordFormDTO formDTO = new SalaryAcctRecordFormDTO();
        // 查询所有启用的薪资账套
        List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByDisable(NumberUtils.INTEGER_ZERO);
        // 薪资核算详情表单中"薪资账套"的下拉选择项
        List<Map<String, Object>> salarySobs = salarySobPOS.stream()
                .map(salarySobPO -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", salarySobPO.getId());
                    map.put("name", salarySobPO.getName());
                    return map;
                })
                .collect(Collectors.toList());

        if (Objects.nonNull(id)) {
            // 查询薪资核算
            SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(id);
            if (Objects.isNull(salaryAcctRecordPO)) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
            }
            // 查询薪资账套
            SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
            if (Objects.isNull(salarySobPO)) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98769, "薪资账套不存在或已被删除"));
            }
            // 转换成薪资核算记录详情dto
            formDTO.setId(salaryAcctRecordPO.getId())
                    .setSalarySobId(salarySobPO.getId())
                    .setSalarySobName(salarySobPO.getName())
                    .setSalaryMonth(SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth()).toString())
                    .setDescription(salaryAcctRecordPO.getDescription());
        }
        // 转换成前端所需的数据格式
        Map<String, Object> result = new HashMap<>();
        result.put("formDTO", formDTO);
        result.put("salarySobs", salarySobs);
        return result;
    }

    /**
     * 薪资核算记录所用的薪资账套薪资周期、考勤周期……
     *
     * @param id 薪资核算记录的id
     * @return
     */
    public SalarySobCycleDTO getSalarySobCycleById(Long id) {
        return getSalaryAcctRecordService(user).getSalarySobCycleById(id);
    }

    /**
     * 保存
     *
     * @param saveParam 保存参数
     * @return
     */
    public Long save(SalaryAcctRecordSaveParam saveParam) {
        return getSalaryAcctRecordService(user).save(saveParam);
    }

    /**
     * 删除
     *
     * @param ids 薪资核算记录的id
     */
    public void delete(Collection<Long> ids) {
        getSalaryAcctRecordService(user).deleteByIds(ids);
    }

    /**
     * 归档
     *
     * @param id 薪资核算记录的id
     */
    public void file(Long id) {
        getSalaryAcctRecordService(user).file(id);
    }

    /**
     * 重新核算
     *
     * @param id 薪资核算记录的id
     */
    public void reCalculate(Long id) {
        getSalaryAcctRecordService(user).reCalculate(id);
    }



    /**
     * 判断是否存在合并计税
     *
     * @param id 主键id
     * @return
     */
    public Integer hasConsolidatedTax(Long id) {
        return getSalaryAcctRecordService(user).hasConsolidatedTax(id);
    }

    /**
     * @description 回算
     * @return void
     * @author Harryxzy
     * @date 2022/11/24 15:52
     */
    public void backCalculate(Long salaryAcctRecordId){
        getSalaryAcctRecordService(user).backCalculate(salaryAcctRecordId);
    }
}
