/*
 * 文 件 名:  PowerControlService
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  功率控制服务
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/12/25
 * 修改内容:  添加远程停机功能
 */
package com.ruoyi.ems.charging.service;

import com.ruoyi.ems.charging.core.ChargingPileSessionManager;
import com.ruoyi.ems.charging.model.resp.ReadRealtimeDataFrame;
import com.ruoyi.ems.charging.model.resp.RemoteStopFrame;
import com.ruoyi.ems.charging.model.resp.WorkParamSetFrame;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 功率控制服务
 * 用于能耗平台对充电桩进行功率调控和远程控制
 *
 * @author lvwenbin
 * @version [版本号, 2025/12/25]
 */
@Service
public class PowerControlService {

    private static final Logger log = LoggerFactory.getLogger(PowerControlService.class);

    @Autowired
    private ChargingPileSessionManager sessionManager;

    @Autowired
    private ChargingDataService chargingDataService;

    /**
     * 设置充电桩最大输出功率百分比
     *
     * @param pileCode              桩编号
     * @param maxOutputPowerPercent 最大输出功率百分比(30-100)
     * @return 是否发送成功
     */
    public boolean setMaxOutputPower(String pileCode, int maxOutputPowerPercent) {
        if (!sessionManager.isOnline(pileCode)) {
            log.warn("充电桩[{}]不在线，无法设置功率", pileCode);
            return false;
        }

        Channel channel = sessionManager.getChannel(pileCode);
        if (channel == null || !channel.isActive()) {
            log.warn("充电桩[{}]通道无效", pileCode);
            return false;
        }

        ChargingPileSessionManager.PileSession session = sessionManager.getSession(pileCode);
        int sequenceNo = session.nextSequenceNo();

        WorkParamSetFrame frame = WorkParamSetFrame.createPowerLimit(pileCode, maxOutputPowerPercent, sequenceNo);

        ChannelFuture future = channel.writeAndFlush(frame);

        try {
            future.await(5, TimeUnit.SECONDS);
            if (future.isSuccess()) {
                log.info("功率限制指令发送成功 - 桩号: {}, 功率限制: {}%", pileCode, maxOutputPowerPercent);
                return true;
            } else {
                log.error("功率限制指令发送失败 - 桩号: {}", pileCode, future.cause());
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("功率限制指令发送超时 - 桩号: {}", pileCode);
            return false;
        }
    }

    /**
     * 启用充电桩
     *
     * @param pileCode 桩编号
     * @return 是否发送成功
     */
    public boolean enablePile(String pileCode) {
        if (!sessionManager.isOnline(pileCode)) {
            log.warn("充电桩[{}]不在线，无法启用", pileCode);
            return false;
        }

        Channel channel = sessionManager.getChannel(pileCode);
        if (channel == null || !channel.isActive()) {
            return false;
        }

        ChargingPileSessionManager.PileSession session = sessionManager.getSession(pileCode);
        int sequenceNo = session.nextSequenceNo();

        WorkParamSetFrame frame = WorkParamSetFrame.createEnable(pileCode, sequenceNo);

        ChannelFuture future = channel.writeAndFlush(frame);

        try {
            future.await(5, TimeUnit.SECONDS);
            if (future.isSuccess()) {
                log.info("充电桩启用指令发送成功 - 桩号: {}", pileCode);
                return true;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return false;
    }

    /**
     * 禁用充电桩
     *
     * @param pileCode 桩编号
     * @return 是否发送成功
     */
    public boolean disablePile(String pileCode) {
        if (!sessionManager.isOnline(pileCode)) {
            log.warn("充电桩[{}]不在线，无法禁用", pileCode);
            return false;
        }

        Channel channel = sessionManager.getChannel(pileCode);
        if (channel == null || !channel.isActive()) {
            return false;
        }

        ChargingPileSessionManager.PileSession session = sessionManager.getSession(pileCode);
        int sequenceNo = session.nextSequenceNo();

        WorkParamSetFrame frame = WorkParamSetFrame.createDisable(pileCode, sequenceNo);

        ChannelFuture future = channel.writeAndFlush(frame);

        try {
            future.await(5, TimeUnit.SECONDS);
            if (future.isSuccess()) {
                log.info("充电桩禁用指令发送成功 - 桩号: {}", pileCode);
                return true;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return false;
    }

    /**
     * 远程停止充电
     * 
     * 使用场景：
     * 1. 紧急情况下远程停止充电
     * 2. 电网负荷调控需要时停止充电
     *
     * @param pileCode 桩编号
     * @param gunNo    枪号
     * @return 是否发送成功
     */
    public boolean remoteStop(String pileCode, String gunNo) {
        if (!sessionManager.isOnline(pileCode)) {
            log.warn("充电桩[{}]不在线，无法远程停机", pileCode);
            return false;
        }

        Channel channel = sessionManager.getChannel(pileCode);
        if (channel == null || !channel.isActive()) {
            log.warn("充电桩[{}]通道无效", pileCode);
            return false;
        }

        ChargingPileSessionManager.PileSession session = sessionManager.getSession(pileCode);
        int sequenceNo = session.nextSequenceNo();

        RemoteStopFrame frame = RemoteStopFrame.create(pileCode, gunNo, sequenceNo);

        ChannelFuture future = channel.writeAndFlush(frame);

        try {
            future.await(5, TimeUnit.SECONDS);
            if (future.isSuccess()) {
                String fullGunNo = pileCode + gunNo;
                log.info("远程停机指令发送成功 - 枪号: {}", fullGunNo);
                
                // 记录待处理请求，用于超时检测
                chargingDataService.recordStopRequest(fullGunNo);
                return true;
            } else {
                log.error("远程停机指令发送失败 - 桩号: {}, 枪号: {}", pileCode, gunNo, future.cause());
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("远程停机指令发送超时 - 桩号: {}, 枪号: {}", pileCode, gunNo);
            return false;
        }
    }

    /**
     * 远程停止充电（通过完整枪号）
     *
     * @param fullGunNo 完整枪号(桩编号14位+枪号)
     * @return 是否发送成功
     */
    public boolean remoteStopByFullGunNo(String fullGunNo) {
        if (fullGunNo == null || fullGunNo.length() < 15) {
            log.warn("完整枪号格式错误: {}", fullGunNo);
            return false;
        }
        String pileCode = fullGunNo.substring(0, 14);
        String gunNo = fullGunNo.substring(14);
        return remoteStop(pileCode, gunNo);
    }

    /**
     * 主动读取实时数据
     *
     * @param pileCode 桩编号
     * @param gunNo    枪号
     * @return 是否发送成功
     */
    public boolean readRealtimeData(String pileCode, String gunNo) {
        if (!sessionManager.isOnline(pileCode)) {
            log.warn("充电桩[{}]不在线，无法读取数据", pileCode);
            return false;
        }

        Channel channel = sessionManager.getChannel(pileCode);
        if (channel == null || !channel.isActive()) {
            return false;
        }

        ChargingPileSessionManager.PileSession session = sessionManager.getSession(pileCode);
        int sequenceNo = session.nextSequenceNo();

        ReadRealtimeDataFrame frame = ReadRealtimeDataFrame.create(pileCode, gunNo, sequenceNo);

        ChannelFuture future = channel.writeAndFlush(frame);

        try {
            future.await(5, TimeUnit.SECONDS);
            if (future.isSuccess()) {
                log.info("读取实时数据指令发送成功 - 桩号: {}, 枪号: {}", pileCode, gunNo);
                return true;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return false;
    }

    /**
     * 批量设置功率限制
     * 用于电网功率调控场景
     *
     * @param powerPercent 功率百分比
     */
    public void setAllPilesPowerLimit(int powerPercent) {
        log.info("批量设置所有充电桩功率限制: {}%", powerPercent);

        for (ChargingPileSessionManager.PileSession session : sessionManager.getAllOnlineSessions()) {
            if (session.isOnline() && session.getChannel() != null && session.getChannel().isActive()) {
                try {
                    setMaxOutputPower(session.getPileCode(), powerPercent);
                } catch (Exception e) {
                    log.error("设置充电桩[{}]功率限制失败", session.getPileCode(), e);
                }
            }
        }
    }

    /**
     * 批量停止所有正在充电的枪
     * 用于紧急情况
     *
     * @return 发送成功的数量
     */
    public int stopAllCharging() {
        log.warn("执行紧急停止所有充电操作");
        int successCount = 0;

        for (ChargingPileSessionManager.PileSession session : sessionManager.getAllOnlineSessions()) {
            if (session.isOnline() && session.getChannel() != null && session.getChannel().isActive()) {
                String pileCode = session.getPileCode();
                int gunCount = session.getGunCount();
                
                // 对每个枪发送停机命令
                for (int i = 1; i <= gunCount; i++) {
                    String gunNo = String.format("%02d", i);
                    try {
                        if (remoteStop(pileCode, gunNo)) {
                            successCount++;
                        }
                    } catch (Exception e) {
                        log.error("停止充电桩[{}]枪[{}]失败", pileCode, gunNo, e);
                    }
                }
            }
        }

        log.warn("紧急停止充电完成 - 成功发送: {}条", successCount);
        return successCount;
    }
}
