package cn.iocoder.yudao.module.pms.job;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.pms.constant.PmsConstants;
import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectPlanDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillOrderDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotoperationplan.IotOperationPlanDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotoperationplandev.IotOperationPlanDevDO;
import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillOrderMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotoperationplan.IotOperationPlanMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotoperationplandev.IotOperationPlanDevMapper;
import cn.iocoder.yudao.module.pms.message.PmsMessage;
import cn.iocoder.yudao.module.pms.service.iotopeationfill.IotOpeationFillService;
import cn.iocoder.yudao.module.pms.service.iotrhdailyreport.IotRhDailyReportService;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;

/**
 * @author yc
 * @version 1.0
 * @className IotOperationFillTask
 * @date 2025/5/11 10:26
 * @description
 */
@Component
@Slf4j
public class IotOperationPlanJob implements JobHandler {



    @Autowired
    private IotOpeationFillMapper iotOpeationFillMapper;
    @Autowired
    private IotOpeationFillOrderMapper iotOpeationFillOrderMapper;
    @Resource
    private PmsMessage pmsMessage;
    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
    @Resource
    private IotOperationPlanMapper planMapper;
    @Resource
    private IotOperationPlanDevMapper planDevMapper;
    @Resource
    private DeptService deptService;
    @Resource
    private IotOpeationFillService opeationFillService;
    @Resource
    private IotRhDailyReportService iotRhDailyReportService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;;
    /**
     * 1、查询开启状态运行计划
     * 2、根据计划获取设备
     * 3、根据设备ID查询设备责任人表，获取user_id
     * 4、根据user_id生成工单主表数据
     * 5、生成设备子表数据
     * 6、根据计划周期确认工单生成时间
     */

    @Override
    public String execute(String param) throws Exception {
        TenantContextHolder.setIgnore(true);
        //1、查询开启，非删除状态运行计划
        List<IotOperationPlanDO> planList = planMapper.getPlanList();
        if(planList.size()>0){
            for (IotOperationPlanDO planDO:planList) {
                if (planDO.getLastCreateTime()==null&& Objects.nonNull(planDO.getBeginCreateTime())) {
                    //当首次执行时间大于当前时间
                    if (planDO.getBeginCreateTime().isBefore(LocalDateTime.now())) {
                        Date date = Date.from(
                                planDO.getBeginCreateTime().atZone(ZoneId.systemDefault()) // 使用系统默认时区
                                        .toInstant()                    // 转为 Instant（时间戳）
                        );
                        extractedOrder(planDO, date);
                    }
                } else {
                    Date lastdate = Date.from(
                            planDO.getLastCreateTime().atZone(ZoneId.systemDefault()) // 使用系统默认时区
                                    .toInstant()                    // 转为 Instant（时间戳）
                    );
                    extractedOrder(planDO, lastdate);
                }
            }
        }
        return "创建成功";
    }

    private void extractedOrder(IotOperationPlanDO planDO, Date date) {
        Set<Long> idList = new HashSet<>();
        if(Objects.nonNull(planDO.getDeptId())){
            idList =  deptService.getChildDeptIdListFromCache(planDO.getDeptId());
            idList.add(planDO.getDeptId());
        }
        //2、根据计划获取设备ID
        List<IotDeviceRespVO> devList = iotOpeationFillMapper.getFillDevices2(idList);
        if(devList.size()>0){
            List<Long> devIdList= devList.stream().map(IotDeviceRespVO::getId).collect(Collectors.toList());
            //3、根据设备ID生成主表数据
            List<IotOpeationFillOrderDO> orderList = new ArrayList<>();
            List<IotOpeationFillDO> pdList = iotOpeationFillMapper.pdList(devIdList);
            for (IotOpeationFillDO pd:pdList) {
                IotOpeationFillOrderDO fillDO = new IotOpeationFillOrderDO();
                fillDO.setOrderName(pd.getOrgName()+"/"+ LocalDate.now()+"运行记录填报");
                fillDO.setDeptId(pd.getDeptId());
                fillDO.setOrderStatus(0);
                fillDO.setCreateTime(LocalDateTime.now());
                fillDO.setUserName(pd.getUserName());
                fillDO.setUserId(pd.getUserId());
                fillDO.setMobile(pd.getMobile());
                orderList.add(fillDO);
            }
            deal(planDO, date,devIdList,orderList);
        }
    }


    private void deal(IotOperationPlanDO plan, Date date,List<Long> devIdList, List<IotOpeationFillOrderDO> orderList) {
        Date date1 = new Date();
        if ("hour".equals(plan.getPlanUnit())){
            DateTime dateTime = DateUtil.offsetHour(date, Integer.parseInt(StringUtils.substringBeforeLast(String.valueOf(plan.getPlanCycle()),".")));
            if (date1.compareTo(dateTime) > 0){
                extracted(devIdList, orderList,plan);
            }
        } else if ("day".equals(plan.getPlanUnit())){
            DateTime dateTime = DateUtil.offsetDay(date, Integer.parseInt(StringUtils.substringBeforeLast(String.valueOf(plan.getPlanCycle()),".")));
            if (date1.compareTo(dateTime) > 0){
                extracted(devIdList, orderList,plan);
            }
        } else if ("month".equals(plan.getPlanUnit())){
            DateTime dateTime = DateUtil.offsetMonth(date, Integer.parseInt(StringUtils.substringBeforeLast(String.valueOf(plan.getPlanCycle()),".")));
            if (date1.compareTo(dateTime) > 0){
                extracted(devIdList, orderList,plan);
            }
        }
    }



    private void extracted(List<Long> devIdList, List<IotOpeationFillOrderDO> orderList,IotOperationPlanDO plan) {




        //瑞鹰日报计划为12小时执行一次
        //判断计划周期是否为小时，如果是，则保存上次执行时间为当前时间最近的整点
        if ("hour".equals(plan.getPlanUnit())) {
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            // 获取当前分钟数
            int minute = now.getMinute();

            LocalDateTime localDateTime;
            if (minute <= 30) {
                // 如果分钟数小于等于30，取当前小时的整点
                localDateTime = now.truncatedTo(ChronoUnit.HOURS);
            } else {
                // 如果分钟数大于30，取下一小时的整点
                localDateTime = now.truncatedTo(ChronoUnit.HOURS).plusHours(1);
            }
            plan.setLastCreateTime(localDateTime);
        } else {
            LocalDateTime localDateTime = DateUtils.contactTime(plan.getBeginCreateTime());
            plan.setLastCreateTime(localDateTime);
        }
        planMapper.updateById(plan);

        //判断是否为瑞恒特殊计划
        if(plan.getId()==153L){
            unNormalTeamInPlan(plan);
        }else{
            //4、根据设备ID生成子表数据
            List<IotOpeationFillDO> deviceList = iotOpeationFillMapper.getFillDevices(devIdList);
            List<Integer> idList = deviceList.stream().map(IotOpeationFillDO::getUserId).collect(Collectors.toList());
            List<IotOpeationFillOrderDO> orderList1 = orderList.stream()
                    .filter(obj -> idList.contains(obj.getUserId()))
                    .collect(Collectors.toList());



            Set<Long> ryIdList = new HashSet<>();
            if(plan.getIsReport()==1){//日报
                //瑞鹰
                ryIdList =  deptService.getChildDeptIdListFromCache(158L);
                ryIdList.add(158L);

                List<IotOpeationFillOrderDO> zxjOrderList = new ArrayList<>();

                for (IotOpeationFillOrderDO orderDO:orderList1) {
                    IotDeviceRunLogDO runLogDO = new IotDeviceRunLogDO();
                    runLogDO.setDeptId(orderDO.getDeptId());
                    //获取队伍类型
                    IotDeviceRunLogDO teamType = iotOpeationFillMapper.getTeamType(runLogDO);

                    //如果是钻井队伍，则日报工单责任人更新为技术员
                    //修井队伍不变
                    if(teamType!=null&&teamType.getPointCode().equals("zj")){
                        //获取技术员信息
                        AdminUserDO userInfo = iotOpeationFillMapper.getUserInfo(runLogDO);
                        if(userInfo!=null){
                            orderDO.setUserName(userInfo.getUsername());
                            orderDO.setUserId(new BigDecimal(userInfo.getId()).intValue());
                            orderDO.setMobile(userInfo.getMobile());
                        }
                        zxjOrderList.add(orderDO);
                    }else if(teamType!=null&&teamType.getPointCode().equals("xj")){
                        zxjOrderList.add(orderDO);
                    }
                }


                // 按dept_id去重，保留第一个出现的元素
                List<IotOpeationFillOrderDO> distinctOrderList = zxjOrderList.stream()
                        .collect(Collectors.toMap(
                                IotOpeationFillOrderDO::getDeptId,
                                order -> {
                                    order.setId(null); // 关键：重置ID，避免与已有数据冲突
                                    return order;
                                },
                                (existing, replacement) -> existing
                        ))
                        .values()
                        .stream()
                        .collect(Collectors.toList());
                //插入工单主表
                iotOpeationFillOrderMapper.insertBatch(distinctOrderList);
                //发送钉钉消息
                sendDingMessage(distinctOrderList);

                boolean ryContain = ryIdList.contains(plan.getDeptId());
                //瑞鹰日报插入
                ryReportInsert(plan,distinctOrderList,ryContain);

            }else{

                //插入工单主表
                iotOpeationFillOrderMapper.insertBatch(orderList1);
                //瑞都
                ryIdList =  deptService.getChildDeptIdListFromCache(163L);
                ryIdList.add(163L);
                Set<Long> rhIdList = new HashSet<>();
                rhIdList =  deptService.getChildDeptIdListFromCache(157L);//瑞恒
                rhIdList.add(157L);
                boolean exist = ryIdList.contains(plan.getDeptId());
                if(!exist){
                    boolean rhContain = rhIdList.contains(plan.getDeptId());
                    //瑞恒日报插入
                    rhReportInsert(plan, orderList1, rhContain);
                }
                //发送钉钉消息
                sendDingMessage(orderList1);
                //正常工单设备
                for (IotOpeationFillDO device:deviceList) {
                    for (IotOpeationFillOrderDO order:orderList1) {
                        if(device.getUserId().intValue()==order.getUserId().intValue()){
                            device.setOrderId(order.getId());
                        }
                    }
                }
                //插入子表
                for (IotOpeationFillDO re:deviceList) {
                    re.setDeviceId(re.getId());
                }
                iotOpeationFillMapper.insertFill(deviceList);
            }
        }
    }

    private void sendDingMessage(List<IotOpeationFillOrderDO> orderList1) {
        //发送钉钉通知
        pmsThreadPoolTaskExecutor.execute(()->{
            try{
                for (IotOpeationFillOrderDO order: orderList1) {
                    pmsMessage.sendMessage(order.getId(), order.getOrderName(), PmsConstants.GENERATE_OPERATION, (long)order.getUserId(), order.getMobile());
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        });
    }



    private void unNormalTeamInPlan(IotOperationPlanDO planDO) {


        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(planDO.getDeptId());
        DeptListReqVO reqVO = new DeptListReqVO();
        reqVO.setDeptIds(allRhChildDeptIds);

        List<DeptDO> depts = deptService.getDeptList(reqVO);

        //筛选出所有小队
        List<DeptDO> teams = depts.stream().filter(e->e.getType().equals("3")).collect(Collectors.toList());


        //查询增压机状态为非施工的小队
        List<IotDeviceDO> teamStatusL = iotOpeationFillMapper.selectDevStatusBatch(teams);

        System.out.println("-------开始打印RH非正常工单-----");
        teams.forEach(System.out::println);
        System.out.println("-------结束打印RH非正常工单-----");

        if(teamStatusL.size()>0){
            for (IotDeviceDO vir:teamStatusL) {
                IotRhDailyReportSaveReqVO saveReqVO = new IotRhDailyReportSaveReqVO();
                //查询队伍增压机状态

                IotDeviceRunLogDO cx = new IotDeviceRunLogDO();
                cx.setDeptId(vir.getDeptId());
                IotDeviceRunLogDO result = iotOpeationFillMapper.getUserId(cx);
                //不为空则为日报赋值
                if(vir.getDeviceStatus()!=null){
                    saveReqVO.setConstructionStatus(vir.getDeviceStatus());
                }
                //当日注气量
                saveReqVO.setDailyGasInjection(BigDecimal.valueOf(0.00));
                //当日注水量
                saveReqVO.setDailyWaterInjection(BigDecimal.valueOf(0.00));
                //当日注气时间
                saveReqVO.setDailyInjectGasTime(BigDecimal.valueOf(0.00));
                //当日注水时间
                saveReqVO.setDailyInjectWaterTime(BigDecimal.valueOf(0.00));
                //当日用电量
                saveReqVO.setDailyPowerUsage(BigDecimal.valueOf(0.00));
                //非生产时间
                saveReqVO.setNonProductionTime(BigDecimal.valueOf(0.00));
                saveReqVO.setDeptId(vir.getDeptId());
                saveReqVO.setFillOrderCreateTime(LocalDateTime.now());
                if(result!=null){
                    saveReqVO.setCreator(String.valueOf(result.getDeviceId()));
                }
                iotRhDailyReportService.createIotRhDailyReport(saveReqVO);
            }
        }

    }




    private void ryReportInsert(IotOperationPlanDO plan, List<IotOpeationFillOrderDO> orderList1, boolean ryContain) {
        if(ryContain){
            //创建日报设备
            List <IotOpeationFillDO> devList = opeationFillService.reportMethod(orderList1);
            //插入日报设备
            iotOpeationFillMapper.insertFill(devList);
        }
    }

    private void rhReportInsert(IotOperationPlanDO plan, List<IotOpeationFillOrderDO> orderList1, boolean rhContain) {
        if(rhContain){

            //创建瑞恒日报虚拟设备
            List <IotOpeationFillDO> devList = opeationFillService.reportMethod(orderList1);
            //插入日报设备
            iotOpeationFillMapper.insertFill(devList);

            /*//2、瑞恒无指定队伍全部队伍插入日报设备
            //筛选正常工单部门id
            List<Long> deptIdList = orderList1.stream().map(IotOpeationFillOrderDO::getDeptId).collect(Collectors.toList());
            //查询瑞恒所有责任人数据
            Set<Long> pIdList = new HashSet<>();
            pIdList =  deptService.getChildDeptIdListFromCache(plan.getDeptId());
            pIdList.add(plan.getDeptId());
            List<IotOpeationFillDO> rhPdList = iotOpeationFillMapper.pdListRh(pIdList);
            //筛选与正常工单不同部门的责任人数据
            List<IotOpeationFillDO> verRPList = rhPdList.stream().filter(e->!deptIdList.contains(e.getDeptId())).collect(Collectors.toList());
            //筛选小队责任人数据
            // 使用迭代器遍历集合
            Iterator<IotOpeationFillDO> iterator = verRPList.iterator();
            while (iterator.hasNext()) {
                IotOpeationFillDO rp = iterator.next();
                IotOpeationFillOrderDO rpOrder = new IotOpeationFillOrderDO();
                rpOrder.setDeptId(rp.getDeptId());
                List<IotOpeationFillOrderDO> childList = iotOpeationFillMapper.childList(rpOrder);

                // 当childList有元素时，通过迭代器删除当前元素
                if (childList.size() > 0) {
                    iterator.remove(); // 使用迭代器的remove方法安全删除
                }
            }
            //创建虚拟工单
            if(verRPList.size()>0){
                for (IotOpeationFillDO vir:verRPList) {
                    IotRhDailyReportSaveReqVO saveReqVO = new IotRhDailyReportSaveReqVO();
                    //查询队伍增压机状态
                    IotDeviceDO virDev = new IotDeviceDO();
                    virDev.setDeptId(vir.getDeptId());
                    IotDeviceDO devStatus = iotOpeationFillMapper.devStatus(virDev);
                    //不为空则为日报赋值
                    if(devStatus!=null){
                        saveReqVO.setConstructionStatus(devStatus.getDeviceStatus());
                    }
                    //当日注气量
                    saveReqVO.setDailyGasInjection(BigDecimal.valueOf(0.00));
                    //当日注水量
                    saveReqVO.setDailyWaterInjection(BigDecimal.valueOf(0.00));
                    //当日注气时间
                    saveReqVO.setDailyInjectGasTime(BigDecimal.valueOf(0.00));
                    //当日注水时间
                    saveReqVO.setDailyInjectWaterTime(BigDecimal.valueOf(0.00));
                    //当日用电量
                    saveReqVO.setDailyPowerUsage(BigDecimal.valueOf(0.00));
                    //非生产时间
                    saveReqVO.setNonProductionTime(BigDecimal.valueOf(0.00));
                    saveReqVO.setDeptId(vir.getDeptId());
                    saveReqVO.setFillOrderCreateTime(LocalDateTime.now());
                    saveReqVO.setCreator(String.valueOf(vir.getUserId()));
                    iotRhDailyReportService.createIotRhDailyReport(saveReqVO);
                }
            }*/
        }
    }

}
