package com.testor.module.contractor.ledger.service.impl;

import cn.hutool.core.util.IdcardUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.biz.sys.dict.data.model.domain.SysDictData;
import com.testor.biz.sys.dict.data.service.SysDictDataService;
import com.testor.common.constant.StatusEnum;
import com.testor.common.core.utils.StringUtils;
import com.testor.common.excel.ExcelResult;
import com.testor.common.excel.SheetData;
import com.testor.common.util.BeanConverUtil;
import com.testor.common.util.excel.EasyExcelUtil;
import com.testor.module.contractor.ledger.dao.TContractorLedgerDao;
import com.testor.module.contractor.ledger.dao.TContractorPersonDao;
import com.testor.module.contractor.ledger.model.domain.TContractorInfo;
import com.testor.module.contractor.ledger.model.domain.TContractorLedger;
import com.testor.module.contractor.ledger.model.domain.TContractorPerson;
import com.testor.module.contractor.ledger.model.domain.TContractorPersonCertificate;
import com.testor.module.contractor.ledger.model.dto.TContractorLedgerParam;
import com.testor.module.contractor.ledger.model.dto.TContractorPersonDto;
import com.testor.module.contractor.ledger.model.dto.TContractorPersonParam;
import com.testor.module.contractor.ledger.model.template.PersonContractorTemplate;
import com.testor.module.contractor.ledger.model.template.PersonJobNatureTemplate;
import com.testor.module.contractor.ledger.model.template.PersonTemplate;
import com.testor.module.contractor.ledger.service.TContractorInfoService;
import com.testor.module.contractor.ledger.service.TContractorLedgerService;
import com.testor.module.contractor.ledger.service.TContractorPersonCertificateService;
import com.testor.module.contractor.ledger.service.TContractorPersonService;
import com.testor.module.sys.model.domian.NewSysOrg;
import com.testor.module.sys.service.NewSysDictDataService;
import com.testor.module.sys.service.NewSysOrgService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.models.exceptions.ServiceException;
import com.tongtech.tfw.backend.common.models.response.ResponseInfo;
import com.tongtech.tfw.backend.common.models.supers.SuperModel;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 承包商管理人员台账Service业务层处理
 * 
 * @author testor-framework
 * @date 2024-11-20 09:58:38
 */
@Slf4j
@Service
public class TContractorPersonServiceImpl extends SuperServiceImpl<TContractorPersonDao, TContractorPerson> implements TContractorPersonService
{
    @Autowired(required = false)
    private TContractorPersonDao tContractorPersonDao;

    @Autowired
    private NewSysDictDataService newSysDictDataService;

    @Autowired
    private TContractorInfoService tContractorInfoService;

    @Autowired
    private TContractorLedgerService tContractorLedgerService;

    @Autowired
    private TContractorPersonCertificateService tContractorPersonCertificateService;

    @Autowired
    private NewSysOrgService newSysOrgService;
    @Resource
    private TContractorLedgerDao contractorLedgerDao;


    @Override
    public void downloadTemplate(HttpServletResponse response) {
        List<SheetData<Object>> sheetData = buildSheetDataList();
        EasyExcelUtil.writeExcelBySelectMultiSheet(response,"导入模板",sheetData);
    }

    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importTemplate(MultipartFile file) {
        try {
            // 导入Excel文件，将文件流转换为PersonTemplate对象列表
            ExcelResult<PersonTemplate> personTemplateExcelResult = EasyExcelUtil.importExcel(file.getInputStream(), PersonTemplate.class, true);

            // 获取PersonTemplate对象列表
            List<PersonTemplate> templates = personTemplateExcelResult.getList();
            if (templates == null || templates.isEmpty()) {
                throw new ServiceException(new ResponseInfo(400, "导入文件内容为空，请检查后重新上传！"));
            }

            for (PersonTemplate template : templates) {
                String jobNatureName = template.getJobNatureName();
                SysDictData jobNature = newSysDictDataService.getDictByTypeAndValue("contractor_person_position_type", jobNatureName);
                if (jobNature != null) {
                    template.setJobNatureId(jobNature.getDictDataId());
                }else {
                    throw new ServiceException(new ResponseInfo(400, "未找到对应的岗位性质："+jobNatureName));
                }
                // 获取岗位名称
                String jobTitleName = template.getJobTitleName();
                SysDictData dictByParentIdAndValue = newSysDictDataService.getDictByParentIdAndValue(jobNature.getDictDataId(), jobTitleName);
                if (dictByParentIdAndValue != null) {
                    template.setJobTitleId(dictByParentIdAndValue.getDictDataId());
                } else {
                    throw new ServiceException(new ResponseInfo(400, "未找到岗位性质："+jobNatureName+",对应的岗位名称:+"+jobTitleName));
                }
                // 获取承包商   根据承包商名称查询对应的台账信息，获取info_id
                TContractorLedger infoByName = tContractorLedgerService.findLedgerByName(template.getInfoId());
                if (infoByName != null) {
                    template.setInfoId(infoByName.getInfoId());
                } else {
                    throw new ServiceException(new ResponseInfo(400, "未找到对应的承包商信息，承包商名称：" + template.getInfoId()));
                }
                TContractorPersonDto tContractorPersonDto = BeanConverUtil.conver(template, TContractorPersonDto.class);
                this.addEntity(tContractorPersonDto);
            }
        } catch (IOException e) {
            throw new ServiceException(new ResponseInfo(500, "文件读取失败，请检查文件格式！"));
        } catch (ServiceException se) {
            throw se; // 保留业务异常原样抛出
        }
    }

    /**
     * 添加承包商人员实体
     *
     * @param addRequest 包含承包商人员及其资质信息的请求对象
     * @return 保存后的承包商人员实体
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TContractorPerson addEntity(TContractorPersonDto addRequest) {
        validateIdCard(addRequest.getIdCardNo(), null); // 校验身份证号码

        String id = IdHelper.getId32bit();
        TContractorPerson data = BeanConverUtil.conver(addRequest, TContractorPerson.class);
        data.setId(id);
        data.setOrgId(ContextUtils.getLoginUser().getOrgId());
        if (!this.save(data)) {
            throw new ServiceException(new ResponseInfo(400, "承包商人员信息保存失败！"));
        }

        saveCertificates(addRequest.getTContractorPersonCertificates(), id);
        return data;
    }

    /**
     * 更新承包商人员实体
     *
     * @param updateRequest 包含承包商人员及其资质信息的请求对象
     * @return 更新是否成功
     */
    @Override
    public boolean updateEntity(TContractorPersonDto updateRequest) {
        validateIdCard(updateRequest.getIdCardNo(), updateRequest.getId()); // 校验身份证号码

        TContractorPerson data = BeanHelper.beanToBean(updateRequest, TContractorPerson.class);
        if (!this.updateById(data)) {
            throw new ServiceException(new ResponseInfo(400, "承包商人员信息更新失败！"));
        }

        List<TContractorPersonCertificate> certificates =
                tContractorPersonCertificateService.list(new QueryWrapper<TContractorPersonCertificate>().eq("person_id", data.getId()));
        boolean removeResult = tContractorPersonCertificateService.remove(
                new QueryWrapper<TContractorPersonCertificate>().eq("person_id", data.getId())
        );
        if (!removeResult && ObjectHelper.isNotEmpty(certificates)) {
            throw new ServiceException(new ResponseInfo(400, "旧承包商人员证书删除失败！"));
        }

        saveCertificates(updateRequest.getTContractorPersonCertificates(), data.getId());
        return true;
    }

    @Override
    public Page<TContractorPerson> listEntity(TContractorPersonParam param) {
        Long page=
                StringHelper.isEmpty(param.getPage())?BizConstants.PAGE:Long.valueOf(param.getPage());
        Long limit=
                StringHelper.isEmpty(param.getLimit())?BizConstants.LIMIT:Long.valueOf(param.getLimit());
        Page<TContractorPerson> resultPage=new Page<>(page,limit);
        // TODO 根据需求修改查询条件及查询参数
        QueryWrapper<TContractorPerson> queryWrapper=this.createQuery(param);
        return this.page(resultPage, queryWrapper);
    }

    @Override
    public List<TContractorPerson> listAllEntity(TContractorPersonParam param) {
        QueryWrapper<TContractorPerson> queryWrapper=this.createQuery(param);
        return this.list(queryWrapper);
    }

    @Override
    public List<TContractorPerson> ValidPeopleList(TContractorPersonParam param) {
        QueryWrapper<TContractorPerson> query = this.createQuery(param);
        query.eq(TContractorPerson.JOB_STATUS, 1);
        return this.list(query).stream().filter(tContractorPerson -> {

            int age = IdcardUtil.getAgeByIdCard(tContractorPerson.getIdCardNo());
            int gender = IdcardUtil.getGenderByIdCard(tContractorPerson.getIdCardNo());
            if (gender == 1){
                return age <= 60;
            }else {
                return age <= 55;
            }
        }).collect(Collectors.toList());
    }

    /**
     * 校验身份证号码的合法性及唯一性
     *
     * @param idCardNo 身份证号码
     * @param excludeId 排除的人员ID（更新时使用）
     */
    private void validateIdCard(String idCardNo, String excludeId) {
        if (!IdcardUtil.isValidCard(idCardNo)) {
            throw new ServiceException(new ResponseInfo(400, "身份证号码["+idCardNo+"]格式不正确！"));
        }

        LambdaQueryWrapper<TContractorPerson> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TContractorPerson::getIdCardNo, idCardNo).eq(SuperModel::getStatus, StatusEnum.USE.getCode());
        if (excludeId != null) {
            queryWrapper.ne(TContractorPerson::getId, excludeId);
        }

        if (this.count(queryWrapper) > 0) {
            throw new ServiceException(new ResponseInfo(400, "身份证号码["+idCardNo+"]已存在！"));
        }
    }

    /**
     * 批量保存承包商人员证书
     *
     * @param certificates 承包商人员证书列表
     * @param personId 承包商人员ID
     */
    private void saveCertificates(List<TContractorPersonCertificate> certificates, String personId) {
        if (ObjectHelper.isNotEmpty(certificates)) {
            certificates.forEach(cert -> cert.setPersonId(personId));
            if (!tContractorPersonCertificateService.saveBatch(certificates)) {
                throw new ServiceException(new ResponseInfo(400, "承包商人员证书保存失败！"));
            }
        }
    }



    private List<SheetData<Object>> buildSheetDataList() {
        List<SheetData<Object>> sheetDataList = new ArrayList<>();

        // 添加“导入模板”Sheet
        sheetDataList.add(createSheetData("导入模板", 0, Collections.singletonList(new PersonTemplate())));

        // 添加“参考文件-岗位性质-岗位名称”Sheet
        List jobNatureList = buildPersonJobNatureList();
        sheetDataList.add(createSheetData("参考文件-岗位性质-岗位名称", 1, jobNatureList));

        // 添加“参考文件-承包商信息”Sheet
        List contractorTemplates = buildPersonContractorTemplateList();
        sheetDataList.add(createSheetData("参考文件-承包商信息", 2, contractorTemplates));

        return sheetDataList;
    }

    private List<PersonJobNatureTemplate> buildPersonJobNatureList() {
        // 获取字典数据并按 parentId 分组
        List<SysDictData> dictByType = newSysDictDataService.getDictByType("contractor_person_position_type");
        Map<String, List<SysDictData>> groupedByParentId = dictByType.stream()
                .collect(Collectors.groupingBy(SysDictData::getParentId));

        // 构造结果列表
        List<PersonJobNatureTemplate> templates = dictByType.stream()
                .filter(parent -> groupedByParentId.containsKey(parent.getDictDataId()))
                .flatMap(parent -> groupedByParentId.get(parent.getDictDataId()).stream()
                        .map(child -> {
                            PersonJobNatureTemplate template = new PersonJobNatureTemplate();
                            template.setJobNatureId(parent.getDictValue()); // 父级的 dictValue
                            template.setJobTitleId(child.getDictValue()); // 子级的 dictValue
                            return template;
                        })
                ).collect(Collectors.toList());
        if (templates.isEmpty()){
            templates.add(new PersonJobNatureTemplate());
        }
        return templates;
    }

    private List<PersonContractorTemplate> buildPersonContractorTemplateList() {

        TContractorLedgerParam param = new TContractorLedgerParam();
        param.setOrgId(ContextUtils.getLoginUser().getOrgId());
        List<String> contractorLedgerNames = contractorLedgerDao.findContractorLedgerNames(param);
        List<PersonContractorTemplate> personContractorTemplates = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(contractorLedgerNames)){
            contractorLedgerNames.forEach(contractorLedgerName -> {
                if (StringUtils.isNotBlank(contractorLedgerName)){
                    PersonContractorTemplate template = new PersonContractorTemplate();
                    template.setContractorName(contractorLedgerName);
                    personContractorTemplates.add(template);
                }

            });
        }
        return  personContractorTemplates;
    }

    private <T> SheetData<T> createSheetData(String sheetName, int index, List<T> data) {
        SheetData<T> sheetData = new SheetData<>();
        sheetData.setSheetName(sheetName);
        sheetData.setIndex(index);
        sheetData.setData(data);
        return sheetData;
    }


    /**
     * 列表查询条件及查询参数
     */
    private QueryWrapper<TContractorPerson> createQuery(TContractorPersonParam queryParam){
        QueryWrapper<TContractorPerson> queryWrapper=new QueryWrapper<>();
        //获取当前登录用户所在机构的ID
        String orgId = ContextUtils.getLoginUser().getOrgId();
        log.info("承包商人员台账列表--当前登录用户所在机构的ID:{}",orgId);
//        //根据机构ID获取机构信息
//        NewSysOrg byId = newSysOrgService.getById(orgId);
//        //获取当前机构的父级机构ID
////        String parentId = byId.getOrgId();
//        //将父级机构ID转换为集合
//        List<String> ids = new ArrayList<>(Arrays.asList(byId.getParentIds().split(",")));
//        //将当前机构ID添加到集合中
//        ids.add(orgId);
//        //获取同一机构下的机构
//        List<NewSysOrg> newSysOrgs = newSysOrgService.list(new QueryWrapper<NewSysOrg>().eq("parent_id", orgId));
//        //如果同一机构下的机构数量大于0
//        if(newSysOrgs.size()>0){
//            //将同一机构下的机构ID转换为集合
//            List<String> orgIds = newSysOrgs.stream().map(NewSysOrg::getOrgId).collect(Collectors.toList());
//            //将同一机构下的机构ID添加到集合中
//            ids.addAll(orgIds);
//        }
        List<String> ids = newSysOrgService.getIdsChildrenById(orgId);

        //查询同一机构创建的人员
        queryWrapper.in(TContractorPerson.ORG_ID,ids);

        if (ObjectHelper.isNotEmpty(queryParam.getIds())) {
            if ("0".equals(queryParam.getTypeQuery())){
                queryWrapper.notIn("id", queryParam.getIds());
            }else {
                queryWrapper.in("id", queryParam.getIds());
            }
        }
        if (StringHelper.isNotEmpty(queryParam.getContractorId())){
            TContractorLedger tContractorLedger = tContractorLedgerService.getById(queryParam.getContractorId());
            if (tContractorLedger != null){
                queryWrapper.eq(TContractorPerson.INFO_ID,tContractorLedger.getInfoId());
            }
        }
        if(StringHelper.isNotEmpty(queryParam.getInfoId())){
            queryWrapper.eq(TContractorPerson.INFO_ID,queryParam.getInfoId());
        }
        if(StringHelper.isNotEmpty(queryParam.getName())){
            queryWrapper.like(TContractorPerson.NAME,queryParam.getName());
        }
        if(StringHelper.isNotEmpty(queryParam.getGender())){
            queryWrapper.eq(TContractorPerson.GENDER,queryParam.getGender());
        }
        if(StringHelper.isNotEmpty(queryParam.getJobStatus())){
            queryWrapper.eq(TContractorPerson.JOB_STATUS,queryParam.getJobStatus());
        }
        if(StringHelper.isNotEmpty(queryParam.getIdCardNo())){
            queryWrapper.eq(TContractorPerson.ID_CARD_NO,queryParam.getIdCardNo());
        }
        if(ObjectHelper.isNotEmpty(queryParam.getAge())){
            queryWrapper.eq(TContractorPerson.AGE,queryParam.getAge());
        }
        if(ObjectHelper.isNotEmpty(queryParam.getHireDate())){
            queryWrapper.eq(TContractorPerson.HIRE_DATE,queryParam.getHireDate());
        }
        if(StringHelper.isNotEmpty(queryParam.getJobNatureId())){
            queryWrapper.eq(TContractorPerson.JOB_NATURE_ID,queryParam.getJobNatureId());
        }
        if(StringHelper.isNotEmpty(queryParam.getJobNature())){
            queryWrapper.eq(TContractorPerson.JOB_NATURE,queryParam.getJobNature());
        }
        if(StringHelper.isNotEmpty(queryParam.getJobTitleId())){
            queryWrapper.eq(TContractorPerson.JOB_TITLE_ID,queryParam.getJobTitleId());
        }
        if(StringHelper.isNotEmpty(queryParam.getJobTitle())){
            queryWrapper.eq(TContractorPerson.JOB_TITLE,queryParam.getJobTitle());
        }
        if(StringHelper.isNotEmpty(queryParam.getTel())){
            queryWrapper.eq(TContractorPerson.TEL,queryParam.getTel());
        }
        if(StringHelper.isNotEmpty(queryParam.getContractTerm())){
            queryWrapper.eq(TContractorPerson.CONTRACT_TERM,queryParam.getContractTerm());
        }
        if(StringHelper.isNotEmpty(queryParam.getIsOc())){
            queryWrapper.eq(TContractorPerson.IS_OC,queryParam.getIsOc());
        }
        if(StringHelper.isNotEmpty(queryParam.getOcDiseaseId())){
            queryWrapper.eq(TContractorPerson.OC_DISEASE_ID,queryParam.getOcDiseaseId());
        }
        if(StringHelper.isNotEmpty(queryParam.getOcDisease())){
            queryWrapper.eq(TContractorPerson.OC_DISEASE,queryParam.getOcDisease());
        }
        if(StringHelper.isNotEmpty(queryParam.getHealth())){
            queryWrapper.eq(TContractorPerson.HEALTH,queryParam.getHealth());
        }
        if(StringHelper.isNotEmpty(queryParam.getContraindication())){
            queryWrapper.eq(TContractorPerson.CONTRAINDICATION,queryParam.getContraindication());
        }
        if(ObjectHelper.isNotEmpty(queryParam.getInsurancePeriod())){
            queryWrapper.eq(TContractorPerson.INSURANCE_PERIOD,queryParam.getInsurancePeriod());
        }
        if(StringHelper.isNotEmpty(queryParam.getInsuranceType())){
            queryWrapper.eq(TContractorPerson.INSURANCE_TYPE,queryParam.getInsuranceType());
        }
        if(StringHelper.isNotEmpty(queryParam.getPhoto())){
            queryWrapper.eq(TContractorPerson.PHOTO,queryParam.getPhoto());
        }
        if(StringHelper.isNotEmpty(queryParam.getInsurance())){
            queryWrapper.eq(TContractorPerson.INSURANCE,queryParam.getInsurance());
        }
        if(StringHelper.isNotEmpty(queryParam.getHealthReport())){
            queryWrapper.eq(TContractorPerson.HEALTH_REPORT,queryParam.getHealthReport());
        }
        if(StringHelper.isNotEmpty(queryParam.getEmployeeContract())){
            queryWrapper.eq(TContractorPerson.EMPLOYEE_CONTRACT,queryParam.getEmployeeContract());
        }
        if(StringHelper.isNotEmpty(queryParam.getOrgId())){
            queryWrapper.eq(TContractorPerson.ORG_ID,queryParam.getOrgId());
        }
        if (StringHelper.isNotEmpty(queryParam.getStatus())) {
            queryWrapper.eq(TContractorPerson.STATUS, queryParam.getStatus());
        } else {
            queryWrapper.ne(TContractorPerson.STATUS, BizConstants.STATUS_DELETE);
        }
        if (StringHelper.isNotEmpty(queryParam.getOrderBy())){
            if(StringHelper.isNotEmpty(queryParam.getOrderType())
                    &&BizConstants.ASC.equals(queryParam.getOrderType())){
                queryWrapper.orderByAsc(queryParam.getOrderBy());
            }else{
                queryWrapper.orderByDesc(queryParam.getOrderBy());
            }
        }else{
            queryWrapper.orderByDesc(TContractorPerson.UPDATE_DATE);
        }
        return queryWrapper;
    }



}
