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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.common.core.constant.Constants;
import com.testor.common.util.BeanConverUtil;
import com.testor.module.contractor.common.model.constant.ContractorProcessStatus;
import com.testor.module.contractor.enums.ContractorFlowTypeEnum;
import com.testor.module.contractor.manage.dao.TContractorAllowDao;
import com.testor.module.contractor.manage.model.domain.TContractorAllow;
import com.testor.module.contractor.manage.model.domain.TContractorBasicInfo;
import com.testor.module.contractor.manage.model.domain.TContractorPreparation;
import com.testor.module.contractor.manage.model.dto.TContractorAllowDTO;
import com.testor.module.contractor.manage.model.dto.TContractorAllowParam;
import com.testor.module.contractor.manage.model.dto.TContractorAllowPersonParam;
import com.testor.module.contractor.manage.model.dto.TContractorPreparationParam;
import com.testor.module.contractor.manage.service.TContractorAllowService;
import com.testor.module.contractor.manage.service.TContractorBasicInfoService;
import com.testor.module.contractor.manage.service.TContractorPreparationService;
import com.testor.module.hazard.dao.TContractorAccessLogApprovalDao;
import com.testor.module.hazard.dao.TContractorAccessLogDao;
import com.testor.module.hazard.model.domain.TContractorAccessLogApproval;
import com.testor.module.hazard.service.TContractorAccessLogApprovalService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.exception.BusinessException;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.workflow.apis.definition.controller.ProcessDefinitionController;
import com.tongtech.tfw.workflow.apis.definition.model.dto.ProcessDefStartParam;
import com.tongtech.tfw.workflow.apis.task.controller.WfTaskController;
import com.tongtech.tfw.workflow.apis.task.model.dto.CompleteTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 准入管理Service业务层处理
 * 
 * @author testor-framework
 * @date 2024-11-26 14:07:35
 */
@Service
@Slf4j
public class TContractorAllowServiceImpl extends SuperServiceImpl<TContractorAllowDao, TContractorAllow> implements TContractorAllowService
{
    @Autowired(required = false)
    private TContractorAllowDao tContractorAllowDao;

    @Autowired
    private ProcessDefinitionController processDefinitionController;

    @Autowired
    private WfTaskController wfTaskController;

    @Autowired
    private TContractorPreparationService tContractorPreparationService;

    @Autowired
    private TContractorAccessLogApprovalDao contractorAccessLogApprovalDao;

    @Autowired
    private TContractorBasicInfoService tContractorBasicInfoService;

    @Autowired
    private TContractorAccessLogDao contractorAccessLogDao;

    @Override
    public Page<TContractorAllowDTO> pageList(TContractorAllowParam 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<TContractorAllow> resultPage=new Page<>(page,limit);
        // TODO 根据需求修改查询条件及查询参数
        Page<TContractorAllowDTO> tContractorAllowDTOPage = tContractorAllowDao.pageList(resultPage, param);

        //自己创建的+状态已通过+没有进行中的修改记录=可以修改
        //自己创建的+状态已通过+有进行中的修改记录=不能修改
        //自己创建的+状态未通过+没有进行中的修改记录=不能修改
        //自己创建的+状态未通过+有进行中的修改记录=不能修改
        //不是自己创建的+状态已通过+没有进行中的修改记录=不能修改
        //不是自己创建的+状态已通过+有进行中的修改记录=不能修改
        //不是自己创建的+状态未通过+没有进行中的修改记录=不能修改
        //不是自己创建的+状态未通过+有进行中的修改记录=不能修改
        for(TContractorAllowDTO tContractorAllowDTO:tContractorAllowDTOPage.getRecords()){
            if (param.getCreateBy() != null) {
                // 初始设置：如果是自己创建的，有审批权限
                tContractorAllowDTO.setApproval(
                        param.getCreateBy().equals(tContractorAllowDTO.getCreateBy()) ?
                                Constants.APPROVAL_STATUS_ONE : Constants.APPROVAL_STATUS_ZERO
                );
                // 如果记录状态是"已通过"
                if(null != tContractorAllowDTO.getProcessStatus()){
                    if (tContractorAllowDTO.getProcessStatus().equals(ContractorProcessStatus.APPROVED.getValue())) {
                        // 检查是否有进行中的审批记录
                        if (contractorAccessLogApprovalDao.selectCountByContractorAllowIdAndApprovalStatus(
                                tContractorAllowDTO.getId(), ContractorProcessStatus.UNDER_REVIEW.getValue()) > 0) {
                            // 有进行中的审批记录：有审批权限，但不能修改
                            List<TContractorAccessLogApproval> tContractorAccessLogApprovals = contractorAccessLogApprovalDao.selectByContractorAllowIdAndNameBy(tContractorAllowDTO.getId(), param.getCreateBy());
                            if(tContractorAccessLogApprovals.size() > 0){
                                tContractorAllowDTO.setApproval(Constants.APPROVAL_STATUS_ONE);
                            }else{
                                tContractorAllowDTO.setApproval(Constants.APPROVAL_STATUS_ZERO);
                            }
                            tContractorAllowDTO.setModify(Constants.MODIFY_STATUS_ZERO);
                        } else {
                            // 没有进行中的审批记录：无审批权限，但如果是自己创建的可以修改
                            tContractorAllowDTO.setApproval(Constants.APPROVAL_STATUS_ZERO);
                            tContractorAllowDTO.setModify(
                                    param.getCreateBy().equals(tContractorAllowDTO.getCreateBy()) ?
                                            Constants.MODIFY_STATUS_ONE : Constants.MODIFY_STATUS_ZERO
                            );
                        }
                    } else {
                        // 记录状态不是"已通过"：无审批权限，无修改权限
                        tContractorAllowDTO.setApproval(Constants.APPROVAL_STATUS_ZERO);
                        tContractorAllowDTO.setModify(Constants.MODIFY_STATUS_ZERO);
                    }
                }else {
                    // 记录状态不是"已通过"：无审批权限，无修改权限
                    tContractorAllowDTO.setApproval(Constants.APPROVAL_STATUS_ZERO);
                    tContractorAllowDTO.setModify(Constants.MODIFY_STATUS_ZERO);
                }

            }
        }
        return tContractorAllowDTOPage;
    }

    @Override
    public void submit(TContractorAllowParam tContractorAllowPersonParam) {
        ProcessDefStartParam processDefStartParam = new ProcessDefStartParam("contractor");
        processDefStartParam.setBizKey(tContractorAllowPersonParam.getId());
        Map<String, Object> map = new HashMap<>();
        map.put("type", ContractorFlowTypeEnum.ADMIT.getCode());
        if (tContractorAllowPersonParam.getMap() != null){
            map.putAll(tContractorAllowPersonParam.getMap());
        }
        processDefStartParam.setVariables(map);
        String result = processDefinitionController.startProcessIns(processDefStartParam).getData().getResult();
        TContractorAllow tContractorAllow = BeanConverUtil.conver(tContractorAllowPersonParam, TContractorAllow.class);
        tContractorAllow.setProcessId(result);
        tContractorAllow.setProcessStatus(ContractorProcessStatus.UNDER_REVIEW.getValue());
        this.updateById(tContractorAllow);
    }

    @Override
    public void completeProcess(TContractorAllowParam tContractorAllowParam) {
        TContractorAllow tContractorAllow = this.getById(tContractorAllowParam.getId());
        String processStatus = tContractorAllowParam.getProcessStatus();
        CompleteTask completeTask = new CompleteTask();
        completeTask.setBizId(tContractorAllowParam.getId());
        completeTask.setTaskId(tContractorAllowParam.getTaskId());
        Map<String, Object> map = new HashMap<>();
        map.put("processStatus", processStatus);
        if (tContractorAllowParam.getMap() != null){
            map.putAll(tContractorAllowParam.getMap());
        }
        completeTask.setVars(map);
        wfTaskController.completeTask(completeTask).getData().getResult();
        // 创建一个TContractorBasicInfo对象
        tContractorAllow.setProcessStatus(processStatus);
        // 调用tContractorBasicInfoService的updateById方法，更新tContractorBasicInfo对象
        this.updateById(tContractorAllow);
        //如果审核状态为通过推送数据到开工准备
        if (processStatus.equals(ContractorProcessStatus.APPROVED.getValue())){
            TContractorPreparationParam tContractorPreparation = new TContractorPreparationParam();
            tContractorPreparation.setContractorId(tContractorAllow.getContractorId());
            tContractorPreparation.setBizId(tContractorAllow.getBizId());
            tContractorPreparation.setOrgId(tContractorAllow.getOrgId());
            tContractorPreparation.setProjId(tContractorAllow.getProjId());
            tContractorPreparation.setCreateBy(tContractorAllow.getCreateBy());
            tContractorPreparation.setUpdateBy(tContractorAllow.getUpdateBy());
            tContractorPreparationService.addEntity(tContractorPreparation);
        }
    }


    /* Private Methods */
    /**
     * 列表查询条件及查询参数
     */
    private QueryWrapper<TContractorAllow> createQuery(TContractorAllowParam queryParam){
        QueryWrapper<TContractorAllow> queryWrapper=new QueryWrapper<>();
        if(StringHelper.isNotEmpty(queryParam.getContractorId())){
            queryWrapper.eq(TContractorAllow.CONTRACTOR_ID,queryParam.getContractorId());
        }
        if(StringHelper.isNotEmpty(queryParam.getProjId())){
            queryWrapper.eq(TContractorAllow.PROJ_ID,queryParam.getProjId());
        }
        if(StringHelper.isNotEmpty(queryParam.getProcessId())){
            queryWrapper.eq(TContractorAllow.PROCESS_ID,queryParam.getProcessId());
        }
        if(StringHelper.isNotEmpty(queryParam.getProcessStatus())){
            queryWrapper.eq(TContractorAllow.PROCESS_STATUS,queryParam.getProcessStatus());
        }
        if(StringHelper.isNotEmpty(queryParam.getBizId())){
            queryWrapper.eq(TContractorAllow.BIZ_ID,queryParam.getBizId());
        }
        if(StringHelper.isNotEmpty(queryParam.getWorkDescription())){
            queryWrapper.eq(TContractorAllow.WORK_DESCRIPTION,queryParam.getWorkDescription());
        }
        if(StringHelper.isNotEmpty(queryParam.getWorkLocation())){
            queryWrapper.eq(TContractorAllow.WORK_LOCATION,queryParam.getWorkLocation());
        }
        if(StringHelper.isNotEmpty(queryParam.getWorkPlan())){
            queryWrapper.eq(TContractorAllow.WORK_PLAN,queryParam.getWorkPlan());
        }
        if(StringHelper.isNotEmpty(queryParam.getEmergencyPlan())){
            queryWrapper.eq(TContractorAllow.EMERGENCY_PLAN,queryParam.getEmergencyPlan());
        }
        if(StringHelper.isNotEmpty(queryParam.getHealthSafetyNotice())){
            queryWrapper.eq(TContractorAllow.HEALTH_SAFETY_NOTICE,queryParam.getHealthSafetyNotice());
        }
        if(StringHelper.isNotEmpty(queryParam.getSafetyCommitment())){
            queryWrapper.eq(TContractorAllow.SAFETY_COMMITMENT,queryParam.getSafetyCommitment());
        }
        if (StringHelper.isNotEmpty(queryParam.getStatus())) {
            queryWrapper.eq(TContractorAllow.STATUS, queryParam.getStatus());
        } else {
            queryWrapper.ne(TContractorAllow.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(TContractorAllow.UPDATE_DATE);
        }
        return queryWrapper;
    }



    /**
     * 删除准入管理数据并回退基本信息状态
     */
    @Transactional
    @Override
    public void deleteAdmissionAndRollback(String allowId) throws BusinessException {
        // 1. 查询准入管理数据
        TContractorAllow contractorAllow = this.getById(allowId);
        if (contractorAllow == null) {
            throw new BusinessException("准入管理数据不存在");
        }

        String bizId = contractorAllow.getBizId(); // 对应的基本信息ID

        // 2. 回退基本信息状态为"待提交"
        rollbackBasicInfoStatus(bizId);

        // 3. 删除准入管理数据
        this.removeById(allowId);

        contractorAccessLogDao.updateStatus(allowId);
        contractorAccessLogApprovalDao.updateStatus(allowId);

        log.info("准入管理数据删除成功，业务ID: {}, 删除原因: {}", bizId);
    }

    /**
     * 批量删除准入管理数据
     */
    public void batchDeleteAdmission(List<String> allowIds, String deleteReason, String operator) {
        if (CollectionUtils.isEmpty(allowIds)) {
            return;
        }

        for (String allowId : allowIds) {
            try {
                deleteAdmissionAndRollback(allowId);
            } catch (Exception e) {
                log.error("删除准入管理数据失败，ID: {}", allowId, e);
                // 继续处理其他数据，不中断批量操作
            }
        }
    }

    /**
     * 根据基本信息ID删除所有相关的准入管理数据
     */
    public void deleteAdmissionByBizId(String bizId) throws BusinessException {
        // 查询所有相关的准入管理数据
        List<TContractorAllow> allowList = this.list(
                new LambdaQueryWrapper<TContractorAllow>()
                        .eq(TContractorAllow::getBizId, bizId)
        );

        if (CollectionUtils.isEmpty(allowList)) {
            log.warn("未找到业务ID: {} 对应的准入管理数据", bizId);
            return;
        }

        // 回退基本信息状态
        rollbackBasicInfoStatus(bizId);

        // 批量删除准入管理数据
        List<String> allowIds = allowList.stream()
                .map(TContractorAllow::getId)
                .collect(Collectors.toList());

        this.removeByIds(allowIds);

        log.info("根据业务ID删除准入管理数据成功，业务ID: {}, 删除记录数: {}", bizId, allowList.size());
    }

    /**
     * 回退基本信息状态为"待提交"
     */
    private void rollbackBasicInfoStatus(String bizId) throws BusinessException {
        TContractorBasicInfo basicInfo = tContractorBasicInfoService.getById(bizId);
        if (basicInfo == null) {
            throw new BusinessException("基本信息数据不存在，ID: " + bizId);
        }

        // 更新基本信息状态为"待提交"（假设待提交的状态值为0）
        basicInfo.setProcessStatus(ContractorProcessStatus.PENDING_SUBMISSION.getValue()); // 根据您的状态枚举调整

        tContractorBasicInfoService.updateById(basicInfo);

        log.info("基本信息状态已回退为待提交，业务ID: {}", bizId);
    }



}
