package com.engine.salary.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.cloudstore.eccom.constant.WeaBoolAttr;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.setting.dto.PageListTemplateDTO;
import com.engine.salary.entity.setting.dto.PageListTemplateDetailDTO;
import com.engine.salary.entity.setting.param.*;
import com.engine.salary.entity.setting.po.PageLinkPO;
import com.engine.salary.entity.setting.po.PageListSettingPO;
import com.engine.salary.entity.setting.po.PageListTemplatePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.SalaryOnOffEnum;
import com.engine.salary.enums.common.SharedTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.setting.PageLinkMapper;
import com.engine.salary.mapper.setting.PageListSettingMapper;
import com.engine.salary.mapper.setting.PageListTemplateMapper;
import com.engine.salary.report.common.constant.SalaryConstant;
import com.engine.salary.service.SalaryItemService;
import com.engine.salary.service.SettingService;
import com.engine.salary.service.TaxAgentService;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.IdGenerator;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.ValidUtil;
import weaver.hrm.User;

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

import static com.engine.salary.constant.SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY;
import static com.engine.salary.enums.setting.PageListSettingPageEnum.SALARY_DETAILS_REPORT;

/**
 * 页面显示
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SettingServiceImpl extends Service implements SettingService {

    private PageListSettingMapper getPageListSettingMapper() {
        return MapperProxyFactory.getProxy(PageListSettingMapper.class);
    }

    private PageListTemplateMapper getPageListTemplateMapper() {
        return MapperProxyFactory.getProxy(PageListTemplateMapper.class);
    }

    private PageLinkMapper getPageLinkMapper() {
        return MapperProxyFactory.getProxy(PageLinkMapper.class);
    }

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

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

    @Override
    public void savePageListSetting(PageListSettingSaveParam pageListSettingSaveParam) {
        ValidUtil.doValidator(pageListSettingSaveParam);

        Date now = new Date();

        //是否保存默认设置
        Integer defaultSetting = pageListSettingSaveParam.getDefaultSetting();
        PageListSettingPO pageListSettingPO;
        if (defaultSetting == 0) {
            pageListSettingPO = getPageListSettingMapper().getByPage(pageListSettingSaveParam.getPage(), defaultSetting, (long) user.getUID());
        } else {
            pageListSettingPO = getPageListSettingMapper().getByPage(pageListSettingSaveParam.getPage(), defaultSetting, null);
        }

        List<String> checked = pageListSettingSaveParam.getSetting().stream().distinct().collect(Collectors.toList());
        if (pageListSettingPO != null) {
            pageListSettingPO.setSetting(checked);
            pageListSettingPO.setUpdateTime(now);
            getPageListSettingMapper().updateIgnoreNull(pageListSettingPO);
        } else {
            pageListSettingPO = PageListSettingPO.builder().id(IdGenerator.generate()).page(pageListSettingSaveParam.getPage()).setting(checked).defaultSetting(defaultSetting).creator((long) user.getUID()).createTime(now).updateTime(now).deleteType(0).tenantKey(DEFAULT_TENANT_KEY).build();
            getPageListSettingMapper().insertIgnoreNull(pageListSettingPO);
        }
    }

    @Override
    public PageListTemplateDetailDTO getDefaultPageListSetting(PageListSettingQueryParam param) {
        String page = param.getPage();
        if (SALARY_DETAILS_REPORT.getValue().equals(page)) {
            List<WeaTableColumn> columns = new ArrayList<>();
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(87614, "薪资所属月"), "salaryMonth"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"), "taxAgent"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "账套"), "salarySob"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "姓名"), "userName"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "分部"), "subCompany"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "部门"), "department"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "岗位"), "jobTitle"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "员工状态"), "status"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "工号"), "workCode"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "入职日期"), "companystartdate"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "次数"), "acctTimes").setDisplay(WeaBoolAttr.FALSE));
            if (StrUtil.isNotBlank(param.getName())) {
                columns = columns.stream().filter(column -> column.getText().contains(param.getName())).collect(Collectors.toList());
            }

            List<SalaryItemPO> salaryItemList = getSalaryItemService(user).listAll();
            List<WeaTableColumn> collect = salaryItemList.stream().filter(po -> {
                String name = param.getName();
                if (StrUtil.isNotEmpty(name)) {
                    return po.getName() != null && po.getName().contains(name);
                }
                return true;
            }).sorted((o1, o2) -> {
                if (o1.getSortedIndex() == null && o2.getSortedIndex() == null) {
                    Integer systemType1 = o1.getSystemType() == null ? 0 : o1.getSystemType();
                    Integer systemType2 = o2.getSystemType() == null ? 0 : o2.getSystemType();
                    return systemType1.compareTo(systemType2);
                } else {
                    Integer sortedIndex1 = o1.getSortedIndex() == null ? 0 : o1.getSortedIndex();
                    Integer sortedIndex2 = o2.getSortedIndex() == null ? 0 : o2.getSortedIndex();
                    return sortedIndex2.compareTo(sortedIndex1);
                }
            }).map(item -> new WeaTableColumn("100px", item.getName(), item.getId() + SalaryConstant.DYNAMIC_SUFFIX)).collect(Collectors.toList());

            columns.addAll(collect);

            Map<String, WeaTableColumn> columnMap = SalaryEntityUtil.convert2Map(columns, WeaTableColumn::getColumn);

            //默认设置
            PageListSettingPO pageListSettingPO = getPageListSettingMapper().getByPage(page, 1, null);

            //查询选中的项目
            List<WeaTableColumn> checkedList = new ArrayList<>();
            if (pageListSettingPO != null) {
                checkedList = Optional.ofNullable(pageListSettingPO.getSetting()).orElse(new ArrayList<>()).stream().map(s -> columnMap.getOrDefault(s, new WeaTableColumn())).collect(Collectors.toList());
            } else {
                checkedList = columns;
            }
            return PageListTemplateDetailDTO.builder().setting(columns).checked(checkedList).build();
        }

        return PageListTemplateDetailDTO.builder().setting(new ArrayList<>()).checked(new ArrayList<>()).build();
    }

    @Override
    public void resetPageListSetting(PageListSettingResetParam param) {
        ValidUtil.doValidator(param);

        String page = param.getPage();

        //个人设置
        PageListSettingPO selfSetting = getPageListSettingMapper().getByPage(page, 0, (long) user.getUID());

        if (selfSetting != null) {
            getPageListSettingMapper().delete(selfSetting);
        }
    }

    @Override
    public PageListTemplateDetailDTO getPageListTemplate(PageListTemplateQueryParam param) {
        String page = param.getPage();
        if (SALARY_DETAILS_REPORT.getValue().equals(page)) {
            List<WeaTableColumn> columns = new ArrayList<>();
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(87614, "薪资所属月"), "salaryMonth"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"), "taxAgent"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "账套"), "salarySob"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "姓名"), "userName"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "分部"), "subCompany"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "部门"), "department"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "岗位"), "jobTitle"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "员工状态"), "status"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "工号"), "workCode"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "证件号码"), "idNo"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "入职日期"), "companystartdate"));
            columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "次数"), "acctTimes").setDisplay(WeaBoolAttr.FALSE));
            if (StrUtil.isNotBlank(param.getName())) {
                columns = columns.stream().filter(column -> column.getText().contains(param.getName())).collect(Collectors.toList());
            }

            List<SalaryItemPO> salaryItemList = getSalaryItemService(user).listAll();
            List<WeaTableColumn> salaryItemCols = salaryItemList.stream().filter(po -> {
                String name = param.getName();
                if (StrUtil.isNotEmpty(name)) {
                    return po.getName() != null && po.getName().contains(name);
                }
                return true;
            }).sorted((o1, o2) -> {
                if (o1.getSortedIndex() == null && o2.getSortedIndex() == null) {
                    Integer systemType1 = o1.getSystemType() == null ? 0 : o1.getSystemType();
                    Integer systemType2 = o2.getSystemType() == null ? 0 : o2.getSystemType();
                    return systemType1.compareTo(systemType2);
                } else {
                    Integer sortedIndex1 = o1.getSortedIndex() == null ? 0 : o1.getSortedIndex();
                    Integer sortedIndex2 = o2.getSortedIndex() == null ? 0 : o2.getSortedIndex();
                    return sortedIndex2.compareTo(sortedIndex1);
                }
            }).map(item -> new WeaTableColumn("100px", item.getName(), item.getId() + SalaryConstant.DYNAMIC_SUFFIX)).collect(Collectors.toList());

            columns.addAll(salaryItemCols);

            Map<String, WeaTableColumn> columnMap = SalaryEntityUtil.convert2Map(columns, WeaTableColumn::getColumn);
            List<WeaTableColumn> checkedList = columns;
            Long id = param.getId();
            if (id != null) {
                //编辑模板，指定模板id
                PageListTemplatePO po = getPageListTemplateMapper().getById(id);
                if (po != null) {
                    checkedList = Optional.ofNullable(po.getSetting()).orElse(new ArrayList<>()).stream().map(s -> columnMap.getOrDefault(s, new WeaTableColumn())).collect(Collectors.toList());
                }
            } else {
                //打开选中的模板
                List<PageListTemplatePO> pageListTemplates = getPageListTemplates(PageListTemplateQueryParam.builder().page(page).build());
                List<WeaTableColumn> columnList = pageListTemplates.stream()
                        .filter(PageListTemplatePO::getChecked).map(PageListTemplatePO::getSetting).findFirst().orElse(new ArrayList<>())
                        .stream().map(s -> columnMap.getOrDefault(s, new WeaTableColumn())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(columnList)) {
                    checkedList = columnList;
                }
            }
            return PageListTemplateDetailDTO.builder().setting(columns).checked(checkedList).build();
        }

        return PageListTemplateDetailDTO.builder().build();
    }

    @Override
    public List<PageListTemplatePO> getPageListTemplates(PageListTemplateQueryParam param) {

        ValidUtil.doValidator(param);

        Date now = new Date();
        String page = param.getPage();

        //个人配置模板
        PageListTemplatePO build = PageListTemplatePO.builder().page(page).build();
        List<PageListTemplatePO> pos = getPageListTemplateMapper().listSome(build);

        //如果查不到不到系统模板，创建系统模板
        PageListTemplatePO systemTemplate = pos.stream().filter(po -> po.getSystemType() != null && po.getSystemType() == 1).findFirst().orElse(null);
        if (systemTemplate == null) {
            //查询系统默认配置
            PageListTemplateDetailDTO pageListSetting = getDefaultPageListSetting(PageListSettingQueryParam.builder().page(SALARY_DETAILS_REPORT.getValue()).build());

            systemTemplate = PageListTemplatePO.builder()
                    .id(IdGenerator.generate())
                    .page(param.getPage())
                    .name("系统模板")
                    .sharedType(SharedTypeEnum.PUBLIC.getValue())
                    .systemType(SalaryOnOffEnum.ON.getValue())
                    .setting(pageListSetting.getChecked().stream().map(WeaTableColumn::getColumn).collect(Collectors.toList()))
                    .creator((long) user.getUID())
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(0)
                    .tenantKey(DEFAULT_TENANT_KEY).build();
            getPageListTemplateMapper().insertIgnoreNull(systemTemplate);
            pos.add(systemTemplate);
        }

        //获取当前选择的模板
        PageLinkPO link = getPageLinkMapper().listSome(PageLinkPO.builder().employeeId((long) user.getUID()).page(SALARY_DETAILS_REPORT.getValue()).build()).stream().findFirst().orElse(null);
        if (link == null) {
            link = PageLinkPO.builder()
                    .id(IdGenerator.generate())
                    .employeeId((long) user.getUID())
                    .page(param.getPage())
                    .templateId(systemTemplate.getId())
                    .tenantKey(DEFAULT_TENANT_KEY)
                    .createTime(new Date())
                    .updateTime(new Date())
                    .creator((long) user.getUID())
                    .deleteType(0).build();
            getPageLinkMapper().insertIgnoreNull(link);
        }
        Long templateId = link.getTemplateId();

        //权限控制
        Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService().listAllTaxAgents((long) user.getUID());
        List<Long> taxIds = SalaryEntityUtil.properties(taxAgentPOS, TaxAgentPO::getId, Collectors.toList());
        Boolean chief = getTaxAgentService().isChief((long) user.getUID());
        pos = pos.stream().filter(po -> {
            SharedTypeEnum sharedTypeEnum = SharedTypeEnum.parseByValue(po.getSharedType());
            //系统模板直接可见
            if (chief || po.getSystemType() == 1) {
                return true;
            }
            //私有，只能自己看到
            if (sharedTypeEnum == SharedTypeEnum.PRIVATE) {
                return Objects.equals((long) user.getUID(), po.getCreator());
            }
            //共享
            if (sharedTypeEnum == SharedTypeEnum.PUBLIC) {
                List<Long> limitIds = po.getLimitIds();
                return CollectionUtil.isEmpty(limitIds) || CollectionUtil.intersection(limitIds, taxIds).size() != 0;
            }
            return true;
        }).peek(po -> {
            po.setChecked(po.getId().equals(templateId));
        }).collect(Collectors.toList());
        return pos;
    }

    @Override
    public PageListTemplatePO savePageListTemplate(PageListTemplateSaveParam param) {
        ValidUtil.doValidator(param);
        Date now = new Date();
        Long id = param.getId();

        PageListTemplatePO po;
        if (id == null) {
            po = PageListTemplatePO.builder()
                    .id(IdGenerator.generate())
                    .page(param.getPage())
                    .name(param.getName())
                    .sharedType(param.getSharedType())
                    .systemType(0)
                    .limitIds(param.getLimitIds())
                    .setting(param.getSetting())
                    .creator((long) user.getUID())
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(0)
                    .tenantKey(DEFAULT_TENANT_KEY).build();
            getPageListTemplateMapper().insertIgnoreNull(po);
        } else {
            po = getPageListTemplateMapper().getById(id);
            if (po == null) {
                throw new SalaryRunTimeException("模板不存在!");
            }
            po.setName(param.getName());
            po.setSharedType(param.getSharedType());
            po.setLimitIds(param.getLimitIds());
            po.setSetting(param.getSetting());
            po.setUpdateTime(now);
            getPageListTemplateMapper().updateIgnoreNull(po);
        }

        return po;
    }

    @Override
    public void changePageListTemplate(PageListTemplateChangeParam param) {

        ValidUtil.doValidator(param);

        List<PageLinkPO> pageLinkPOS = getPageLinkMapper().listSome(PageLinkPO.builder().employeeId((long) user.getUID()).page(param.getPage()).build());
        if (CollUtil.isNotEmpty(pageLinkPOS)) {
            Set<Long> ids = SalaryEntityUtil.properties(pageLinkPOS, PageLinkPO::getId);
            getPageLinkMapper().deleteByIds(ids);
        }
        PageLinkPO pageLinkPO = PageLinkPO.builder().id(IdGenerator.generate()).employeeId((long) user.getUID()).page(param.getPage()).templateId(param.getTemplateId()).tenantKey(DEFAULT_TENANT_KEY).createTime(new Date()).updateTime(new Date()).creator((long) user.getUID()).deleteType(0).build();

        getPageLinkMapper().insertIgnoreNull(pageLinkPO);
    }

    @Override
    public List<WeaTableColumn> getPageListColumns(String page) {
        PageListTemplateDetailDTO pageListTemplate = getPageListTemplate((PageListTemplateQueryParam.builder().page(page).build()));
        return pageListTemplate.getChecked();
    }

    @Override
    public PageInfo<PageListTemplateDTO> getTemplates(PageListTemplateQueryParam param) {
        PageListTemplatePO build = PageListTemplatePO.builder().page(param.getPage()).build();
        List<PageListTemplatePO> pos = getPageListTemplateMapper().listSome(build);

        //权限控制
        List<TaxAgentPO> agentPOList = getTaxAgentService().listAll();
        Map<Long, String> idNameMap = SalaryEntityUtil.convert2Map(agentPOList, TaxAgentPO::getId, TaxAgentPO::getName);
        Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService().listAllTaxAgents((long) user.getUID());
        Boolean chief = getTaxAgentService().isChief((long) user.getUID());
        List<Long> taxIds = SalaryEntityUtil.properties(taxAgentPOS, TaxAgentPO::getId, Collectors.toList());
        List<PageListTemplateDTO> templateDTOS = pos.stream()
                .filter(po -> {
                    SharedTypeEnum sharedTypeEnum = SharedTypeEnum.parseByValue(po.getSharedType());
                    //系统模板直接可见
                    if (chief || po.getSystemType() == 1) {
                        return true;
                    }
                    //私有，只能自己看到
                    if (sharedTypeEnum == SharedTypeEnum.PRIVATE) {
                        return Objects.equals((long) user.getUID(), po.getCreator());
                    }
                    //共享
                    if (sharedTypeEnum == SharedTypeEnum.PUBLIC) {
                        List<Long> limitIds = po.getLimitIds();
                        return CollectionUtil.isEmpty(limitIds) || CollectionUtil.intersection(limitIds, taxIds).size() != 0;
                    }
                    return true;
                }).map(po -> PageListTemplateDTO.builder()
                        .id(po.getId())
                        .page(po.getPage())
                        .name(po.getName())
                        .sharedType(po.getSharedType())
                        .systemType(po.getSystemType())
                        .sharedTypeName(SharedTypeEnum.parseByValue(po.getSharedType()).getDefaultLabel())
                        .systemTypeName(po.getSystemType() == 1 ? "系统模板" : "自定义")
                        .limits(CollUtil.isEmpty(po.getLimitIds()) ? "所有" : Optional.ofNullable(po.getLimitIds()).orElse(new ArrayList<>()).stream().map(id -> idNameMap.getOrDefault(id, "")).collect(Collectors.joining(",")))
                        .limitIds(CollUtil.isEmpty(po.getLimitIds()) ? new ArrayList<>() : po.getLimitIds())
                        .setting(po.getSetting())
                        .canEdit(chief || (Objects.equals((long) user.getUID(), po.getCreator()) && po.getSystemType() == 0))
                        .build())
                .collect(Collectors.toList());

        return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), templateDTOS, PageListTemplateDTO.class);
    }

    @Override
    public void deletePageListTemplate(PageListTemplateDeleteParam param) {
        List<Long> ids = param.getIds();

        if (CollUtil.isEmpty(ids)) {
            throw new SalaryRunTimeException("未选择模板！");
        }

        ids.forEach(id -> {
            PageListTemplatePO pageListTemplatePO = getPageListTemplateMapper().getById(id);
            if (pageListTemplatePO == null) {
                throw new SalaryRunTimeException("模板不存在！");
            }
            if (pageListTemplatePO.getSystemType() == 1) {
                throw new SalaryRunTimeException("系统模板不允许删除！");
            }
            if (!Objects.equals((long) user.getUID(), pageListTemplatePO.getCreator())) {
                throw new SalaryRunTimeException(pageListTemplatePO.getName() + "模板无权限删除！");
            }
            List<PageLinkPO> pageLinkPOS = getPageLinkMapper().listSome(PageLinkPO.builder().templateId(id).build());
            if (CollUtil.isNotEmpty(pageLinkPOS)) {
                throw new SalaryRunTimeException(pageListTemplatePO.getName() + "模板正被使用！不允许删除");
            }
        });

        getPageListTemplateMapper().deleteByIds(ids);
    }
}
