namespace SHH.CameraSdk.HikFeatures;

/// <summary>
/// 海康时间同步组件
/// </summary>
public class HikTimeSyncProvider : ITimeSyncFeature
{
    private readonly IHikContext _context;

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

    public async Task<DateTime> GetTimeAsync()
    {
        // 1. 获取句柄
        int userId = _context.GetUserId();
        if (userId < 0) throw new InvalidOperationException("设备未登录");

        return await Task.Run(() =>
        {
            uint returned = 0;
            uint size = (uint)Marshal.SizeOf(typeof(HikNativeMethods.NET_DVR_TIME));
            IntPtr ptr = Marshal.AllocHGlobal((int)size);

            try
            {
                // 调用 SDK: NET_DVR_GET_TIME (命令号 118)
                bool result = HikNativeMethods.NET_DVR_GetDVRConfig(
                    userId,
                    HikNativeMethods.NET_DVR_GET_TIMECFG,
                    0,
                    ptr,
                    size,
                    ref returned);

                if (!result)
                {
                    var err = HikNativeMethods.NET_DVR_GetLastError();
                    throw new Exception($"获取时间失败, 错误码: {err}");
                }

                var t = Marshal.PtrToStructure<HikNativeMethods.NET_DVR_TIME>(ptr);
                return new DateTime((int)t.dwYear, (int)t.dwMonth, (int)t.dwDay, (int)t.dwHour, (int)t.dwMinute, (int)t.dwSecond);
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        });
    }

    public async Task SetTimeAsync(DateTime time)
    {
        int userId = _context.GetUserId();
        if (userId < 0) throw new InvalidOperationException("设备未登录");

        await Task.Run(() =>
        {
            var t = new HikNativeMethods.NET_DVR_TIME
            {
                dwYear = (uint)time.Year,
                dwMonth = (uint)time.Month,
                dwDay = (uint)time.Day,
                dwHour = (uint)time.Hour,
                dwMinute = (uint)time.Minute,
                dwSecond = (uint)time.Second
            };

            uint size = (uint)Marshal.SizeOf(t);
            IntPtr ptr = Marshal.AllocHGlobal((int)size);

            try
            {
                Marshal.StructureToPtr(t, ptr, false);

                // 调用 SDK: NET_DVR_SET_TIME (命令号 119)
                bool result = HikNativeMethods.NET_DVR_SetDVRConfig(
                    userId,
                    HikNativeMethods.NET_DVR_SET_TIMECFG,
                    0,
                    ptr,
                    size);

                if (!result)
                {
                    var err = HikNativeMethods.NET_DVR_GetLastError();
                    throw new Exception($"设置时间失败, 错误码: {err}");
                }
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        });
    }
}