using Check.Main.Camera;
using Check.Main.Common;
using OpenCvSharp;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using YoloDotNet;
using YoloDotNet.Models;
namespace Check.Main.Infer
{
    /// 
    /// YOLO 检测结果对象,包含标签、置信度与检测框
    /// 
    public class YoloPrediction
    {
        public YoloLabel Label { get; set; }
        public float Score { get; set; }
        public BoundingBox BoundingBox { get; set; }
    }
    /// 
    /// YOLO 类别标签
    /// 
    public class YoloLabel
    {
        public string Name { get; set; }
    }
    /// 
    /// 检测框坐标结构体
    /// 
    public struct BoundingBox
    {
        public float Left { get; set; }
        public float Top { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public BoundingBox(float left, float top, float width, float height)
        {
            Left = left;
            Top = top;
            Width = width;
            Height = height;
        }
    }
    /// 
    /// YOLO 目标检测器实现类
    /// 
    public class YoloDetector : IDetector, IDisposable
    {
        private Yolo _yoloModel;
        private int _modelID;
        private float _confidenceThreshold = 0.25f;
        private float _nmsThreshold = 0.45f;
        /// 
        /// 初始化 YOLO 检测器并加载模型
        /// 
        /// 模型 ID 字符串
        /// 可选检测参数
        /// ID 无效
        /// 模型未加载
        public void Initialize(string modelIdStr, object detectionSettings = null)
        {
            if (string.IsNullOrWhiteSpace(modelIdStr))
                throw new ArgumentException("模型ID字符串不能为空。", nameof(modelIdStr));
            if (!int.TryParse(modelIdStr, out _modelID))
                throw new ArgumentException("模型ID必须为有效整数。", nameof(modelIdStr));
            _yoloModel = YoloModelManager.GetModel(_modelID)
                ?? throw new InvalidOperationException($"YOLO 模型 (ID: {_modelID}) 未加载或找不到。");
            if (detectionSettings is YoloDetectionSettings yoloSettings)
            {
                _confidenceThreshold = Math.Clamp(yoloSettings.ConfidenceThreshold, 0f, 1f);
                _nmsThreshold = Math.Clamp(yoloSettings.NmsThreshold, 0f, 1f);
            }
        }
        /// 
        /// 执行检测,判断是否含有 logo 类对象
        /// 
        public DetectionResult Detect(Bitmap image)
        {
            if (_yoloModel == null)
                throw new InvalidOperationException("YoloDetector 未初始化或模型未加载。");
            if (image == null)
                return new DetectionResult(false, "输入图像为空。");
            try
            {
                using var skBitmap = CameraProcessor.ToSKBitmapFast(image);
                if (skBitmap == null)
                    return new DetectionResult(false, "图像转换失败。");
                using var skImage = SKImage.FromBitmap(skBitmap);
                if (skImage == null)
                    return new DetectionResult(false, "无法生成 SKImage。");
                var predictions = _yoloModel.RunObjectDetection(
                    skImage,
                    confidence: _confidenceThreshold,
                    iou: _nmsThreshold
                );
                // 检查是否检测到 logo
                bool foundLogo = predictions.Any(p =>
                    p.Label.Name.Equals("logo", StringComparison.OrdinalIgnoreCase));
                return foundLogo
                    ? new DetectionResult(false, "NG")
                    : new DetectionResult(true, "OK");
            }
            catch (Exception ex)
            {
                return new DetectionResult(false, $"检测失败: {ex.Message}");
            }
        }
        /// 
        /// 在图像上绘制检测框与标签
        /// 
        public Bitmap DrawYoloPredictions(Bitmap source, IEnumerable predictions)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (predictions == null || !predictions.Any())
                return (Bitmap)source.Clone();
            Bitmap output = (Bitmap)source.Clone();
            using var graphics = Graphics.FromImage(output);
            using var pen = new Pen(Color.Yellow, 2);
            using var font = new Font("Arial", 10, FontStyle.Bold);
            using var brush = new SolidBrush(Color.Yellow);
            foreach (var pred in predictions)
            {
                var box = pred.BoundingBox;
                var rect = new RectangleF(box.Left, box.Top, box.Width, box.Height);
                // 绘制检测框
                graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
                // 绘制标签
                string label = $"{pred.Label?.Name ?? "unknown"} ({pred.Score:P1})";
                graphics.DrawString(label, font, brush, rect.X, rect.Y - 15);
            }
            return output;
        }
        /// 
        /// 无需显式释放模型,资源由 YoloModelManager 管理
        /// 
        public void Dispose()
        {
            //_yoloModel = null;
        }
    }
}
//总结,区分好YoloModelManager.cs和YoloDetector.cs各自的职能,谁负责模型管理,谁负责yolo算法的执行,现在这两个文件是交织在一起比较乱的,有时间去处理一下
//看上面的定义的一些结构体胡总和类,就可以调用啦
//using Check.Main.Camera;
//using Check.Main.Common;
//using SkiaSharp;
//using System;
//using System.Collections.Generic;
//using System.Drawing;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using YoloDotNet;
//using YoloDotNet.Models;
//namespace Check.Main.Infer
//{
//    public class YoloDetector : IDetector
//    {
//        private Yolo _yoloModel;
//        private int _modelID; // 需要知道模型ID来从 YoloModelManager 获取
//        private float _confidenceThreshold = 0.25f;
//        private float _nmsThreshold = 0.45f;
//        public void Initialize(string modelIdStr, object detectionSettings = null)
//        {
//            if (!int.TryParse(modelIdStr, out _modelID))
//            {
//                throw new ArgumentException("YoloDetector 初始化需要有效的模型ID字符串。", nameof(modelIdStr));
//            }
//            _yoloModel = YoloModelManager.GetModel(_modelID);
//            if (_yoloModel == null)
//            {
//                throw new InvalidOperationException($"YOLO 模型 (ID: {_modelID}) 未加载或找不到。");
//            }
//            if (detectionSettings is YoloDetectionSettings yoloSettings)
//            {
//                _confidenceThreshold = yoloSettings.ConfidenceThreshold;
//                _nmsThreshold = yoloSettings.NmsThreshold;
//                // 注意:YOLO模型的置信度和NMS阈值最好在YoloModelManager加载时设置
//                // 这里如果需要运行时调整,可能需要Yolo.SetThresholds方法
//            }
//        }
//        public DetectionResult Detect(Bitmap image)
//        {
//            if (_yoloModel == null)
//                throw new InvalidOperationException("YoloDetector 未初始化或模型未加载。");
//            using (var skImage = CameraProcessor.ToSKBitmapFast(image)) // 使用 CameraProcessor 的静态方法
//            {
//                if (skImage == null)
//                {
//                    return new DetectionResult(false, "图像转换失败");
//                }
//                // 在这里可以应用运行时阈值,如果Yolo模型支持
//                // _yoloModel.Confidence = _confidenceThreshold;
//                // _yoloModel.Nms = _nmsThreshold;
//                var predictions = _yoloModel.RunObjectDetection(skImage);
//                bool isOk = !predictions.Any(); // 假设没有检测到任何目标为 OK
//                string message = isOk ? "OK" : "NG";
//                List boundingBoxes = predictions.Select(p => new RectangleF(p.Rectangle.X, p.Rectangle.Y, p.Rectangle.Width, p.Rectangle.Height)).ToList();
//                Bitmap resultImage = DrawYoloPredictions(image, predictions);
//                return new DetectionResult(isOk, message, 0, boundingBoxes, resultImage);
//            }
//        }
//        private Bitmap DrawYoloPredictions(Bitmap originalImage, IEnumerable predictions)
//        {
//            Bitmap resultBmp = (Bitmap)originalImage.Clone();
//            using (Graphics g = Graphics.FromImage(resultBmp))
//            {
//                Pen ngPen = new Pen(Color.Red, 3);
//                Font font = new Font("Arial", 12, FontStyle.Bold);
//                Brush brush = new SolidBrush(Color.Red);
//                foreach (var p in predictions)
//                {
//                    Rectangle rect = new Rectangle((int)p.Rectangle.X, (int)p.Rectangle.Y, (int)p.Rectangle.Width, (int)p.Rectangle.Height);
//                    g.DrawRectangle(ngPen, rect);
//                    g.DrawString($"{p.Label} ({p.Confidence:P})", font, brush, rect.X, rect.Y - 20);
//                }
//            }
//            return resultBmp;
//        }
//        public void Dispose()
//        {
//            // YOLO 模型生命周期由 YoloModelManager 管理,这里不需要额外释放
//        }
//    }
//}
//public DetectionResult Detect(Bitmap image)
//{
//    if (_yoloModel == null)
//        throw new InvalidOperationException("YoloDetector 未初始化或模型未加载。");
//    using (var skBitmap = CameraProcessor.ToSKBitmapFast(image))
//    using (var skImage = SKImage.FromBitmap(skBitmap))
//    {
//        //注意深拷贝浅拷贝的概念,复制的图片别忘了释放
//        var output = image.Clone();
//        if (skImage == null)
//            return new DetectionResult(false, "图像转换失败");
//        //var results = _yoloModel.RunObjectDetection(skImage, confidence: 0.4f, iou: 0.5f);
//        var predictions = _yoloModel.RunObjectDetection(
//            skImage,
//            confidence: _confidenceThreshold,
//            iou: _nmsThreshold
//        );
//        var ExistBool = predictions.FirstOrDefault(res => res.Label.Name.Equals("logo", StringComparison.OrdinalIgnoreCase));
//        if (ExistBool != null)
//        {
//            var box = ExistBool.BoundingBox;
//            var rect = new Rect(box.Left, box.Top, box.Width, box.Height);
//            //Cv2.Rectangle(output, rect, Scalar.Yellow, 2);
//            //Cv2.PutText(output, $"{logoResult.Label.Name}: {logoResult.Confidence:P2}", new CvPoint(rect.X, rect.Y - 10), HersheyFonts.HersheySimplex, 0.6, Scalar.Yellow, 2);
//        }
//        bool isOk = !predictions.Any(); // 没有检测结果为OK
//        string message = isOk ? "OK" : "NG";
//        //var boundingBoxes = predictions
//        //    .Select(p => new RectangleF(p.Rectangle.X, p.Rectangle.Y, p.Rectangle.Width, p.Rectangle.Height))
//        //    .ToList();
//        //Bitmap resultImage = DrawYoloPredictions(image, predictions);
//        //return new DetectionResult(isOk, message, 0, boundingBoxes, resultImage);
//    }
//}
//// 注意:如果你使用的是 YoloResult,请改为 IEnumerable     IEnumerable 
//private Bitmap DrawYoloPredictions(Bitmap originalImage, IEnumerable predictions)
//{
//    Bitmap resultBmp = (Bitmap)originalImage.Clone();
//    using (Graphics g = Graphics.FromImage(resultBmp))
//    {
//        Pen boxPen = new Pen(Color.Red, 3);
//        Font font = new Font("Arial", 12, FontStyle.Bold);
//        Brush brush = new SolidBrush(Color.Red);
//        foreach (var p in predictions)
//        {
//            Rectangle rect = new Rectangle(
//                (int)p.Rectangle.X,
//                (int)p.Rectangle.Y,
//                (int)p.Rectangle.Width,
//                (int)p.Rectangle.Height
//            );
//            g.DrawRectangle(boxPen, rect);
//            g.DrawString($"{p.Label} ({p.Confidence:P0})", font, brush, rect.X, rect.Y - 20);
//        }
//        boxPen.Dispose();
//        font.Dispose();
//        brush.Dispose();
//    }
//    return resultBmp;
//}
// 错误②:CS0246 解决方法:确保 YoloPrediction 的完整命名空间正确引用。
// 由于你的文件开头已经有了 `using YoloDotNet.Models;`
// 所以这里直接使用 `YoloPrediction` 应该是正确的,除非 `YoloPrediction` 不在该命名空间下。
// 如果问题依然存在,检查 YoloDotNet.Models 命名空间中 YoloPrediction 的具体定义。
//private Bitmap DrawYoloPredictions(Bitmap originalImage, IEnumerable predictions)
//{
//    Bitmap resultBmp = (Bitmap)originalImage.Clone();
//    using (Graphics g = Graphics.FromImage(resultBmp))
//    {
//        Pen boxPen = new Pen(Color.Red, 3);
//        Font font = new Font("Arial", 12, FontStyle.Bold);
//        Brush brush = new SolidBrush(Color.Red);
//        foreach (var p in predictions)
//        {
//            Rectangle rect = new Rectangle(
//                (int)p.Rectangle.X,
//                (int)p.Rectangle.Y,
//                (int)p.Rectangle.Width,
//                (int)p.Rectangle.Height
//            );
//            g.DrawRectangle(boxPen, rect);
//            g.DrawString($"{p.Label} ({p.Confidence:P0})", font, brush, rect.X, rect.Y - 20);
//        }
//        boxPen.Dispose();
//        font.Dispose();
//        brush.Dispose();
//    }
//    return resultBmp;
//}