package cn.lihongjie.coal.empSalaryItemConfig.service;

import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.empSalaryItem.entity.EmpSalaryItemEntity;
import cn.lihongjie.coal.empSalaryItem.service.EmpSalaryItemService;
import cn.lihongjie.coal.empSalaryItemConfig.dto.CreateEmpSalaryItemConfigDto;
import cn.lihongjie.coal.empSalaryItemConfig.dto.EmpSalaryItemConfigDto;
import cn.lihongjie.coal.empSalaryItemConfig.dto.UpdateEmpSalaryItemConfigDto;
import cn.lihongjie.coal.empSalaryItemConfig.entity.EmpSalaryItemConfigEntity;
import cn.lihongjie.coal.empSalaryItemConfig.mapper.EmpSalaryItemConfigMapper;
import cn.lihongjie.coal.empSalaryItemConfig.repository.EmpSalaryItemConfigRepository;
import cn.lihongjie.coal.empSalaryStandard.entity.EmpSalaryStandardEntity;
import cn.lihongjie.coal.empSalaryStandard.service.EmpSalaryStandardService;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;

import lombok.extern.slf4j.Slf4j;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Slf4j
@Transactional
public class EmpSalaryItemConfigService
        extends BaseService<EmpSalaryItemConfigEntity, EmpSalaryItemConfigRepository> {
    @Autowired private EmpSalaryItemConfigRepository repository;

    @Autowired private EmpSalaryItemConfigMapper mapper;

    @Autowired private ConversionService conversionService;

    public EmpSalaryItemConfigDto create(CreateEmpSalaryItemConfigDto request) {
        EmpSalaryItemConfigEntity entity = mapper.toEntity(request);

        this.repository.save(entity);
        return getById(entity.getId());
    }

    public EmpSalaryItemConfigDto update(UpdateEmpSalaryItemConfigDto request) {
        EmpSalaryItemConfigEntity entity = this.repository.get(request.getId());
        this.mapper.updateEntity(entity, request);

        this.repository.save(entity);

        return getById(entity.getId());
    }

    public void delete(IdRequest request) {
        this.repository.deleteAllById(request.getIds());
    }

    public EmpSalaryItemConfigDto getById(String id) {
        EmpSalaryItemConfigEntity entity = repository.get(id);

        return mapper.toDto(entity);
    }

    public Page<EmpSalaryItemConfigDto> list(CommonQuery query) {
        Page<EmpSalaryItemConfigEntity> page =
                repository.findAll(
                        query.specification(conversionService),
                        PageRequest.of(
                                query.getPageNo(),
                                query.getPageSize(),
                                Sort.by(query.getOrders())));

        return page.map(this.mapper::toDto);
    }


    @Autowired EmpSalaryItemService empSalaryItemService;

    @NotNull
    private static EmpSalaryItemConfigEntity createEmpConfig(String organizationId,String name, String code,  String expression, String expressionShow, boolean systemPreset, String itemType) {
        EmpSalaryItemConfigEntity config = new EmpSalaryItemConfigEntity();
        config.setName(name);
        config.setCode(code);
        config.setOrganizationId(organizationId);
        config.setItemType(itemType);
        config.setExpression(expression);
        config.setExpressionShow(expressionShow);
        config.setSystemPreset(systemPreset);
        return config;
    }

    public void initOrg(String organizationId) {

        // 所有启用的工资项目, 系统预设, 无法编辑

        initSalaItem(organizationId);

        // 人员信息字段, 可编辑

        initEmp(organizationId);

        // 工资标准字段, 系统预设, 无法编辑

        initSalaStandard(organizationId);

        // 其他辅助信息字段, 系统预设, 无法编辑

        initOthers(organizationId);

        // 自定义函数, 可编辑

        initCustomFunctions(organizationId);






















    }

    private void initCustomFunctions(String organizationId) {

    }

    private void initOthers(String organizationId) {
        long delete = repository.deleteByOrganizationIdAndItemType(organizationId, "3");


        this.repository.save(createEmpConfig(organizationId, "发放年度", "batchYear", "batch?.batchYearMonth?.year", "发放年度", false, "3"));
        this.repository.save(createEmpConfig(organizationId, "发放月份", "batchMonth", "batch?.batchYearMonth?.monthValue", "发放月份", false, "3"));
        this.repository.save(createEmpConfig(organizationId, "发放批次号", "batchNo", "batch?.batchNo", "发放批次号", false, "3"));

    }

    @Autowired private EmpSalaryStandardService empSalaryStandardService;

    private void initSalaStandard(String organizationId) {

        long delete = repository.deleteByOrganizationIdAndItemType(organizationId, "2");

        List<EmpSalaryStandardEntity> items = empSalaryStandardService.findAll(
                new Specification<EmpSalaryStandardEntity>() {
                    @Override
                    public Predicate toPredicate(
                            Root<EmpSalaryStandardEntity> root,
                            CriteriaQuery<?> query,
                            CriteriaBuilder criteriaBuilder) {
                        return criteriaBuilder.and(
                                criteriaBuilder.equal(root.get("organizationId"), organizationId),
                                criteriaBuilder.equal(root.get("status"), 1));
                    }
                });


        for (EmpSalaryStandardEntity item : items) {

            this.repository.save(createEmpConfig(organizationId, item.getName(), "std_" +  item.getCode(), "stdMap[\"" +  item.getName() + "\"]", item.getName(),true, "2"));
        }
    }

    private void initEmp(String organizationId) {

        long delete = repository.deleteByOrganizationIdAndItemType(organizationId, "0");


        this.repository.save(createEmpConfig(organizationId,"部门编码", "emp_departmentCode",  "emp?.department?.code", "部门编码", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"部门名称", "emp_departmentName",  "emp?.department?.name", "部门名称", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"岗位编码", "emp_jobPostCode",  "emp?.jobPost?.code", "岗位编码", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"岗位名称", "emp_jobPostName",  "emp?.jobPost?.name", "岗位名称", false, "0"));


        this.repository.save(createEmpConfig(organizationId,"养老保险基数", "emp_insurance1Base",  "emp.insurance1Base", "养老保险基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"养老保险基数", "emp_insurance1Base",  "emp.insurance1Base", "养老保险基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"养老保险比例", "emp_insurance1Percent",  "emp.insurance1Percent", "养老保险比例", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"医疗保险基数", "emp_insurance2Base",  "emp.insurance2Base", "医疗保险基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"医疗保险比例", "emp_insurance2Percent",  "emp.insurance2Percent", "医疗保险比例", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"失业保险基数", "emp_insurance3Base",  "emp.insurance3Base", "失业保险基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"失业保险比例", "emp_insurance3Percent",  "emp.insurance3Percent", "失业保险比例", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"工伤保险基数", "emp_insurance4Base",  "emp.insurance4Base", "工伤保险基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"工伤保险比例", "emp_insurance4Percent",  "emp.insurance4Percent", "工伤保险比例", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"生育保险基数", "emp_insurance5Base",  "emp.insurance5Base", "生育保险基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"生育保险比例", "emp_insurance5Percent",  "emp.insurance5Percent", "生育保险比例", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"住房公积金基数", "emp_insurance6Base",  "emp.insurance6Base", "住房公积金基数", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"住房公积金比例", "emp_insurance6Percent",  "emp.insurance6Percent", "住房公积金比例", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"姓名", "emp_name",  "emp.name", "姓名", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"性别", "emp_sex",  "emp.sex", "性别", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"民族", "emp_nation",  "emp.nation", "民族", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"婚姻状况", "emp_marriage",  "emp.marriage", "婚姻状况", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"入职时间", "emp_entryDate",  "emp.entryDate", "入职时间", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"离职时间", "emp_resignDate",  "emp.resignDate", "离职时间", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"身份证号", "emp_idCard",  "emp.idCard", "身份证号", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"学历", "emp_education",  "emp.education", "学历", false, "0"));
        this.repository.save(createEmpConfig(organizationId,"手机号", "emp_phone",  "emp.phone", "手机号", false, "0"));
        this.repository.save(createEmpConfig(organizationId, "员工状态", "emp_empStatus","emp.empStatus", "员工状态", false, "0"));


    }

    private void initSalaItem(String organizationId) {



        long delete = repository.deleteByOrganizationIdAndItemType(organizationId, "1");

        List<EmpSalaryItemEntity> items = empSalaryItemService.findAll(
                new Specification<EmpSalaryItemEntity>() {
                    @Override
                    public Predicate toPredicate(
                            Root<EmpSalaryItemEntity> root,
                            CriteriaQuery<?> query,
                            CriteriaBuilder criteriaBuilder) {
                        return criteriaBuilder.and(
                                criteriaBuilder.equal(root.get("organizationId"), organizationId),
                                criteriaBuilder.equal(root.get("status"), 1));
                    }
                });


        for (EmpSalaryItemEntity item : items) {

            this.repository.save(createEmpConfig(organizationId, item.getName(), "salary_" + item.getCode(),"salary." + item.getCode(), item.getName(), true, "1"));
        }
    }


}
