package org.jeecg.modules.workOrder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.jdbc.Work;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.api.model.CabinetModel;
import org.jeecg.modules.api.service.CabinetApiService;
import org.jeecg.modules.api.service.CabinetConnectService;
import org.jeecg.modules.apply.entity.ApplyRecord;
import org.jeecg.modules.apply.mapper.ApplyRecordMapper;
import org.jeecg.modules.cabinet.entity.Cabinet;
import org.jeecg.modules.cabinet.mapper.CabinetMapper;
import org.jeecg.modules.device.entity.BuDevice;
import org.jeecg.modules.device.mapper.BuDeviceMapper;
import org.jeecg.modules.plan.entity.Plan;
import org.jeecg.modules.plan.mapper.PlanMapper;
import org.jeecg.modules.regular.entity.Regular;
import org.jeecg.modules.regular.entity.RegularDetail;
import org.jeecg.modules.regular.entity.RegularInput;
import org.jeecg.modules.regular.mapper.RegularDetailMapper;
import org.jeecg.modules.regular.mapper.RegularInputMapper;
import org.jeecg.modules.regular.mapper.RegularMapper;
import org.jeecg.modules.workOrder.entity.OperationRecord;
import org.jeecg.modules.workOrder.entity.WorkOrder;
import org.jeecg.modules.workOrder.entity.WorkRecord;
import org.jeecg.modules.workOrder.mapper.OperationRecordMapper;
import org.jeecg.modules.workOrder.mapper.WorkOrderMapper;
import org.jeecg.modules.workOrder.mapper.WorkRecordMapper;
import org.jeecg.modules.workOrder.model.WorkOrderDetailModel;
import org.jeecg.modules.workOrder.model.WorkOrderDto;
import org.jeecg.modules.workOrder.service.IWorkOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Description: 任务工单
 * @Author: jeecg-boot
 * @Date: 2025-02-10
 * @Version: V1.0
 */
@Service
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements IWorkOrderService {

    @Autowired
    private PlanMapper planMapper;
    @Autowired
    private OperationRecordMapper operationRecordMapper;
    @Autowired
    private RegularMapper regularMapper;
    @Autowired
    private RegularDetailMapper regularDetailMapper;
    @Autowired
    private ApplyRecordMapper applyRecordMapper;
    @Autowired
    private BuDeviceMapper deviceMapper;
    @Autowired
    private CabinetApiService cabinetApi;
    @Autowired
    private CabinetConnectService cabinetConnectService;
    @Autowired
    private RegularInputMapper regularInputMapper;
    @Autowired
    private WorkRecordMapper workRecordMapper;
    @Autowired
    private CabinetMapper cabinetMapper;
    @Value("${spring.active}")
    private String activeProfile;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addWorkOrder(WorkOrder workOrder) throws Exception {
        if(baseMapper.selectCount(new LambdaQueryWrapper<WorkOrder>().eq(WorkOrder::getPlanId, workOrder.getPlanId()).eq(WorkOrder::getDeleteFlag,0))>0) {
            throw new Exception("创建工单失败：该计划已存在工单");
        }
        // 如果是直接创建的任务工单，不存在可依赖的计划时，创建一个临时计划
        if (StringUtils.isBlank(workOrder.getPlanId())) {
            LocalDate localDate = LocalDate.now(ZoneId.of("Asia/Shanghai"));
            // 查询今天是否已存在计划。目前创建工单两个入口：根据计划创建；直接创建，直接创建时必定为当日工单
            Plan todayPlan = planMapper.selectOne(new LambdaQueryWrapper<Plan>().eq(Plan::getDeviceId,workOrder.getDeviceId())
                    .eq(Plan::getRapairRange,workOrder.getModelType()).eq(Plan::getCalDay,localDate));
            if(todayPlan ==null) {
                Plan plan = new Plan(workOrder.getDeviceId(), workOrder.getModelType(),
                        localDate,// 检修作业日期
                        localDate.getDayOfWeek().getValue(),// 获取数字形式(1-7，周一是1，周日是7)
                        1);
                if (planMapper.insert(plan) <= 0)
                    throw new Exception("创建工单失败：临时计划创建失败");
                workOrder.setPlanId(plan.getId());
            }
            else {
                workOrder.setPlanId(todayPlan.getId());
            }
        }
        BuDevice device = deviceMapper.selectById(workOrder.getDeviceId());
        if(device == null){
            throw new Exception("创建工单失败：设备不存在");
        }
        //生成工单详情
        Regular regular = regularMapper.selectOne(new LambdaQueryWrapper<Regular>()
                .eq(Regular::getDeviceTypeId, device.getDeviceTypeId())
                .eq(Regular::getRapairRange, workOrder.getModelType()));
        if (regular == null) {
            throw new Exception("创建工单失败：设备"+workOrder.getDeviceId()+"无该修程"+workOrder.getModelType());
        }
        workOrder.setRegularId(regular.getId());
        if (this.baseMapper.insert(workOrder) > 0) {
            // 根据检修规程详情创建工单操作记录
            List<RegularDetail> details = regularDetailMapper.selectList(new LambdaQueryWrapper<RegularDetail>()
                    .eq(RegularDetail::getRegularId, regular.getId()));
            List<OperationRecord> records = details.stream().map(item -> {
                OperationRecord record = new OperationRecord();
                record.setWorkOrder(workOrder.getId());
                record.setStatus(0);
                record.setDeliveryStatus(0);
                record.setItemId(item.getId());
                // 根据检修规程明细要求，给工单明细的互检和专检人做初始化赋值
                record.setMutualInspection(item.getMutualInspection()==0?"——":null);
                record.setSpecialInspection(item.getPersonalizedInspection()==0?"——":null);
                return record;
            }).toList();
            AtomicInteger i = new AtomicInteger();
            records.forEach(item -> {
                i.addAndGet(operationRecordMapper.insert(item));
            });
            return i.get() == records.size();
        } else {
            throw new Exception("创建工单失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean stopWorkOrder(WorkOrder workOrder) {
        if (workOrder.getId() == null) {
            return false;
        }

        WorkOrder workOrder1 = baseMapper.selectById(workOrder.getId());
        if (workOrder1 == null) {
            return false;
        }

        BeanUtil.copyProperties(workOrder1,workOrder);
        Date startTime = workOrder.getStartTime();
        if (startTime == null) {
            return false;
        }

        long now = System.currentTimeMillis();
        long duration = now - startTime.getTime();

        // 防止出现负数（系统时间异常等情况）
        if (duration < 0) {
            duration = 0;
        }

        workOrder.setWorkDuration(duration);

        return baseMapper.updateById(workOrder) > 0;
    }

    @Override
    public WorkOrderDto getDetailbyId(String workOrderId, boolean queryAll) {
        WorkOrder workOrder = this.getById(workOrderId);
        WorkOrderDto workOrderDto = BeanUtil.copyProperties(workOrder, WorkOrderDto.class);
        // 获取工单详情
        List<WorkOrderDetailModel> detailModels = operationRecordMapper.findByWorkOrderId(workOrderId);
        detailModels.forEach(item -> {
            if(item.getMeasure().equals("1")){
                //todo 查询测量项
                StringBuilder result = new StringBuilder();
                String falg ="";
                RegularDetail detail = regularDetailMapper.selectById(item.getItemId());
                if(detail != null){
                    List<RegularInput> inputs = regularInputMapper.selectList(new LambdaQueryWrapper<RegularInput>().eq(RegularInput::getDetailId, detail.getId()).isNotNull(RegularInput::getToolId));
                    for(RegularInput input : inputs){
                        WorkRecord record = workRecordMapper.selectOne(new LambdaQueryWrapper<WorkRecord>().eq(WorkRecord::getRegularInputId, input.getId()).eq(WorkRecord::getWorkOrder, workOrderId)
                                .orderByDesc(WorkRecord::getCollectNum).last("limit 1"));
                        if(record!=null){
//                            List<Double> values = records.parallelStream().map(record -> Double.parseDouble(record.getNumericValue())).toList();
//                            if(values.size() == 0){
//                                return;
//                            }
//                            Double avg = values.stream().mapToDouble(a -> a).average().getAsDouble();
                            String temp = input.getDataPot() + ":" + record.getNumericValue() + record.getUnit() + "\r\n";
                            result.append(temp);
                            falg =  record.getNumericValue();
                            if (falg == null || falg.isEmpty()) {
                                item.setSelfInspection("未测量");
                            }else{
                                // 是否多次采集
                                item.setCollectNum(record.getCollectNum());
                                item.setRegularInputId(record.getRegularInputId());
                                double value = Double.parseDouble(record.getNumericValue());
                                Double min = input.getMinValue();
                                Double max = input.getMaxValue();
                                item.setResultOverGauge((min == null || value >= min) && (max == null || value <= max));
                            }

                        }
                    }
                }
                if(StringUtils.isNotEmpty(falg)){
                    item.setCheckResult(result.toString());
                }
            }
        });
        if(queryAll){
            workOrderDto.setWorkOrderDetailModels(detailModels);
        }else{
            workOrderDto.setWorkOrderDetailModels(detailModels.stream()
                    .filter(item -> (StringUtils.isBlank(item.getSelfInspection())// 当自检人为空时，视为未完成
                            ||(StringUtils.isBlank(item.getMutualInspection()) && item.getIsMutual()==2)//当需要互检且互检人为空时，视为未完成
                            ||(StringUtils.isBlank(item.getSpecialInspection()) && item.getIsPersonalized()==1)))//当需要专检且专检人为空时，视为未完成
                    .collect(Collectors.toList()));
        }
        // 获取规程信息
        workOrderDto.setRegular(regularMapper.selectById(workOrder.getRegularId()));

        return workOrderDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelWorkOrder(WorkOrder workOrder) {
        //将物料和工具申请撤销
        applyRecordMapper.update(null,new LambdaUpdateWrapper<ApplyRecord>().set(ApplyRecord::getStatus,-1).eq(ApplyRecord::getWorkOrder,workOrder.getId()));

        // 工具领用工单下发
        if("prod".equals(activeProfile)){
            CabinetModel cabinetModel = new CabinetModel();
            cabinetModel.setOrderId(workOrder.getId());
            List<CabinetModel> datas = new ArrayList<>();
            datas.add(cabinetModel);
            // 查询可用的柜子
            List<Cabinet> cabinets = cabinetMapper.selectList(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getIsAvailable, 1));
            for (Cabinet cabinet: cabinets) {
                // 通过接口撤销工单
                cabinetApi.sendTMessages(cabinet,datas,"receiveCancelOrder");
            }

//            cabinetConnectService.sendCancelWorkOrder(cabinetModel);
        }

        workOrder.setMaterialStatus(0);
        workOrder.setToolsStatus(0);
        // 更新工单状态
        return this.baseMapper.updateById(workOrder) > 0;
    }
}
