namespace SHH.CameraSdk;

/// <summary>
/// 视频源基础配置对象 (V3.3.1 修复版)
/// 核心职责：定义建立相机物理连接所需的所有标准化参数与厂商扩展参数
/// 关键修复：
/// <para>1. [Fix Bug U: 配置漂移] 驱动层接收配置时需创建副本，防止外部修改导致的连接异常</para>
/// <para>2. 强化配置有效性校验，提前拦截非法参数</para>
/// 注意事项：此类为引用类型，传递时建议使用深拷贝
/// </summary>
public class VideoSourceConfig
{
    #region --- 1. 核心连接配置 (Core Connection Configurations) ---

    /// <summary> 业务系统唯一标识（对应数据库自增ID，全局唯一） </summary>
    public long Id { get; set; }

    /// <summary> 设备显示名称（如：北大门-枪机01，用于前端展示） </summary>
    public string Name { get; set; } = string.Empty;

    /// <summary> 设备品牌（决定加载对应的驱动实现类） </summary>
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public DeviceBrand Brand { get; set; } = DeviceBrand.Unknown;

    /// <summary> 设备 IP 地址或域名（如 192.168.1.100 或 camera.example.com） </summary>
    public string IpAddress { get; set; } = string.Empty;

    /// <summary> 设备端口号（厂商默认值：海康8000、大华37777、RTSP 554） </summary>
    public ushort Port { get; set; }

    /// <summary> 设备登录用户名（默认值：admin） </summary>
    public string Username { get; set; } = "admin";

    /// <summary> 设备登录密码（默认空字符串，需根据实际设备配置） </summary>
    public string Password { get; set; } = string.Empty;

    /// <summary> 渲染句柄（可选）：用于硬解码时直接绑定显示窗口，提升渲染性能 </summary>
    public long RenderHandle { get; set; }

    /// <summary> 物理通道号（IPC 通常为 1；NVR 对应接入的摄像头通道索引） </summary>
    public int ChannelIndex { get; set; } = 1;

    /// <summary> 默认码流类型（0 = 主码流(高清)，1 = 子码流(低带宽)） </summary>
    public int StreamType { get; set; } = 0;

    /// <summary> 关联的主板IP </summary>
    public string MainboardIp { get; set; }
        = string.Empty;

    /// <summary>关联的主板端口</summary>
    public int MainboardPort { get; set; }

    /// <summary> Rtsp 播放路径 </summary>
    public string RtspPath {  get; set; } = string.Empty;

    /// <summary> 传输协议（TCP/UDP/Multicast，默认 TCP 保证可靠性） </summary>
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public TransportProtocol Transport { get; set; } = TransportProtocol.Tcp;

    /// <summary> 连接超时时间（毫秒，默认 5000ms = 5秒） </summary>
    public int ConnectionTimeoutMs { get; set; } = 5000;

    #endregion


    #region --- 2. 厂商扩展配置 (Vendor-Specific Extensions) ---

    /// <summary>
    /// 厂商扩展参数字典
    /// 用途：存储无法标准化的品牌专属参数
    /// 示例：
    /// <code>
    /// { 
    ///     "RtspPath": "/h264/ch1/main/av_stream", 
    ///     "HikLoginMode": "ISAPI",
    ///     "DaHuaStreamProtocol": "HTTP"
    /// }
    /// </code>
    /// </summary>
    public Dictionary<string, string> VendorArguments { get; set; } = new();

    #endregion

    #region --- 3. 配置工具方法 (Configuration Utility Methods) ---

    /// <summary>
    /// 配置有效性校验：检查核心参数是否合法，非法则抛出异常
    /// 作用：提前拦截无效配置，避免驱动层连接时出现未知错误
    /// </summary>
    /// <exception cref="ArgumentException">核心参数非法时抛出</exception>
    public void Validate()
    {
        if (Id <= 0)
            throw new ArgumentException("配置ID必须为正整数", nameof(Id));
        if (string.IsNullOrWhiteSpace(IpAddress))
            throw new ArgumentException("IP地址不能为空", nameof(IpAddress));
        if (Port == 0)
            throw new ArgumentException("端口号必须为有效数值", nameof(Port));
        if (Brand == DeviceBrand.Unknown)
            throw new ArgumentException("必须指定设备品牌", nameof(Brand));
        if (ChannelIndex <= 0)
            throw new ArgumentException("通道号必须为正整数", nameof(ChannelIndex));
        if (ConnectionTimeoutMs <= 0)
            throw new ArgumentException("连接超时时间必须大于0", nameof(ConnectionTimeoutMs));
    }

    /// <summary>
    /// 生成设备唯一连接指纹
    /// 用途：用于连接池去重、缓存键、日志标识等场景
    /// 格式：{Brand}://{Username}@{IpAddress}:{Port}/{ChannelIndex}
    /// </summary>
    /// <returns>唯一连接指纹字符串</returns>
    public string GetConnectionKey()
    {
        // 使用 StringBuilder 提升拼接性能，避免频繁创建字符串
        return new StringBuilder()
            .Append(Brand)
            .Append("://")
            .Append(Username)
            .Append('@')
            .Append(IpAddress)
            .Append(':')
            .Append(Port)
            .Append('/')
            .Append(ChannelIndex)
            .ToString();
    }

    /// <summary>
    /// 创建配置对象的深拷贝（防止外部修改导致配置漂移）
    /// </summary>
    /// <returns>新的配置副本</returns>
    public VideoSourceConfig DeepCopy()
    {
        var copy = new VideoSourceConfig
        {
            Id = this.Id,
            Name = this.Name,
            Brand = this.Brand,
            IpAddress = this.IpAddress,
            Port = this.Port,
            Username = this.Username,
            Password = this.Password,
            RenderHandle = this.RenderHandle,
            ChannelIndex = this.ChannelIndex,
            MainboardIp = this.MainboardIp,
            MainboardPort = this.MainboardPort,
            RtspPath = this.RtspPath,
            StreamType = this.StreamType,
            Transport = this.Transport,
            ConnectionTimeoutMs = this.ConnectionTimeoutMs
        };

        // 深拷贝扩展参数字典
        foreach (var kvp in this.VendorArguments)
        {
            copy.VendorArguments.Add(kvp.Key, kvp.Value);
        }

        return copy;
    }

    #endregion
}