use anyhow::{Result, anyhow};
use std::path::Path;
use std::sync::Arc;
use std::time::Instant;
use tracing::{info, warn, debug};

use crate::data::models::watermark::{
    WatermarkDetectionResult, WatermarkDetection, WatermarkDetectionConfig,
    DetectionMethod, BoundingBox, WatermarkType
};
use crate::data::repositories::material_repository::MaterialRepository;
use crate::infrastructure::ffmpeg_watermark::FFmpegWatermark;
use crate::infrastructure::monitoring::PERFORMANCE_MONITOR;

/// 水印检测服务
/// 遵循 Tauri 开发规范的业务逻辑层设计
pub struct WatermarkDetectionService;

impl WatermarkDetectionService {
    /// 检测视频中的水印
    pub async fn detect_watermarks_in_video(
        material_id: &str,
        video_path: &str,
        config: &WatermarkDetectionConfig,
        _repository: Arc<MaterialRepository>,
    ) -> Result<WatermarkDetectionResult> {
        let _timer = PERFORMANCE_MONITOR.start_operation("watermark_detection");
        let start_time = Instant::now();

        info!(
            material_id = %material_id,
            video_path = %video_path,
            "开始检测视频水印"
        );

        // 验证文件存在
        if !Path::new(video_path).exists() {
            return Err(anyhow!("视频文件不存在: {}", video_path));
        }

        // 获取视频信息
        let video_info = FFmpegWatermark::get_video_info(video_path)?;
        let frame_count = video_info.frame_count.unwrap_or(0);
        let duration = video_info.duration;

        debug!(
            material_id = %material_id,
            frame_count = frame_count,
            duration = duration,
            "视频信息获取完成"
        );

        let mut all_detections = Vec::new();
        let mut total_confidence = 0.0;
        let mut detection_count = 0;

        // 根据配置的采样率提取关键帧进行检测
        let sample_interval = config.frame_sample_rate.max(1);
        let sample_frames = Self::calculate_sample_frames(frame_count, sample_interval, duration);

        for (frame_index, timestamp) in sample_frames.iter().enumerate() {
            debug!(
                material_id = %material_id,
                frame_index = frame_index,
                timestamp = timestamp,
                "开始检测帧"
            );

            // 提取帧图像
            let frame_path = Self::extract_frame(video_path, *timestamp, material_id, frame_index)?;

            // 对每个检测方法进行检测
            for method in &config.methods {
                match Self::detect_watermarks_in_frame(
                    &frame_path,
                    method,
                    config,
                ).await {
                    Ok(detections) => {
                        for detection in detections {
                            all_detections.push(detection.clone());
                            total_confidence += detection.confidence;
                            detection_count += 1;
                        }
                    }
                    Err(e) => {
                        warn!(
                            material_id = %material_id,
                            method = ?method,
                            frame_index = frame_index,
                            error = %e,
                            "帧检测失败"
                        );
                    }
                }
            }

            // 清理临时帧文件
            let _ = std::fs::remove_file(&frame_path);
        }

        // 合并相似的检测结果
        let merged_detections = Self::merge_similar_detections(all_detections, 0.7);

        // 计算平均置信度
        let average_confidence = if detection_count > 0 {
            total_confidence / detection_count as f64
        } else {
            0.0
        };

        let processing_time = start_time.elapsed().as_millis() as u64;

        let result = WatermarkDetectionResult {
            id: uuid::Uuid::new_v4().to_string(),
            material_id: material_id.to_string(),
            detection_method: if config.methods.len() == 1 {
                config.methods[0].clone()
            } else {
                DetectionMethod::Combined
            },
            detections: merged_detections,
            confidence_score: average_confidence,
            processing_time_ms: processing_time,
            created_at: chrono::Utc::now(),
        };

        info!(
            material_id = %material_id,
            detection_count = result.detections.len(),
            confidence = result.confidence_score,
            processing_time_ms = processing_time,
            "水印检测完成"
        );

        Ok(result)
    }

    /// 检测图片中的水印
    pub async fn detect_watermarks_in_image(
        material_id: &str,
        image_path: &str,
        config: &WatermarkDetectionConfig,
    ) -> Result<WatermarkDetectionResult> {
        let _timer = PERFORMANCE_MONITOR.start_operation("watermark_detection_image");
        let start_time = Instant::now();

        info!(
            material_id = %material_id,
            image_path = %image_path,
            "开始检测图片水印"
        );

        // 验证文件存在
        if !Path::new(image_path).exists() {
            return Err(anyhow!("图片文件不存在: {}", image_path));
        }

        let mut all_detections = Vec::new();

        // 对每个检测方法进行检测
        for method in &config.methods {
            match Self::detect_watermarks_in_frame(
                image_path,
                method,
                config,
            ).await {
                Ok(detections) => {
                    all_detections.extend(detections);
                }
                Err(e) => {
                    warn!(
                        material_id = %material_id,
                        method = ?method,
                        error = %e,
                        "图片检测失败"
                    );
                }
            }
        }

        // 合并相似的检测结果
        let merged_detections = Self::merge_similar_detections(all_detections, 0.7);

        // 计算平均置信度
        let average_confidence = if !merged_detections.is_empty() {
            merged_detections.iter().map(|d| d.confidence).sum::<f64>() / merged_detections.len() as f64
        } else {
            0.0
        };

        let processing_time = start_time.elapsed().as_millis() as u64;

        let result = WatermarkDetectionResult {
            id: uuid::Uuid::new_v4().to_string(),
            material_id: material_id.to_string(),
            detection_method: if config.methods.len() == 1 {
                config.methods[0].clone()
            } else {
                DetectionMethod::Combined
            },
            detections: merged_detections,
            confidence_score: average_confidence,
            processing_time_ms: processing_time,
            created_at: chrono::Utc::now(),
        };

        info!(
            material_id = %material_id,
            detection_count = result.detections.len(),
            confidence = result.confidence_score,
            processing_time_ms = processing_time,
            "图片水印检测完成"
        );

        Ok(result)
    }

    /// 计算采样帧
    fn calculate_sample_frames(frame_count: u32, sample_interval: u32, duration: f64) -> Vec<f64> {
        let mut sample_frames = Vec::new();
        
        if frame_count == 0 || duration <= 0.0 {
            return sample_frames;
        }

        let fps = frame_count as f64 / duration;
        let total_samples = (frame_count / sample_interval).max(1);
        
        for i in 0..total_samples {
            let frame_index = i * sample_interval;
            let timestamp = frame_index as f64 / fps;
            if timestamp < duration {
                sample_frames.push(timestamp);
            }
        }

        // 确保至少有一帧
        if sample_frames.is_empty() {
            sample_frames.push(duration / 2.0); // 取中间帧
        }

        sample_frames
    }

    /// 提取视频帧
    fn extract_frame(
        video_path: &str,
        timestamp: f64,
        material_id: &str,
        frame_index: usize,
    ) -> Result<String> {
        let temp_dir = std::env::temp_dir();
        let frame_filename = format!("watermark_detection_{}_{}.jpg", material_id, frame_index);
        let frame_path = temp_dir.join(frame_filename);
        let frame_path_str = frame_path.to_string_lossy().to_string();

        // 使用FFmpeg提取帧
        FFmpegWatermark::extract_frame_at_timestamp(
            video_path,
            timestamp,
            &frame_path_str,
            1920, // 使用高分辨率以提高检测精度
            1080,
        )?;

        Ok(frame_path_str)
    }

    /// 在单帧中检测水印
    async fn detect_watermarks_in_frame(
        image_path: &str,
        method: &DetectionMethod,
        config: &WatermarkDetectionConfig,
    ) -> Result<Vec<WatermarkDetection>> {
        match method {
            DetectionMethod::TemplateMatching => {
                Self::template_matching_detection(image_path, config).await
            }
            DetectionMethod::EdgeDetection => {
                Self::edge_detection(image_path, config).await
            }
            DetectionMethod::FrequencyAnalysis => {
                Self::frequency_analysis_detection(image_path, config).await
            }
            DetectionMethod::TransparencyDetection => {
                Self::transparency_detection(image_path, config).await
            }
            DetectionMethod::Combined => {
                // 组合检测：运行所有方法并合并结果
                let mut all_detections = Vec::new();
                
                if let Ok(detections) = Self::template_matching_detection(image_path, config).await {
                    all_detections.extend(detections);
                }
                
                if let Ok(detections) = Self::edge_detection(image_path, config).await {
                    all_detections.extend(detections);
                }
                
                Ok(all_detections)
            }
        }
    }

    /// 模板匹配检测
    async fn template_matching_detection(
        image_path: &str,
        _config: &WatermarkDetectionConfig,
    ) -> Result<Vec<WatermarkDetection>> {
        // TODO: 实现OpenCV模板匹配算法
        // 这里先返回模拟结果，后续需要集成OpenCV
        debug!("执行模板匹配检测: {}", image_path);
        
        // 模拟检测结果
        let detections = vec![
            WatermarkDetection {
                region: BoundingBox {
                    x: 100,
                    y: 100,
                    width: 200,
                    height: 50,
                },
                confidence: 0.85,
                watermark_type: Some(WatermarkType::Image),
                template_id: None,
                description: Some("模板匹配检测到的水印".to_string()),
            }
        ];
        
        Ok(detections)
    }

    /// 边缘检测
    async fn edge_detection(
        image_path: &str,
        _config: &WatermarkDetectionConfig,
    ) -> Result<Vec<WatermarkDetection>> {
        // TODO: 实现边缘检测算法
        debug!("执行边缘检测: {}", image_path);
        
        // 模拟检测结果
        Ok(vec![])
    }

    /// 频域分析检测
    async fn frequency_analysis_detection(
        image_path: &str,
        _config: &WatermarkDetectionConfig,
    ) -> Result<Vec<WatermarkDetection>> {
        // TODO: 实现频域分析算法
        debug!("执行频域分析检测: {}", image_path);
        
        // 模拟检测结果
        Ok(vec![])
    }

    /// 透明度检测
    async fn transparency_detection(
        image_path: &str,
        _config: &WatermarkDetectionConfig,
    ) -> Result<Vec<WatermarkDetection>> {
        // TODO: 实现透明度检测算法
        debug!("执行透明度检测: {}", image_path);
        
        // 模拟检测结果
        Ok(vec![])
    }

    /// 合并相似的检测结果
    fn merge_similar_detections(
        detections: Vec<WatermarkDetection>,
        similarity_threshold: f64,
    ) -> Vec<WatermarkDetection> {
        if detections.is_empty() {
            return detections;
        }

        let mut merged = Vec::new();
        let mut used = vec![false; detections.len()];

        for i in 0..detections.len() {
            if used[i] {
                continue;
            }

            let mut group = vec![detections[i].clone()];
            used[i] = true;

            // 查找相似的检测结果
            for j in (i + 1)..detections.len() {
                if used[j] {
                    continue;
                }

                let similarity = Self::calculate_region_similarity(
                    &detections[i].region,
                    &detections[j].region,
                );

                if similarity >= similarity_threshold {
                    group.push(detections[j].clone());
                    used[j] = true;
                }
            }

            // 合并组内的检测结果
            if group.len() == 1 {
                merged.push(group[0].clone());
            } else {
                merged.push(Self::merge_detection_group(group));
            }
        }

        merged
    }

    /// 计算两个区域的相似度
    fn calculate_region_similarity(region1: &BoundingBox, region2: &BoundingBox) -> f64 {
        // 计算重叠区域
        let x1 = region1.x.max(region2.x);
        let y1 = region1.y.max(region2.y);
        let x2 = (region1.x + region1.width).min(region2.x + region2.width);
        let y2 = (region1.y + region1.height).min(region2.y + region2.height);

        if x2 <= x1 || y2 <= y1 {
            return 0.0; // 没有重叠
        }

        let overlap_area = (x2 - x1) * (y2 - y1);
        let area1 = region1.width * region1.height;
        let area2 = region2.width * region2.height;
        let union_area = area1 + area2 - overlap_area;

        if union_area == 0 {
            return 0.0;
        }

        overlap_area as f64 / union_area as f64
    }

    /// 合并检测组
    fn merge_detection_group(group: Vec<WatermarkDetection>) -> WatermarkDetection {
        if group.is_empty() {
            panic!("检测组不能为空");
        }

        if group.len() == 1 {
            return group[0].clone();
        }

        // 计算边界框的并集
        let min_x = group.iter().map(|d| d.region.x).min().unwrap();
        let min_y = group.iter().map(|d| d.region.y).min().unwrap();
        let max_x = group.iter().map(|d| d.region.x + d.region.width).max().unwrap();
        let max_y = group.iter().map(|d| d.region.y + d.region.height).max().unwrap();

        // 计算平均置信度
        let avg_confidence = group.iter().map(|d| d.confidence).sum::<f64>() / group.len() as f64;

        WatermarkDetection {
            region: BoundingBox {
                x: min_x,
                y: min_y,
                width: max_x - min_x,
                height: max_y - min_y,
            },
            confidence: avg_confidence,
            watermark_type: group[0].watermark_type.clone(),
            template_id: group[0].template_id.clone(),
            description: Some(format!("合并了{}个检测结果", group.len())),
        }
    }
}
