using Ayay.SerilogLogs;
using Newtonsoft.Json.Linq;
using Serilog;
using SHH.CameraSdk;
using SHH.Contracts;

namespace SHH.CameraService;

/// <summary>
/// 云台控制指令处理器
/// 响应 gRpc 指令：ProtocolCodes.Control_Ptz
/// </summary>
public class PtzControlHandler : ICommandHandler
{
    private readonly ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
    private readonly CameraManager _cameraManager;

    /// <summary>指令名称（需与网关下发的 CmdCode 一致）</summary>
    public string ActionName => ProtocolCodes.Ptz_Control; // 需在 ProtocolCodes 中新增该常量

    public PtzControlHandler(CameraManager cameraManager)
    {
        _cameraManager = cameraManager ?? throw new ArgumentNullException(nameof(cameraManager));
    }

    public async Task ExecuteAsync(JToken payload)
    {
        // 1. 解析 PTZ 控制参数（与网关下发的 JSON 结构匹配）
        var ptzDto = payload.ToObject<PtzControlDto>();
        if (ptzDto == null || ptzDto.DeviceId <= 0)
        {
            _sysLog.Warning("[PTZ] 无效指令：参数缺失或设备ID非法");
            return;
        }

        // 2. 获取目标设备并校验能力
        var device = _cameraManager.GetDevice(ptzDto.DeviceId);
        if (device == null)
        {
            _sysLog.Warning($"[PTZ] 设备 {ptzDto.DeviceId} 不存在");
            return;
        }
        if (!device.IsPhysicalOnline)
        {
            _sysLog.Warning($"[PTZ] 设备 {ptzDto.DeviceId} 未在线，无法执行云台控制");
            return;
        }
        if (!(device is IPtzFeature ptzFeature))
        {
            _sysLog.Warning($"[PTZ] 设备 {ptzDto.DeviceId} 不支持云台控制");
            return;
        }

        // 3. 执行云台控制（根据指令类型选择手动/点动模式）
        try
        {
            if (ptzDto.Duration > 0)
            {
                // 点动模式：自动复位（如持续300ms向上转动）
                int safeDuration = Math.Clamp(ptzDto.Duration, 50, 2000); // 限制单次最长2秒
                await ptzFeature.PtzStepAsync(ptzDto.Action, safeDuration, ptzDto.Speed);
                _sysLog.Information($"[PTZ] 设备 {ptzDto.DeviceId} 点动控制：{ptzDto.Action}，时长 {safeDuration}ms，速度 {ptzDto.Speed}");
            }
            else
            {
                // 手动模式：按下/松开（如按住向上、松开停止）
                await ptzFeature.PtzControlAsync(ptzDto.Action, ptzDto.Stop, ptzDto.Speed);
                string actionDesc = ptzDto.Stop ? "停止" : "启动";
                _sysLog.Information($"[PTZ] 设备 {ptzDto.DeviceId} 手动控制：{ptzDto.Action} {actionDesc}，速度 {ptzDto.Speed}");
            }
        }
        catch (Exception ex)
        {
            _sysLog.Error(ex, $"[PTZ] 设备 {ptzDto.DeviceId} 控制失败");
        }
    }
}