using Serilog;
using Ayay.SerilogLogs;

namespace SHH.CameraSdk.HikFeatures;

/// <summary>
/// [海康功能组件] 预置点管理实现
/// <para>适配说明：使用 NET_DVR_PTZPreset_Other 接口</para>
/// </summary>
public class HikPresetProvider : IPresetFeature
{
    private readonly IHikContext _context;

    #region --- 海康 PTZ 预置点命令常量 ---

    private const uint SET_PRESET = 8;    // 设置预置点
    private const uint CLE_PRESET = 9;    // 清除预置点
    private const uint GOTO_PRESET = 39;  // 转到预置点

    #endregion

    public HikPresetProvider(IHikContext context)
    {
        _context = context;
    }

    /// <summary>跳转到指定预置点</summary>
    public async Task GotoPresetAsync(int presetIndex)
    {
        await ExecutePresetAction(presetIndex, GOTO_PRESET, "调用");
    }

    /// <summary>将当前位置保存为预置点</summary>
    public async Task SetPresetAsync(int presetIndex)
    {
        await ExecutePresetAction(presetIndex, SET_PRESET, "保存");
    }

    /// <summary>删除指定的预置点</summary>
    public async Task RemovePresetAsync(int presetIndex)
    {
        await ExecutePresetAction(presetIndex, CLE_PRESET, "删除");
    }

    /// <summary>统一执行海康预置点 SDK 调用</summary>
    private async Task ExecutePresetAction(int index, uint command, string actionName)
    {
        int userId = _context.GetUserId();
        if (userId < 0) return;

        // 位置是从 1 开始, 调用 0 会导致设备重启
        if (index == 0) return;

        // 海康工业相机通道号通常为 1
        int channel = 1;

        await Task.Run(() =>
        {
            // Optimized: [原因] 使用 _Other 接口确保在单机多路并发下通道句柄准确
            bool result = HikNativeMethods.NET_DVR_PTZPreset_Other(
                userId,
                channel,
                command,
                (uint)index
            );

            if (!result)
            {
                uint err = HikNativeMethods.NET_DVR_GetLastError();
                Log.ForContext("SourceContext", LogModules.HikVisionSdk)
                   .Warning("[SDK] Hik 预置点{Action}失败. Index: {Index}, Error: {Error}",
                            actionName, index, err);
            }
            else
            {
                Log.ForContext("SourceContext", LogModules.HikVisionSdk)
                   .Debug("[SDK] Hik 预置点{Action}成功. Index: {Index}", actionName, index);
            }
        });
    }
}