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

namespace SHH.CameraService;

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

    /// <summary>指令名称（需与网关下发的 CmdCode 一致）</summary>
    public string ActionName => ProtocolCodes.Device_Preset;

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

    public async Task ExecuteAsync(JToken payload)
    {
        // 1. 解析预置点控制参数
        // 假设 PresetControlDto 包含 DeviceId, PresetIndex, 和 Action (GOTO/SET/REMOVE)
        var presetDto = payload.ToObject<PresetControlDto>();
        if (presetDto == null || presetDto.DeviceId <= 0)
        {
            _sysLog.Warning("[Preset] 无效指令：参数缺失或设备ID非法");
            return;
        }

        // 2. 获取目标设备并校验能力
        var device = _cameraManager.GetDevice(presetDto.DeviceId);
        if (device == null)
        {
            _sysLog.Warning($"[Preset] 设备 {presetDto.DeviceId} 不存在");
            return;
        }
        if (!device.IsPhysicalOnline)
        {
            _sysLog.Warning($"[Preset] 设备 {presetDto.DeviceId} 未在线，无法执行预置点控制");
            return;
        }

        // Optimized: [原因] 检查设备是否实现了预置点功能接口
        if (!(device is IPresetFeature presetFeature))
        {
            _sysLog.Warning($"[Preset] 设备 {presetDto.DeviceId} ({device.Config.Name}) 不支持预置点功能");
            return;
        }

        // 3. 分发执行逻辑
        try
        {
            switch (presetDto.Action.ToUpper())
            {
                case "GOTO":
                    await presetFeature.GotoPresetAsync(presetDto.PresetIndex);
                    _sysLog.Information($"[Preset] 设备 {presetDto.DeviceId} 跳转至预置点: {presetDto.PresetIndex}");
                    break;
                case "SET":
                    await presetFeature.SetPresetAsync(presetDto.PresetIndex);
                    _sysLog.Information($"[Preset] 设备 {presetDto.DeviceId} 设置当前位置为预置点: {presetDto.PresetIndex}");
                    break;
                case "REMOVE":
                    await presetFeature.RemovePresetAsync(presetDto.PresetIndex);
                    _sysLog.Information($"[Preset] 设备 {presetDto.DeviceId} 删除预置点: {presetDto.PresetIndex}");
                    break;
                default:
                    _sysLog.Warning($"[Preset] 未知操作类型: {presetDto.Action}");
                    break;
            }
        }
        catch (Exception ex)
        {
            _sysLog.Error(ex, $"[Preset] 设备 {presetDto.DeviceId} 预置点操作失败");
        }
    }
}

/// <summary>PresetControlDto 参数</summary>
public class PresetControlDto
{
    /// <summary>设备ID</summary>
    public int DeviceId { get; set; }

    /// <summary>预置点编号 (1-255)</summary>
    public int PresetIndex { get; set; }

    /// <summary>动作：GOTO, SET, REMOVE</summary>
    public string Action { get; set; } = string.Empty;
}