package com.zehong.system.service.impl;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import com.zehong.common.utils.DateUtils;
import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.mapper.TStoreyInfoMapper;
import com.zehong.system.netty.handler.NettyUdpServerHandler;
import com.zehong.system.service.websocket.RobotArmWebSocketHandler;
import com.zehong.system.udp.UdpCommandSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.zehong.system.mapper.RobotArmCommandMapper;
import com.zehong.system.domain.RobotArmCommand;
import com.zehong.system.service.IRobotArmCommandService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 机械臂指令Service业务层处理
 * 
 * @author zehong
 * @date 2025-08-04
 */
@Service
public class RobotArmCommandServiceImpl implements IRobotArmCommandService 
{
    private static final Logger log = LoggerFactory.getLogger(RobotArmCommandServiceImpl.class);

    @Resource
    private NettyUdpServerHandler nettyUdpServerHandler;

    @Resource
    private RobotArmWebSocketHandler robotArmWebSocketHandler;

    @Resource
    private RobotArmCommandMapper robotArmCommandMapper;

    @Resource
    private TStoreyInfoMapper storeyInfoMapper;

    @Resource
    private UdpCommandSender udpCommandSender;
    @Value("${robot.arm.udp.ip}")
    private String robotArmAddress;

    @Value("${robot.arm.udp.port}")
    private int robotArmPort;

    private SocketAddress getRobotAddress() {
        try {
            return new InetSocketAddress(
                    InetAddress.getByName(robotArmAddress), robotArmPort);
        } catch (UnknownHostException e) {
            throw new RuntimeException("无效的机械臂地址: " + robotArmAddress);
        }
    }

    @Override
    @Transactional
    public void processPendingCommands() {
        // 1. 处理待执行的上料指令
        List<RobotArmCommand> loadingCommands =
                robotArmCommandMapper.selectPendingLoadingCommands();
        if (!loadingCommands.isEmpty()) {
            sendCommand(loadingCommands.get(0), "LOAD");
            return;
        }

        // 2. 处理待执行的下料指令
        List<RobotArmCommand> unloadingCommands =
                robotArmCommandMapper.selectPendingUnloadingCommands();
        if (!unloadingCommands.isEmpty()) {
            sendCommand(unloadingCommands.get(0), "UNLOAD");
        }
    }


    private void sendCommand(RobotArmCommand command, String commandType) {
        // 更新状态为执行中
        command.setStatus("1");
        command.setStartExecutionTime(new Date());
        robotArmCommandMapper.updateRobotArmCommand(command);

        // 通过WebSocket广播更新
        robotArmWebSocketHandler.broadcastCommandUpdate();

        // 发送UDP指令
        SocketAddress address = getRobotAddress();
        udpCommandSender.sendCommandWithId(
                address,
                command.getRobotArmCommandId(),
                commandType,
                command.getTrayCode(),
                command.getStoreyCode()
        );

        // 注册指令跟踪
        nettyUdpServerHandler.registerCommandExecution(address, command.getRobotArmCommandId());
    }

    @Override
    @Transactional
    public void completeCommand(Long commandId) {
        RobotArmCommand command = robotArmCommandMapper.selectRobotArmCommandById(commandId);
        if (command != null && "1".equals(command.getStatus())) {
            command.setStatus("3");
            command.setEndExecutionTime(new Date());
            robotArmCommandMapper.updateRobotArmCommand(command);

            // 通过WebSocket广播更新
            robotArmWebSocketHandler.broadcastCommandUpdate();
        }
    }

    @Override
    @Transactional
    public void markCommandTimeout(Long commandId) {
        RobotArmCommand command = robotArmCommandMapper.selectRobotArmCommandById(commandId);
        if (command != null && "1".equals(command.getStatus())) {
            command.setStatus("3"); // 标记为未上电
            robotArmCommandMapper.updateRobotArmCommand(command);

            // 通过WebSocket广播更新
            robotArmWebSocketHandler.broadcastCommandUpdate();

            robotArmWebSocketHandler.broadcastStatus("idle");
        }
    }

    @Override
    @Transactional
    public void completeCommand(String trayCode, String storeyCode) {
        // 1. 查找对应的执行中指令
        RobotArmCommand command = robotArmCommandMapper.findExecutingCommand(trayCode, storeyCode);

        if (command == null) {
            log.warn("未找到对应的执行中指令: {} @ {}", trayCode, storeyCode);
            return;
        }

        // 2. 更新状态为已完成
        command.setStatus("3");
        command.setEndExecutionTime(new Date());
        robotArmCommandMapper.updateRobotArmCommand(command);

        log.info("指令完成: {} @ {}", trayCode, storeyCode);

        // 3. 广播指令更新
        robotArmWebSocketHandler.broadcastCommandUpdate();
    }

    private void sendLoadingCommand(RobotArmCommand command) {
        // 更新状态为执行中
        command.setStatus("1");
        command.setStartExecutionTime(new Date());
        robotArmCommandMapper.updateRobotArmCommand(command);

        notifyCommandsUpdate();

        // 发送UDP指令
        String udpMessage = String.format("LOAD,%s,%s", command.getTrayCode(), command.getStoreyCode());
        udpCommandSender.sendCommand(udpMessage);
    }

    private void sendUnloadingCommand(RobotArmCommand command) {
        // 更新状态为执行中
        command.setStatus("1");
        command.setStartExecutionTime(new Date());
        robotArmCommandMapper.updateRobotArmCommand(command);

        notifyCommandsUpdate();
        // 发送UDP指令
        String udpMessage = String.format("UNLOAD,%s,%s", command.getTrayCode(), command.getStoreyCode());
        udpCommandSender.sendCommand(udpMessage);
    }

    /**
     * 查询机械臂指令
     * 
     * @param robotArmCommandId 机械臂指令ID
     * @return 机械臂指令
     */
    @Override
    public RobotArmCommand selectRobotArmCommandById(Long robotArmCommandId)
    {
        return robotArmCommandMapper.selectRobotArmCommandById(robotArmCommandId);
    }

    /**
     * 查询机械臂指令列表
     * 
     * @param robotArmCommand 机械臂指令
     * @return 机械臂指令
     */
    @Override
    public List<RobotArmCommand> selectRobotArmCommandList(RobotArmCommand robotArmCommand)
    {
        return robotArmCommandMapper.selectRobotArmCommandList(robotArmCommand);
    }

    @Override
    public List<RobotArmCommand> findByType(String type) {
        return robotArmCommandMapper.findByType( type);
    }

    /**
     * 新增机械臂指令
     * 
     * @param robotArmCommand 机械臂指令
     * @return 结果
     */
    @Override
    public int insertRobotArmCommand(RobotArmCommand robotArmCommand)
    {
        robotArmCommand.setCreateTime(DateUtils.getNowDate());

        TStoreyInfo tStoreyInfo = storeyInfoMapper.selectNearestFreeStorey();
        if(tStoreyInfo != null) {
            robotArmCommand.setStoreyCode(tStoreyInfo.getfStoreyCode());
        } else {
            robotArmCommand.setStoreyCode("无空闲老化层");
        }

        int i = robotArmCommandMapper.insertRobotArmCommand(robotArmCommand);
        notifyCommandsUpdate();
        return i;
    }

    @Override
    @Transactional
    public void powerOnCommand(Long commandId) {
        RobotArmCommand command = robotArmCommandMapper.selectRobotArmCommandById(commandId);
        if (command == null) {
            throw new RuntimeException("指令不存在");
        }

        if (!"2".equals(command.getStatus())) {
            throw new RuntimeException("只有未上电状态的指令才能执行上电操作");
        }

        // 更新状态为执行中
        command.setStatus("1");
        robotArmCommandMapper.updateRobotArmCommand(command);

        // 发送上电指令给机械臂
        String udpMessage = String.format("POWER_ON,%s,%s", command.getTrayCode(), command.getStoreyCode());
        udpCommandSender.sendCommand(udpMessage);

        // 记录操作日志
        log.info("执行上电操作: 指令ID={}, 托盘={}, 位置={}", commandId, command.getTrayCode(), command.getStoreyCode());
    }

    /**
     * 修改机械臂指令
     * 
     * @param robotArmCommand 机械臂指令
     * @return 结果
     */
    @Override
    public int updateRobotArmCommand(RobotArmCommand robotArmCommand)
    {
        int i = robotArmCommandMapper.updateRobotArmCommand(robotArmCommand);
        notifyCommandsUpdate();
        return i;
    }

    /**
     * 批量删除机械臂指令
     * 
     * @param robotArmCommandIds 需要删除的机械臂指令ID
     * @return 结果
     */
    @Override
    public int deleteRobotArmCommandByIds(Long[] robotArmCommandIds)
    {
        int i = robotArmCommandMapper.deleteRobotArmCommandByIds(robotArmCommandIds);
        notifyCommandsUpdate();
        return i;
    }

    /**
     * 删除机械臂指令信息
     * 
     * @param robotArmCommandId 机械臂指令ID
     * @return 结果
     */
    @Override
    public int deleteRobotArmCommandById(Long robotArmCommandId)
    {
        int i = robotArmCommandMapper.deleteRobotArmCommandById(robotArmCommandId);
        notifyCommandsUpdate();
        return i;
    }

    @Override
    @Transactional
    public void processIdleState() {
        // 1. 更新执行中状态为完成状态
        robotArmCommandMapper.updateExecutingToCompleted();

        // 2. 优先处理上料指令
        List<RobotArmCommand> loadingCommands = robotArmCommandMapper.selectPendingLoadingCommands();
        if (!loadingCommands.isEmpty()) {
            RobotArmCommand command = loadingCommands.get(0);
            sendLoadingCommand(command);
            return;
        }

        // 3. 处理下料指令
        List<RobotArmCommand> unloadingCommands = robotArmCommandMapper.selectPendingUnloadingCommands();
        if (!unloadingCommands.isEmpty()) {
            RobotArmCommand command = unloadingCommands.get(0);
            sendUnloadingCommand(command);
        }
    }

    private void notifyCommandsUpdate() {
        robotArmWebSocketHandler.broadcastCommandUpdate();
    }
}
