using Microsoft.AspNetCore.Mvc;
using SHH.Contracts;

namespace SHH.CameraSdk;

[ApiController]
[Route("api/[controller]")]
public class CamerasController : ControllerBase
{
    private readonly CameraManager _manager;

    // 1. 新增：我们需要配置管理器
    private readonly ProcessingConfigManager _configManager;

    // 构造函数注入管理器
    public CamerasController(CameraManager manager, DisplayWindowManager displayManager, ProcessingConfigManager configManager)
    {
        _manager = manager;
        _displayManager = displayManager;
        _configManager = configManager;
    }

    // ==========================================================================
    // 区域 A: 设备全生命周期管理 (CRUD)
    // ==========================================================================

    /// <summary>
    /// 1. 获取所有设备清单
    /// </summary>
    [HttpGet]
    public IActionResult GetAll()
    {
        var devices = _manager.GetAllDevices().Select(d => new
        {
            d.Id,
            d.Config.Name,
            d.Config.RenderHandle,
            d.Config.StreamType,
            d.Config.IpAddress,
            Brand = d.Config.Brand.ToString(),
            Status = d.Status.ToString(),
            d.RealFps,
            d.TotalFrames,
            d.IsPhysicalOnline,
            d.IsActived,
            d.IsRunning,
            d.Width,
            d.Height,
            d.PreprocessSettings.AllowEnlarge,
            d.PreprocessSettings.AllowShrink,
            ScalingWidth = d.PreprocessSettings.Width,
            ScalingHeight = d.PreprocessSettings.Height,
        });
        return Ok(devices);
    }

    /// <summary>
    /// 2. 新增设备 (写入配置并初始化)
    /// </summary>
    [HttpPost]
    public IActionResult Add([FromBody] CameraConfigDto dto)
    {
        if (_manager.GetDevice(dto.Id) != null)
            return Conflict($"设备ID {dto.Id} 已存在");

        // DTO 转 Config (实际项目中建议用 AutoMapper)
        var config = MapToConfig(dto);

        _manager.AddDevice(config); // 添加到内存池
                                    // 注意：此时 IsRunning 默认为 false，等待手动 Start 或 API 控制

        return CreatedAtAction(nameof(GetAll), new { id = dto.Id }, dto);
    }

    /// <summary>
    /// 3. 编辑设备 (自动识别冷热更新)
    /// </summary>
    [HttpPut("{id}")]
    public async Task<IActionResult> Update(long id, [FromBody] CameraConfigDto dto)
    {
        try
        {
            if (id != dto.Id) return BadRequest("ID 不匹配");

            // 调用 Manager 的智能更新逻辑 (之前实现的 UpdateDeviceConfigAsync)
            await _manager.UpdateDeviceConfigAsync(id, MapToUpdateDto(dto));

            return Ok(new { Success = true, Message = "配置已更新" });
        }
        catch (KeyNotFoundException) { return NotFound(); }
        catch (System.Exception ex) { return StatusCode(500, ex.Message); }
    }

    /// <summary>
    /// 4. 删除设备 (销毁连接)
    /// </summary>
    [HttpDelete("{id}")]
    public async Task<IActionResult> Remove(long id)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound();

        await device.StopAsync(); // 停流
        _manager.RemoveDevice(id); // 从池中移除

        return Ok($"设备 {id} 已移除");
    }

    // ==========================================================================
    // 区域 B: 多进程流控订阅 (Subscription Strategy)
    // ==========================================================================


    // ==========================================================================
    // 区域 C: 句柄动态绑定 (Handle Binding)
    // ==========================================================================

    /// <summary>
    /// 6. 绑定显示窗口 (对应 A进程-句柄场景)
    /// </summary>
    [HttpPost("{id}/bind-handle")]
    public IActionResult BindHandle(long id, [FromBody] BindHandleDto dto)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound();

        // 构造动态选项，应用句柄
        var options = new DynamicStreamOptions
        {
            RenderHandle = (System.IntPtr)dto.Handle
        };

        device.ApplyOptions(options); // 触发驱动层的 OnApplyOptions

        device.AddAuditLog($"绑定新句柄: {dto.Handle} ({dto.Purpose})");

        return Ok(new { Success = true });
    }

    // ==========================================================================
    // 区域 D: 设备运行控制
    // ==========================================================================

    /// <summary>
    /// 手动控制设备运行状态 (开关机)
    /// </summary>
    [HttpPost("{id}/power")]
    public async Task<IActionResult> TogglePower(long id, [FromQuery] bool enabled)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound();

        // 1. 更新运行意图
        device.IsRunning = enabled;

        // 2. 审计与执行
        if (enabled)
        {
            device.AddAuditLog("用户指令：手动开启设备");
            // 异步启动，Coordinator 也会在下个周期辅助检查
            _ = device.StartAsync();
        }
        else
        {
            device.AddAuditLog("用户指令：手动关闭设备");
            await device.StopAsync();
        }

        return Ok(new { DeviceId = id, IsRunning = enabled });
    }

    /// <summary>
    /// 热应用动态参数 (如切换码流)
    /// </summary>
    [HttpPost("{id}/options")]
    public IActionResult ApplyOptions(long id, [FromBody] DynamicStreamOptions options)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound();

        // 1. 如果涉及码流切换，先同步更新配置对象
        if (options.StreamType.HasValue)
        {
            var newConfig = device.Config.DeepCopy();
            newConfig.StreamType = options.StreamType.Value;
            device.UpdateConfig(newConfig);
        }

        // 2. 应用到驱动层（触发热切换逻辑）
        device.ApplyOptions(options);

        return Ok(new { Message = "动态参数已发送", DeviceId = id });
    }

    // ==========================================================================
    // 辅助方法 (Mapping)
    // ==========================================================================
    private VideoSourceConfig MapToConfig(CameraConfigDto dto)
    {
        return new VideoSourceConfig
        {
            Id = dto.Id,
            Name = dto.Name,
            Brand = (DeviceBrand)dto.Brand,
            IpAddress = dto.IpAddress,
            Port = dto.Port,
            Username = dto.Username,
            Password = dto.Password,
            ChannelIndex = dto.ChannelIndex,
            StreamType = dto.StreamType,
            RtspPath = dto.RtspPath,
            MainboardPort = dto.MainboardPort,
            MainboardIp = dto.MainboardIp,
            RenderHandle =dto.RenderHandle,
        };
    }

    /// <summary>
    /// [辅助方法] 将全量配置 DTO 转换为更新 DTO
    /// </summary>
    private DeviceUpdateDto MapToUpdateDto(CameraConfigDto dto)
    {
        return new DeviceUpdateDto
        {
            // ==========================================
            // 1. 冷更新参数 (基础连接信息)
            // ==========================================
            IpAddress = dto.IpAddress,
            Port = dto.Port,
            Username = dto.Username,
            Password = dto.Password,
            ChannelIndex = dto.ChannelIndex,
            Brand = dto.Brand,
            RtspPath = dto.RtspPath,
            RenderHandle = dto.RenderHandle,

            // ==========================================
            // 2. 热更新参数 (运行时属性)
            // ==========================================
            Name = dto.Name,
            Location = dto.Location,
            StreamType = dto.StreamType,

            MainboardIp = dto.MainboardIp,
            MainboardPort = dto.MainboardPort,


            // ==========================================
            // 3. 图像处理参数
            // ==========================================
            AllowCompress = dto.AllowCompress,
            AllowExpand = dto.AllowExpand,
            TargetResolution = dto.TargetResolution,
            EnhanceImage = dto.EnhanceImage,
            UseGrayscale = dto.UseGrayscale
        };
    }


    private readonly DisplayWindowManager _displayManager; // [新增]
    /// <summary>
    /// 综合订阅策略更新接口
    /// 支持：本地 OpenCV 窗口、海康句柄穿透、本地录像、网络传输
    /// </summary>
    [HttpPost("{id}/subscriptions")]
    public IActionResult UpdateSubscription(int id, [FromBody] SubscriptionDto dto)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound("设备不存在");

        // 1. 自动生成 ID 逻辑
        if (string.IsNullOrWhiteSpace(dto.AppId))
        {
            dto.AppId = $"SUB_{Guid.NewGuid().ToString("N").Substring(0, 8).ToUpper()}";
        }

        // 2. 获取流控控制器
        var controller = device.Controller;
        if (controller == null) return BadRequest("该设备类型不支持流控调度");

        // 3. 处理注销逻辑 (FPS 为 0 代表停止订阅)
        if (dto.DisplayFps <= 0)
        {
            controller.Unregister(dto.AppId);

            // 停止显示管理器中所有相关的显示任务 (无论是本地窗口还是句柄绑定)
            _displayManager.StopDisplay(dto.AppId);

            device.AddAuditLog($"注销订阅: {dto.AppId}");
            return Ok(new { Message = "Subscription removed", AppId = dto.AppId });
        }

        // 4. 业务参数合法性校验
        switch (dto.Type)
        {
            case SubscriptionType.LocalRecord when string.IsNullOrEmpty(dto.SavePath):
                return BadRequest("录像模式必须指定存放路径");
            case SubscriptionType.HandleDisplay when string.IsNullOrEmpty(dto.Handle):
                return BadRequest("句柄显示模式必须提供窗口句柄");
        }

        // 5. 将需求注册到流控控制器
        controller.Register(new FrameRequirement(dto));

        // 6. 路由显示逻辑 (核心整合点)
        if (dto.Type == SubscriptionType.LocalWindow)
        {
            // --- 保留旧版功能：启动本地 OpenCV 渲染窗口 ---
            _displayManager.StartDisplay(dto.AppId, id);
        }
        else if (dto.Type == SubscriptionType.HandleDisplay && !string.IsNullOrEmpty(dto.Handle))
        {

        }

        device.AddAuditLog($"更新订阅: {dto.AppId} ({dto.Type}), 目标 {dto.DisplayFps} FPS");

        return Ok(new
        {
            Success = true,
            AppId = dto.AppId,
            Message = "订阅策略已应用",
            CurrentConfig = controller.GetCurrentRequirements() // 返回当前所有订阅状态供前端同步
        });
    }

    [HttpGet("{id}/subscriptions")]
    public IActionResult GetSubscriptions(long id)
    {
        // 1. 检查设备是否存在
        var camera = _manager.GetDevice(id);
        if (camera == null)
        {
            return NotFound(new { error = $"Camera {id} not found." });
        }

        // 2. 从设备的 FrameController 获取当前活跃的订阅
        // 注意：FrameController.GetCurrentRequirements() 返回的是 List<FrameRequirement>
        // 它可以直接被序列化为 JSON
        var subs = camera.Controller.GetCurrentRequirements();

        return Ok(subs);
    }

    // =============================================================
    // 6. 新增：彻底删除/注销订阅 (RESTful DELETE)
    // URL: DELETE /api/cameras/{id}/subscriptions/{appId}
    // =============================================================
    [HttpDelete("{id}/subscriptions/{appId}")]
    public IActionResult RemoveSubscription(long id, string appId)
    {
        // 1. 检查设备是否存在
        var device = _manager.GetDevice(id);
        if (device == null)
        {
            return NotFound(new { error = $"Camera {id} not found." });
        }

        // 2. 获取流控控制器
        var controller = device.Controller;
        if (controller == null)
        {
            // 如果设备本身没有控制器（比如离线或不支持），也算删除成功
            return Ok(new { success = true, message = "Device has no controller, nothing to remove." });
        }

        // 3. 执行注销逻辑 (核心)
        // 从 FrameController 的分发列表中移除
        controller.Unregister(appId);

        // 4. 清理显示资源 (重要！)
        // 参考您 UpdateSubscription 中的逻辑，必须同时停止 DisplayManager，否则窗口关不掉
        _displayManager.StopDisplay(appId);

        // 5. 记录审计日志
        device.AddAuditLog($"用户指令：彻底注销订阅 [{appId}]");

        return Ok(new
        {
            success = true,
            message = $"Subscription {appId} has been removed and display stopped."
        });
    }

    // 1. 获取单个设备详情（用于编辑回填）
    [HttpGet("{id}")]
    public IActionResult GetDevice(int id)
    {
        var cam = _manager.GetDevice(id);
        if (cam == null) return NotFound();
        return Ok(cam.Config); // 返回原始配置对象
    }


    // 3. 清除特定设备的日志
    [HttpDelete("{id}/logs")]
    public IActionResult ClearLogs(int id)
    {
        var cam = _manager.GetDevice(id);
        cam?.ClearAuditLogs();
        return Ok();
    }

    //// 4. 抓图诊断
    //[HttpGet("{id}/capture")]
    //public async Task<IActionResult> Capture(int id)
    //{
    //    var cam = _manager.GetDevice(id);
    //    if (cam == null) return NotFound();
    //    var bytes = await cam.CaptureCurrentFrameAsync();
    //    return File(bytes, "image/jpeg");
    //}

    // =============================================================
    // 3. 新增：更新图像处理/分辨率参数的接口
    // URL 示例: POST /api/cameras/1001/processing
    // =============================================================
    [HttpPost("{id}/processing")]
    public IActionResult UpdateProcessingOptions(long id, [FromBody] ProcessingOptions options)
    {
        // A. 检查相机是否存在
        var camera = _manager.GetDevice(id);
        if (camera == null)
        {
            return NotFound(new { error = $"Camera {id} not found." });
        }

        // B. 参数校验 (防止宽高为0导致报错)
        if (options.TargetWidth <= 0 || options.TargetHeight <= 0)
        {
            return BadRequest(new { error = "Target dimensions must be greater than 0." });
        }

        // C. 执行更新 (热更，立即生效)
        // ScaleWorker 下一帧处理时会自动读取这个新配置
        _configManager.UpdateOptions(id, options);

        return Ok(new
        {
            success = true,
            message = "Image processing options updated.",
            currentConfig = options
        });
    }

    // 在 CamerasController 类中添加

    // =============================================================
    // 新增：获取/回显图像处理参数的接口
    // URL: GET /api/cameras/{id}/processing
    // =============================================================
    [HttpGet("{id}/processing")]
    public IActionResult GetProcessingOptions(long id)
    {
        // 1. 检查相机是否存在
        var camera = _manager.GetDevice(id);
        if (camera == null)
        {
            return NotFound(new { error = $"Camera {id} not found." });
        }

        // 2. 从配置管理器中获取当前配置
        // 注意：ProcessingConfigManager 内部应该处理好逻辑：
        // 如果该设备还没配过，它会自动返回 new ProcessingOptions() (默认值)
        var options = _configManager.GetOptions(id);

        // 3. 返回 JSON 给前端
        return Ok(options);
    }

    /// <summary>
    /// 获取设备时间 (支持海康/大华等具备此能力的设备)
    /// </summary>
    [HttpGet("{id}/time")]
    public async Task<IActionResult> GetDeviceTime(long id)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound(new { error = "Device not found" });

        if (!device.IsPhysicalOnline) return BadRequest(new { error = "Device is offline" });

        // 【核心】模式匹配：判断这个设备是否实现了“时间同步接口”
        if (device is ITimeSyncFeature timeFeature)
        {
            try
            {
                var time = await timeFeature.GetTimeAsync();
                return Ok(new { deviceId = id, currentTime = time });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { error = ex.Message });
            }
        }

        // 如果是 RTSP/USB 等不支持的设备
        return BadRequest(new { error = "This device does not support time synchronization." });
    }

    /// <summary>
    /// 设置设备时间
    /// </summary>
    [HttpPost("{id}/time")]
    public async Task<IActionResult> SetDeviceTime(long id, [FromBody] DateTime time)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound();

        if (device is ITimeSyncFeature timeFeature)
        {
            try
            {
                await timeFeature.SetTimeAsync(time);
                return Ok(new { success = true, message = $"Time synced to {time}" });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { error = ex.Message });
            }
        }

        return BadRequest(new { error = "This device does not support time synchronization." });
    }

    /// <summary>
    /// 远程重启设备
    /// </summary>
    [HttpPost("{id}/reboot")]
    public async Task<IActionResult> RebootDevice(long id)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound(new { error = "Device not found" });

        // 依然是两道防线：先检查在线，再检查能力
        if (!device.IsActived) return BadRequest(new { error = "Device is offline" });

        if (device is IRebootFeature rebootFeature)
        {
            try
            {
                await rebootFeature.RebootAsync();

                // 记录审计日志 (建议加上)
                device.AddAuditLog("用户执行了远程重启");

                return Ok(new { success = true, message = "重启指令已发送，设备将在几分钟后重新上线。" });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { error = ex.Message });
            }
        }

        return BadRequest(new { error = "This device does not support remote reboot." });
    }

    [HttpPost("{id}/ptz")]
    public async Task<IActionResult> PtzControl(long id, [FromBody] PtzControlDto dto)
    {
        var device = _manager.GetDevice(id);
        if (device == null) return NotFound();
        if (!device.IsActived) return BadRequest("Device offline");

        if (device is IPtzFeature ptz)
        {
            try
            {
                // 逻辑分流
                if (dto.Duration > 0)
                {
                    // 场景：点动模式 (一次调用，自动停止)
                    // 建议限制一下最大时长，防止前端传个 10000秒 导致云台转疯了
                    int safeDuration = Math.Clamp(dto.Duration, 50, 2000);
                    await ptz.PtzStepAsync(dto.Action, safeDuration, dto.Speed);
                }
                else
                {
                    // 场景：手动模式 (按下/松开)
                    await ptz.PtzControlAsync(dto.Action, dto.Stop, dto.Speed);
                }

                return Ok();
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { error = ex.Message });
            }// 
        }

        return BadRequest("Device does not support PTZ.");
    }  
}