package com.cmvr.edge.client.service.impl;

import cmvr.api.SpeakerCommand;
import cmvr.api.SpeakerServiceGrpc;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.edge.client.manage.GrpcServiceManager;
import com.cmvr.edge.client.service.EdgeSpeakerService;
import com.cmvr.edge.client.utils.EdgeCommonUtil;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 边缘扬声器服务实现类
 * 用于与边缘扬声器进行gRPC通信，控制扬声器播放和状态
 * 实现了EdgeSpeakerService接口，提供了扬声器控制的所有基本功能
 */
@Service
@RequiredArgsConstructor
public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
    /**
     * 日志记录器
     * 用于记录服务运行过程中的各种状态和错误信息
     */
    private static final Logger logger = LoggerFactory.getLogger(EdgeSpeakerServiceImpl.class);

    /**
     * gRPC服务管理器
     * 用于管理和获取gRPC客户端连接
     */
    private final GrpcServiceManager grpcServiceManager;

    /**
     * 获取扬声器当前状态
     * 通过gRPC调用获取扬声器的运行状态，包括是否正在播放、音量等信息
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @return SpeakerState 返回扬声器的当前状态
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public SpeakerCommand.GetSpeakerStateCommand.Feedback getStatus(String terminalId, String deviceId) {
        try {
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
            SpeakerCommand.GetSpeakerStateCommand.Request request = SpeakerCommand.GetSpeakerStateCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .build();
            // 直接返回完整的 Feedback
            return stub.getStatus(request);
        } catch (Exception e) {
            logger.error("获取扬声器状态失败", e);
            throw new RuntimeException("获取扬声器状态失败", e);
        }
    }

    /**
     * 播放音频文件
     * 通过gRPC调用播放指定路径的音频文件
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @param audioPath 音频文件的路径
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public String playAudio(String terminalId, String deviceId, String audioPath) {
        try {
            // 获取gRPC客户端存根
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);

            // 构建请求消息
            SpeakerCommand.PlayAudioCommand.Request request = SpeakerCommand.PlayAudioCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .setAudioPath(audioPath)
                    .build();

            // 发送请求
            SpeakerCommand.PlayAudioCommand.Feedback feedback = stub.playAudio(request);
            if (!feedback.getHeader().getSuccess()) {
                throw new RuntimeException((feedback.getHeader().getErrorMessage()));
            }
            return JSON.toJSONString(feedback.getHeader());
        } catch (Exception e) {
            logger.error("播放音频失败", e);
            throw new RuntimeException("播放音频失败", e);
        }
    }

    /**
     * 停止当前播放
     * 通过gRPC调用停止扬声器的当前播放
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public void stopPlayback(String terminalId, String deviceId) {
        try {
            // 获取gRPC客户端存根
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);

            // 构建请求消息
            SpeakerCommand.StopSpeakerCommand.Request request = SpeakerCommand.StopSpeakerCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .build();

            // 发送请求
            stub.stopPlayback(request);
        } catch (Exception e) {
            logger.error("停止播放失败", e);
            throw new RuntimeException("停止播放失败", e);
        }
    }

    /**
     * 暂停当前播放
     * 通过gRPC调用暂停扬声器的当前播放
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public void pausePlayback(String terminalId, String deviceId) {
        try {
            // 获取gRPC客户端存根
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);

            // 构建请求消息
            SpeakerCommand.PauseSpeakerCommand.Request request = SpeakerCommand.PauseSpeakerCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .build();

            // 发送请求
            stub.pausePlayback(request);
        } catch (Exception e) {
            logger.error("暂停播放失败", e);
            throw new RuntimeException("暂停播放失败", e);
        }
    }

    /**
     * 恢复暂停的播放
     * 通过gRPC调用恢复扬声器之前暂停的播放
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public void resumePlayback(String terminalId, String deviceId) {
        try {
            // 获取gRPC客户端存根
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);

            // 构建请求消息
            SpeakerCommand.ResumeSpeakerCommand.Request request = SpeakerCommand.ResumeSpeakerCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .build();

            // 发送请求
            stub.resumePlayback(request);
        } catch (Exception e) {
            logger.error("恢复播放失败", e);
            throw new RuntimeException("恢复播放失败", e);
        }
    }

    /**
     * 设置扬声器音量
     * 通过gRPC调用设置扬声器的音量大小
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @param volume 音量大小（0-100）
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public void setVolume(String terminalId, String deviceId, int volume) {
        try {
            // 获取gRPC客户端存根
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);

            // 构建请求消息
            SpeakerCommand.SetSpeakerVolumeCommand.Request request = SpeakerCommand.SetSpeakerVolumeCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .setVolume(volume)
                    .build();

            // 发送请求
            stub.setVolume(request);
        } catch (Exception e) {
            logger.error("设置音量失败", e);
            throw new RuntimeException("设置音量失败", e);
        }
    }

    /**
     * 获取当前音量
     * 通过gRPC调用获取扬声器的当前音量大小
     *
     * @param terminalId 终端设备ID
     * @param deviceId 设备ID
     * @return int 返回当前音量大小（0-100）
     * @throws RuntimeException 当gRPC调用失败时抛出异常
     */
    @Override
    public int getVolume(String terminalId, String deviceId) {
        try {
            // 获取gRPC客户端存根
            SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);

            // 构建请求消息
            SpeakerCommand.GetSpeakerVolumeCommand.Request request = SpeakerCommand.GetSpeakerVolumeCommand.Request.newBuilder()
                    .setHeader(EdgeCommonUtil.buildRequest(deviceId))
                    .build();

            // 发送请求并获取响应
            SpeakerCommand.GetSpeakerVolumeCommand.Feedback response = stub.getVolume(request);
            return response.getVolume();
        } catch (Exception e) {
            logger.error("获取音量失败", e);
            throw new RuntimeException("获取音量失败", e);
        }
    }

    @Override
    public List<String> getAll() {
        // 获取文件名
        String url = "http://10.148.108.162:8981/files/";
        HttpResponse response = HttpRequest.get(url)
                .timeout(5000)
                .execute().charset("UTF-8");
        String body = response.body();
        JSONObject object = JSON.parseObject(body);

        return object.getList("files", String.class);
    }
}