package org.nl.hand.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.agv.server.NDCAgvService;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.instruction.domain.Instruction;
import org.nl.acs.instruction.domain.InstructionMybatis;
import org.nl.acs.instruction.service.InstructionService;
import org.nl.acs.opc.DeviceAppService;
import org.nl.acs.task.domain.Task;
import org.nl.acs.task.service.TaskService;
import org.nl.acs.task.service.dto.TaskDto;
import org.nl.common.base.CommonFinalParam;
import org.nl.common.enums.TaskStatusEnum;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.CodeUtil;
import org.nl.hand.dto.HeadDto;
import org.nl.hand.dto.HeadInstDto;
import org.nl.hand.dto.HeadTaskDto;
import org.nl.hand.dto.TaskIdAndStatusDTO;
import org.nl.hand.service.HandService;
import org.nl.system.service.dict.ISysDictService;
import org.nl.system.service.dict.dao.Dict;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @Author : TuQiang
 * @create 2024/4/2 10:20
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class HandServiceImpl implements HandService  {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private TaskService taskserver;
    @Autowired
    private ISysDictService dictService;
    @Autowired
    private InstructionService instructionService;
    @Autowired
    NDCAgvService ndcAgvService;
    @Autowired
    DeviceAppService deviceAppService;



    @Override
    public Map<String, Object> queryPointByArea(String region_code) {
        JSONArray data = new JSONArray();
        if (StrUtil.isEmpty(region_code)) {
            throw new BadRequestException("区域编码不能为空！");
        }

        //根据区域编码查询所有设备
        List<Device> list = deviceService.lambdaQuery()
                .eq(Device::getRegion, region_code)
                .list();
        if (CollectionUtil.isEmpty(list)) {
            throw new BadRequestException("未查到该区域的设备！");
        }
        for (int i = 0; i < list.size(); i++) {
            JSONObject jo = new JSONObject();
            Device device = list.get(i);
            String device_id = device.getDevice_id();
            String device_code = device.getDevice_code();
            String device_name = device.getDevice_name();
            BigDecimal seq_num = device.getSeq_num();
            jo.put("device_id", device_id);
            jo.put("device_code", device_code);
            jo.put("device_name", device_name);
            jo.put("seq_num", seq_num);
            data.add(jo);
        }
        JSONObject resultJson = new JSONObject();
        resultJson.put("message", "操作成功");
        resultJson.put("data", data);
        return resultJson;
    }

    @Override
    public Map<String, Object> callTask(HeadDto dto) {
        JSONArray errArr = new JSONArray();
        String start_device_code = dto.getStart_device_code();
        String next_device_code = dto.getNext_device_code();
        String task_type = dto.getTask_type();

        if (StrUtil.isEmpty(start_device_code)) {
            throw new BadRequestException("起点不能为空");
        }
        if (StrUtil.isEmpty(next_device_code)) {
            throw new BadRequestException("终点不能为空");
        }
        if (StrUtil.isEmpty(task_type)) {
            throw new BadRequestException("任务类型不能为空");
        }

        String start_device_code2 = "";
        String next_device_code2 = "";
        JSONObject jo = new JSONObject();
        if (StrUtil.equals(task_type, CommonFinalParam.TYPE_ONE)) {
            String s = start_device_code.substring(start_device_code.length() - 1);
            if (StrUtil.equals("K", s)) {
                start_device_code2 = next_device_code.substring(0, next_device_code.length() - 1) + "M";
                next_device_code2 = start_device_code.substring(0, start_device_code.length() - 1) + "M";
                jo.put("start_device_code2", start_device_code2);
                jo.put("next_device_code2", next_device_code2);
                jo.put("start_point_code2", start_device_code2);
                jo.put("next_point_code2", next_device_code2);
            }else{
                throw new BadRequestException("起点设备名称不符");
            }
        } else if (StrUtil.equals(task_type, CommonFinalParam.TYPE_TWO)) {
            String s = start_device_code.substring(start_device_code.length() - 1);
            String n = next_device_code.substring(next_device_code.length() - 1);
            if (StrUtil.equals("M", s) && StrUtil.equals("M", n)) {
                start_device_code2 = next_device_code.substring(0, next_device_code.length() - 1) + "K";
                next_device_code2 = start_device_code.substring(0, start_device_code.length() - 1) + "K";
                jo.put("start_device_code2", start_device_code2);
                jo.put("next_device_code2", next_device_code2);
                jo.put("start_point_code2", start_device_code2);
                jo.put("next_point_code2", next_device_code2);
            }else if(StrUtil.equals("S", n) && StrUtil.equals("M", s)){
                start_device_code2 = next_device_code.substring(0, next_device_code.length() - 1) + "X";
                next_device_code2 = start_device_code.substring(0, start_device_code.length() - 1) + "K";
                jo.put("start_device_code2", start_device_code2);
                jo.put("next_device_code2", next_device_code2);
                jo.put("start_point_code2", start_device_code2);
                jo.put("next_point_code2", next_device_code2);
            }else{
                throw new BadRequestException("起点设备名称不符");
            }
        }
        Device startDevice =  deviceAppService.findDeviceByCode(start_device_code2);
        Device nextDevice = deviceAppService.findDeviceByCode(next_device_code2);
        if(StrUtil.isAllNotEmpty(start_device_code2,next_device_code2) && ObjectUtil.isAllEmpty(startDevice,nextDevice)){
            throw new BadRequestException("起点终点设备不存在");
        }
        jo.put("start_device_code", start_device_code);
        jo.put("next_device_code", next_device_code);
        jo.put("start_point_code", start_device_code);
        jo.put("next_point_code", next_device_code);
        jo.put("task_type", task_type);
        jo.put("agv_system_type", "2");
        jo.put("priority", "1");

        TaskDto task_dto = jo.toJavaObject(TaskDto.class);
        try {
            taskserver.create(task_dto);
        } catch (Exception e) {
//                    e.printStackTrace();
            JSONObject json = new JSONObject();
            json.put("message", e.getMessage());
            errArr.add(json);
            throw new RuntimeException(e.getMessage());
        }
        JSONArray data = new JSONArray();
        JSONObject resultJson = new JSONObject();
        if (ObjectUtil.isEmpty(errArr)) {
            resultJson.put("message", "操作成功");
            resultJson.put("data", data);
        } else {
            resultJson.put("message", "操作失败");
            resultJson.put("data", data);
        }
        return resultJson;
    }

    @Override
    public Map<String, Object> queryArea() {
        JSONArray data = new JSONArray();
        List<Dict> list = dictService.lambdaQuery()
                .eq(Dict::getCode, "region_type")
                .list();
        if (CollectionUtil.isEmpty(list)) {
            throw new BadRequestException("未查到该区域的设备！");
        }
        for (int i = 0; i < list.size(); i++) {
            JSONObject jo = new JSONObject();
            Dict dict = list.get(i);
            String region_id = dict.getDict_id();
            String region_code = dict.getValue();
            String region_name = dict.getLabel();
            jo.put("region_id", region_id);
            jo.put("region_code", region_code);
            jo.put("region_name", region_name);
            data.add(jo);
        }
        JSONObject resultJson = new JSONObject();
        resultJson.put("message", "操作成功");
        resultJson.put("data", data);
        return resultJson;
    }

    @Override
    public Map<String, Object> queryInst(HeadInstDto dto) {
        //查询未完成的指令
        String key = dto.getKeyword();
        String start_point = dto.getStart_devicecode();
        String next_point = dto.getNext_devicecode();

        List<InstructionMybatis> list;
        if (StrUtil.isEmpty(key)&&StrUtil.isEmpty(start_point)&&StrUtil.isEmpty(next_point)){
            list = instructionService.lambdaQuery()
                    .le(InstructionMybatis::getInstruction_status,"1")
                    .orderByDesc(InstructionMybatis::getCreate_time)
                    .list();
        }else {
            list = instructionService.lambdaQuery()
                    .like(InstructionMybatis::getStart_device_code, start_point)
                    .like(InstructionMybatis::getNext_device_code, next_point)
                    .le(InstructionMybatis::getInstruction_status, "1")
                    .eq(InstructionMybatis::getInstruction_code, key)
                    .or()
                    .eq(InstructionMybatis::getCarno, key)
                    .or()
                    .eq(InstructionMybatis::getVehicle_code, key)
                    .orderByDesc(InstructionMybatis::getCreate_time)
                    .list();
        }
//        if (CollectionUtil.isEmpty(list)){
//            throw new BadRequestException("没有指令存在！");
//        }
        JSONArray data = new JSONArray();
        for (int i = 0; i < list.size(); i++) {
            JSONObject inst = new JSONObject();
            inst.put("inst_uuid",list.get(i).getInstruction_id());
            inst.put("task_no",list.get(i).getTask_code());
            inst.put("instruction_code",list.get(i).getInstruction_code());
            inst.put("start_devicecode",list.get(i).getStart_device_code());
            inst.put("next_devicecode",list.get(i).getNext_device_code());
            inst.put("inst_status",list.get(i).getInstruction_status());
            inst.put("inst_status_name", TaskStatusEnum.getName(list.get(i).getInstruction_status()));
            inst.put("carrier",list.get(i).getVehicle_code()==null?"":list.get(i).getVehicle_code());
            inst.put("inst_step",list.get(i).getExecute_message()==null?"":list.get(i).getExecute_message());
            inst.put("priority",list.get(i).getPriority());
            inst.put("create_time",list.get(i).getCreate_time());
            inst.put("carno",list.get(i).getCarno()==null?"":list.get(i).getCarno());
            data.add(inst);
        }
        JSONObject resultJson = new JSONObject();
        resultJson.put("message", "操作成功");
        resultJson.put("data", data);
        return resultJson;
    }

    @Override
    public Map<String, Object> instOpt(HeadInstDto dto) throws Exception {
        JSONObject resultJson = new JSONObject();
        JSONArray data = new JSONArray();
        String type = dto.getType();
        String inst_uuid = dto.getInst_uuid();
        InstructionMybatis instruction= instructionService.lambdaQuery()
                .eq(InstructionMybatis::getInstruction_id, inst_uuid)
                .one();
        if(instruction==null){
            resultJson.put("message", "未找到该指令!");
            resultJson.put("data", data);
            return resultJson;
        }
        if (StrUtil.equals(instruction.getInstruction_status(),"2")||
                StrUtil.equals(instruction.getInstruction_status(),"3")){
            resultJson.put("message", "指令已完成或已取消,无法操作!");
            resultJson.put("data", data);
            return resultJson;
        }

        /* 1 指令撤销
        2 重新下发
        3 强制完成*/
        if ("1".equals(type)){
            try {
                if (StrUtil.isEmpty(instruction.getAgv_jobno())){
                    instructionService.cancelNOSendAgv(inst_uuid);
                }else {
                    ndcAgvService.deleteAgvInstToNDC(BeanUtil.copyProperties(instruction, Instruction.class));
                }
            } catch (Exception e) {
                resultJson.put("message", "下发agv失败!");
                resultJson.put("data", data);
                return resultJson;
            }
        }else if ("2".equals(type)){
            try {
                ndcAgvService.sendAgvInstToNDC(instruction.getAgv_system_type(),BeanUtil.copyProperties(instruction, Instruction.class));
            } catch (Exception e) {
                resultJson.put("message", "下发agv失败!");
                resultJson.put("data", data);
                return resultJson;
            }
        }else if ("3".equals(type)){
            try {
                instructionService.finish(inst_uuid);
            } catch (Exception e) {
                resultJson.put("message", e.getMessage());
                resultJson.put("data", data);
                return resultJson;
            }
        }

        resultJson.put("message", "操作成功");
        resultJson.put("data", data);
        return resultJson;
    }

    @Override
    public Map<String, Object> querytasks(HeadTaskDto dto) {
        String key = dto.getKeyword();
        String start_point = dto.getStart_devicecode();
        String next_point = dto.getNext_devicecode();

        List<Task> list;
        if (StrUtil.isEmpty(key)&&StrUtil.isEmpty(start_point)&&StrUtil.isEmpty(next_point)){
            list = taskserver.lambdaQuery()
                    .orderByDesc(Task::getCreate_time)
                    .lt(Task::getTask_status, "2")
                    .list();
        }else {
            list = taskserver.lambdaQuery()
                    .like(Task::getStart_device_code, start_point)
                    .like(Task::getNext_device_code, next_point)
                    .lt(Task::getTask_status, "2")
                    .eq(Task::getTask_code, key)
                    .or()
                    .eq(Task::getVehicle_code, key)
                    .or()
                    .eq(Task::getTask_id, key)
                    .orderByDesc(Task::getCreate_time)
                    .list();
        }
//        if (CollectionUtil.isEmpty(list)){
//            throw new BadRequestException("没有指令存在！");
//        }
        JSONArray data = new JSONArray();
        for (int i = 0; i < list.size(); i++) {
            JSONObject task = new JSONObject();
            task.put("task_uuid",list.get(i).getTask_id());
            task.put("task_no",list.get(i).getTask_code());
            task.put("start_devicecode",list.get(i).getStart_device_code());
            task.put("next_devicecode",list.get(i).getNext_device_code());
            task.put("task_status",list.get(i).getTask_status());
            task.put("task_status_name", TaskStatusEnum.getName(list.get(i).getTask_status()));
            task.put("priority",list.get(i).getPriority());
            task.put("create_time",list.get(i).getCreate_time());
            task.put("carrier",list.get(i).getVehicle_code()==null?"":list.get(i).getVehicle_code());
            data.add(task);
        }
        JSONObject resultJson = new JSONObject();
        resultJson.put("message", "操作成功");
        resultJson.put("data", data);
        return resultJson;
    }

    @Override
    public Map<String, Object> taskOperation(HeadTaskDto dto) {
        JSONObject resultJson = new JSONObject();
        JSONArray data = new JSONArray();
        String type = dto.getType();
        String task_uuid = dto.getTask_uuid();
        if (StrUtil.isEmpty(type)){
            throw new BadRequestException("操作类型不能为空！");
        }
        if (StrUtil.isEmpty(task_uuid)){
            throw new BadRequestException("id不能为空！");
        }
        TaskDto taskDto = taskserver.findById(task_uuid);
        if (BeanUtil.isEmpty(taskDto)){
            throw new BadRequestException("任务为空！");
        }
        String task_code = taskDto.getTask_code();
        String start_device_code = taskDto.getStart_device_code();
        String next_device_code = taskDto.getNext_device_code();
        String task_id = taskDto.getTask_id();

        if(StrUtil.equals(taskDto.getTask_status(),"2")||StrUtil.equals(taskDto.getTask_status(),"3")){
            resultJson.put("message", "任务已完成或已取消,无法操作");
            resultJson.put("data", data);
            return resultJson;
        }
        if ("1".equals(type)){
            //重新生成指令
            Instruction instdto = new Instruction();
            instdto.setInstruction_id(IdUtil.simpleUUID());
            instdto.setInstruction_code(CodeUtil.getNewCode("INSTRUCT_NO"));
            instdto.setRemark(taskDto.getRemark());
            instdto.setMaterial(taskDto.getMaterial());
            instdto.setTask_id(task_id);
            instdto.setTask_code(task_code);
            instdto.setVehicle_code(taskDto.getVehicle_code());
            String now = DateUtil.now();
            instdto.setCreate_time(now);
            instdto.setCreate_by("auto");
            instdto.setStart_point_code(taskDto.getStart_point_code());
            instdto.setNext_point_code(taskDto.getNext_point_code());
            instdto.setStart_device_code(start_device_code);
            instdto.setNext_device_code(next_device_code);
            instdto.setInstruction_status("0");
            InstructionMybatis instructionMybatis = instructionService.lambdaQuery()
                    .eq(InstructionMybatis::getStart_device_code, start_device_code)
                    .eq(InstructionMybatis::getNext_device_code, next_device_code)
                    .lt(InstructionMybatis::getInstruction_status, "2")
                    .eq(InstructionMybatis::getTask_id,task_uuid)
                    .one();
            if (BeanUtil.isNotEmpty(instructionMybatis)){
                resultJson.put("message", task_code + ":该任务已存在待完成指令!");
                resultJson.put("data", data);
                return resultJson;
            }
            try{
                instructionService.create(instdto);
            } catch (Exception e){
                resultJson.put("message", e.getMessage());
                resultJson.put("data", data);
                return resultJson;
            }
            instdto.setExecute_code(start_device_code);
        }else if ("2".equals(type)){
            //强制完成
            Instruction instruction = instructionService.findByTaskid(task_uuid, "instruction_status <2 ");
            if (instruction!=null){
                resultJson.put("message", "有指令未完成!");
                resultJson.put("data", data);
                return resultJson;
            }
            TaskIdAndStatusDTO taskIdAndStatusDTO = new TaskIdAndStatusDTO();
            taskIdAndStatusDTO.setTask_id(task_uuid);
            taskIdAndStatusDTO.setTask_status(TaskStatusEnum.FINISHED.getIndex());
            taskserver.finish(task_uuid);
        }
        resultJson.put("message", "操作成功");
        resultJson.put("data", data);
        return resultJson;
    }
}
