use anyhow::{anyhow, Result};
use reqwest::Client;
use std::time::Duration;
use std::path::{Path, PathBuf};
use std::fs;
use base64::prelude::*;
use uuid::Uuid;
use tokio::time::sleep;
use image::{ImageFormat};

use crate::data::models::image_editing::{
    ImageEditingConfig, ImageEditingRequest, ImageEditingResponse, ImageEditingTask,
    BatchImageEditingTask, ImageEditingTaskStatus, ImageEditingParams,
};

/// 图像编辑服务
/// 基于火山云SeedEdit 3.0 API实现图像编辑功能
#[derive(Clone)]
pub struct ImageEditingService {
    client: Client,
    config: ImageEditingConfig,
}

impl ImageEditingService {
    /// 创建新的图像编辑服务实例
    pub fn new() -> Self {
        let client = Client::builder()
            .timeout(Duration::from_secs(120))
            .build()
            .expect("Failed to create HTTP client");

        Self {
            client,
            config: ImageEditingConfig::default(),
        }
    }

    /// 支持的图片格式列表
    const SUPPORTED_FORMATS: &'static [&'static str] = &[
        "jpg", "jpeg", "png", "webp", "bmp", "tiff", "gif", "ico", "tga"
    ];

    /// 原生支持的格式（无需转换）
    const NATIVE_FORMATS: &'static [&'static str] = &["jpg", "jpeg", "png"];

    /// 检查文件是否为支持的图片格式
    fn is_supported_image_format(file_path: &Path) -> bool {
        if let Some(extension) = file_path.extension() {
            let ext = extension.to_string_lossy().to_lowercase();
            Self::SUPPORTED_FORMATS.contains(&ext.as_str())
        } else {
            false
        }
    }

    /// 检查文件是否需要格式转换
    fn needs_format_conversion(file_path: &Path) -> bool {
        if let Some(extension) = file_path.extension() {
            let ext = extension.to_string_lossy().to_lowercase();
            Self::SUPPORTED_FORMATS.contains(&ext.as_str()) &&
            !Self::NATIVE_FORMATS.contains(&ext.as_str())
        } else {
            false
        }
    }

    /// 获取图片格式
    fn get_image_format(file_path: &Path) -> Option<ImageFormat> {
        if let Some(extension) = file_path.extension() {
            let ext = extension.to_string_lossy().to_lowercase();
            match ext.as_str() {
                "jpg" | "jpeg" => Some(ImageFormat::Jpeg),
                "png" => Some(ImageFormat::Png),
                "webp" => Some(ImageFormat::WebP),
                "bmp" => Some(ImageFormat::Bmp),
                "tiff" | "tif" => Some(ImageFormat::Tiff),
                "gif" => Some(ImageFormat::Gif),
                "ico" => Some(ImageFormat::Ico),
                "tga" => Some(ImageFormat::Tga),
                _ => None,
            }
        } else {
            None
        }
    }

    /// 确定转换目标格式
    fn determine_target_format(source_format: ImageFormat) -> ImageFormat {
        match source_format {
            // 有损格式转为JPEG
            ImageFormat::WebP | ImageFormat::Jpeg => ImageFormat::Jpeg,
            // 无损格式转为PNG
            ImageFormat::Png | ImageFormat::Bmp | ImageFormat::Tiff |
            ImageFormat::Gif | ImageFormat::Ico | ImageFormat::Tga => ImageFormat::Png,
            // 其他格式默认转为PNG
            _ => ImageFormat::Png,
        }
    }

    /// 获取格式对应的文件扩展名
    fn get_format_extension(format: ImageFormat) -> &'static str {
        match format {
            ImageFormat::Jpeg => "jpg",
            ImageFormat::Png => "png",
            _ => "png", // 默认使用PNG
        }
    }

    /// 转换图片格式
    async fn convert_image_format(
        input_path: &Path,
        output_dir: &Path,
    ) -> Result<PathBuf> {
        println!("🔄 开始转换图片格式: {}", input_path.display());

        // 检查输入文件是否存在
        if !input_path.exists() {
            return Err(anyhow!("输入文件不存在: {}", input_path.display()));
        }

        // 获取源格式
        let source_format = Self::get_image_format(input_path)
            .ok_or_else(|| anyhow!("不支持的图片格式: {}", input_path.display()))?;

        // 确定目标格式
        let target_format = Self::determine_target_format(source_format);
        let target_extension = Self::get_format_extension(target_format);

        // 生成输出文件路径
        let file_stem = input_path.file_stem()
            .ok_or_else(|| anyhow!("无法获取文件名"))?;
        let output_filename = format!("{}_converted.{}",
            file_stem.to_string_lossy(), target_extension);
        let output_path = output_dir.join(output_filename);

        // 确保输出目录存在
        tokio::fs::create_dir_all(output_dir).await
            .map_err(|e| anyhow!("创建输出目录失败: {}", e))?;

        // 读取并转换图片
        let img = image::open(input_path)
            .map_err(|e| anyhow!("读取图片失败: {}", e))?;

        // 保存转换后的图片
        img.save_with_format(&output_path, target_format)
            .map_err(|e| anyhow!("保存转换后的图片失败: {}", e))?;

        println!("✅ 图片格式转换完成: {} -> {}",
            input_path.display(), output_path.display());

        Ok(output_path)
    }

    /// 获取或创建临时转换目录
    async fn get_temp_conversion_dir() -> Result<PathBuf> {
        let temp_dir = std::env::temp_dir().join("mixvideo_image_conversion");
        tokio::fs::create_dir_all(&temp_dir).await
            .map_err(|e| anyhow!("创建临时转换目录失败: {}", e))?;
        Ok(temp_dir)
    }

    /// 清理临时转换文件
    async fn cleanup_converted_files(temp_files: &[PathBuf]) -> Result<()> {
        for file_path in temp_files {
            if file_path.exists() {
                if let Err(e) = tokio::fs::remove_file(file_path).await {
                    println!("⚠️ 清理临时文件失败: {} - {}", file_path.display(), e);
                }
            }
        }
        Ok(())
    }

    /// 使用自定义配置创建图像编辑服务
    pub fn with_config(config: ImageEditingConfig) -> Self {
        let client = Client::builder()
            .timeout(Duration::from_secs(config.timeout))
            .build()
            .expect("Failed to create HTTP client");

        Self { client, config }
    }

    /// 设置API密钥
    pub fn set_api_key(&mut self, api_key: String) {
        self.config.api_key = api_key;
    }

    /// 验证图像文件格式（用于Base64编码，只接受原生支持的格式）
    fn validate_image_format(file_path: &Path) -> Result<()> {
        let extension = file_path
            .extension()
            .and_then(|ext| ext.to_str())
            .ok_or_else(|| anyhow!("无法获取文件扩展名"))?
            .to_lowercase();

        match extension.as_str() {
            "jpg" | "jpeg" | "png" => Ok(()),
            _ => Err(anyhow!("文件格式错误: {}，此时应该已经转换为 JPEG 或 PNG 格式", extension)),
        }
    }

    /// 将图像文件转换为Base64编码
    async fn image_to_base64(file_path: &Path) -> Result<String> {
        Self::validate_image_format(file_path)?;

        let image_data = tokio::fs::read(file_path).await
            .map_err(|e| anyhow!("读取图像文件失败: {}", e))?;

        // 检查文件大小（10MB限制）
        if image_data.len() > 10 * 1024 * 1024 {
            return Err(anyhow!("图像文件过大，超过10MB限制"));
        }

        let extension = file_path
            .extension()
            .and_then(|ext| ext.to_str())
            .unwrap_or("jpeg")
            .to_lowercase();

        let mime_type = match extension.as_str() {
            "png" => "image/png",
            _ => "image/jpeg",
        };

        let base64_data = BASE64_STANDARD.encode(&image_data);
        Ok(format!("data:{};base64,{}", mime_type, base64_data))
    }

    /// 调用图像编辑API
    async fn call_api(&self, request: &ImageEditingRequest) -> Result<ImageEditingResponse> {
        if self.config.api_key.is_empty() {
            return Err(anyhow!("API密钥未设置"));
        }

        let mut retries = 0;
        loop {
            let response = self
                .client
                .post(&self.config.api_url)
                .header("Content-Type", "application/json")
                .header("Authorization", format!("Bearer {}", self.config.api_key))
                .json(request)
                .send()
                .await;

            match response {
                Ok(resp) => {
                    if resp.status().is_success() {
                        let api_response: ImageEditingResponse = resp.json().await
                            .map_err(|e| anyhow!("解析API响应失败: {}", e))?;

                        // 检查API响应中的错误
                        if let Some(error) = &api_response.error {
                            return Err(anyhow!("API错误: {} - {}", error.code, error.message));
                        }

                        return Ok(api_response);
                    } else {
                        let status = resp.status();
                        let error_text = resp.text().await.unwrap_or_else(|_| "未知错误".to_string());
                        if retries >= self.config.max_retries {
                            return Err(anyhow!("API请求失败: HTTP {} - {}", status, error_text));
                        }
                    }
                }
                Err(e) => {
                    if retries >= self.config.max_retries {
                        return Err(anyhow!("网络请求失败: {}", e));
                    }
                }
            }

            retries += 1;
            println!("API请求失败，{}秒后重试 ({}/{})", self.config.retry_delay, retries, self.config.max_retries);
            sleep(Duration::from_secs(self.config.retry_delay)).await;
        }
    }

    /// 下载生成的图像
    async fn download_image(&self, url: &str, output_path: &Path) -> Result<()> {
        let response = self.client.get(url).send().await
            .map_err(|e| anyhow!("下载图像失败: {}", e))?;

        if !response.status().is_success() {
            return Err(anyhow!("下载图像失败: HTTP {}", response.status()));
        }

        let image_data = response.bytes().await
            .map_err(|e| anyhow!("读取图像数据失败: {}", e))?;

        // 确保输出目录存在
        if let Some(parent) = output_path.parent() {
            tokio::fs::create_dir_all(parent).await
                .map_err(|e| anyhow!("创建输出目录失败: {}", e))?;
        }

        tokio::fs::write(output_path, image_data).await
            .map_err(|e| anyhow!("保存图像文件失败: {}", e))?;

        Ok(())
    }

    /// 编辑单张图像
    pub async fn edit_single_image(
        &self,
        input_path: &Path,
        output_path: &Path,
        prompt: &str,
        params: &ImageEditingParams,
    ) -> Result<ImageEditingResponse> {
        println!("🎨 开始编辑图像: {}", input_path.display());
        println!("提示词: {}", prompt);

        // 转换图像为Base64
        let base64_image = Self::image_to_base64(input_path).await?;

        // 构建请求
        let mut request = ImageEditingRequest::default();
        request.model = self.config.model_id.clone();
        request.prompt = prompt.to_string();
        request.image = base64_image;
        request.guidance_scale = Some(params.guidance_scale);
        request.seed = Some(params.seed);
        request.watermark = Some(params.watermark);
        request.response_format = Some(params.response_format.clone());
        request.size = Some(params.size.clone());

        // 调用API
        let response = self.call_api(&request).await?;

        // 下载生成的图像
        if let Some(data) = response.data.first() {
            if let Some(url) = &data.url {
                self.download_image(url, output_path).await?;
                println!("✅ 图像编辑完成: {}", output_path.display());
            } else if let Some(b64_data) = &data.b64_json {
                // 处理Base64格式的响应
                let image_data = BASE64_STANDARD.decode(b64_data)
                    .map_err(|e| anyhow!("解码Base64图像数据失败: {}", e))?;

                if let Some(parent) = output_path.parent() {
                    tokio::fs::create_dir_all(parent).await
                        .map_err(|e| anyhow!("创建输出目录失败: {}", e))?;
                }

                tokio::fs::write(output_path, image_data).await
                    .map_err(|e| anyhow!("保存图像文件失败: {}", e))?;

                println!("✅ 图像编辑完成: {}", output_path.display());
            } else {
                return Err(anyhow!("API响应中没有图像数据"));
            }
        } else {
            return Err(anyhow!("API响应中没有数据"));
        }

        Ok(response)
    }

    /// 获取文件夹中的所有图像文件（包括需要转换的格式）
    fn get_image_files(folder_path: &Path) -> Result<Vec<PathBuf>> {
        let mut image_files = Vec::new();

        if !folder_path.exists() {
            return Err(anyhow!("文件夹不存在: {}", folder_path.display()));
        }

        if !folder_path.is_dir() {
            return Err(anyhow!("路径不是文件夹: {}", folder_path.display()));
        }

        let entries = fs::read_dir(folder_path)
            .map_err(|e| anyhow!("读取文件夹失败: {}", e))?;

        for entry in entries {
            let entry = entry.map_err(|e| anyhow!("读取文件夹条目失败: {}", e))?;
            let path = entry.path();

            if path.is_file() && Self::is_supported_image_format(&path) {
                image_files.push(path);
            }
        }

        if image_files.is_empty() {
            return Err(anyhow!("文件夹中没有找到支持的图像文件"));
        }

        image_files.sort();

        // 统计不同格式的文件数量
        let mut format_counts = std::collections::HashMap::new();
        for file in &image_files {
            if let Some(ext) = file.extension() {
                let ext_str = ext.to_string_lossy().to_lowercase();
                *format_counts.entry(ext_str).or_insert(0) += 1;
            }
        }

        println!("📊 发现的图片格式统计:");
        for (format, count) in format_counts {
            println!("  {} 格式: {} 个文件", format.to_uppercase(), count);
        }

        Ok(image_files)
    }

    /// 生成输出文件名
    fn generate_output_filename(input_path: &Path, output_folder: &Path) -> PathBuf {
        let file_stem = input_path.file_stem().unwrap_or_default();
        let extension = input_path.extension().unwrap_or_default();
        let timestamp = chrono::Utc::now().format("%Y%m%d_%H%M%S");

        let output_filename = format!("{}_{}.{}",
            file_stem.to_string_lossy(),
            timestamp,
            extension.to_string_lossy()
        );

        output_folder.join(output_filename)
    }

    /// 批量编辑图像
    pub async fn edit_batch_images(
        &self,
        input_folder: &Path,
        output_folder: &Path,
        prompt: &str,
        params: &ImageEditingParams,
        progress_callback: Option<Box<dyn Fn(f32, String) + Send + Sync>>,
    ) -> Result<BatchImageEditingTask> {
        println!("🎨 开始批量编辑图像");
        println!("输入文件夹: {}", input_folder.display());
        println!("输出文件夹: {}", output_folder.display());
        println!("提示词: {}", prompt);

        // 获取所有图像文件
        let image_files = Self::get_image_files(input_folder)?;
        println!("找到 {} 个图像文件", image_files.len());

        // 创建输出文件夹
        tokio::fs::create_dir_all(output_folder).await
            .map_err(|e| anyhow!("创建输出文件夹失败: {}", e))?;

        // 创建批量任务
        let task_id = Uuid::new_v4().to_string();
        let mut batch_task = BatchImageEditingTask::new(
            task_id,
            input_folder.to_string_lossy().to_string(),
            output_folder.to_string_lossy().to_string(),
            prompt.to_string(),
            ImageEditingRequest {
                model: self.config.model_id.clone(),
                prompt: prompt.to_string(),
                image: String::new(), // 每个任务单独设置
                response_format: Some(params.response_format.clone()),
                size: Some(params.size.clone()),
                seed: Some(params.seed),
                guidance_scale: Some(params.guidance_scale),
                watermark: Some(params.watermark),
            },
        );

        // 为每个图像文件创建单独的任务
        for (_index, input_file) in image_files.iter().enumerate() {
            let _output_file = Self::generate_output_filename(input_file, output_folder);
            let individual_task = ImageEditingTask::new(
                Uuid::new_v4().to_string(),
                input_file.to_string_lossy().to_string(),
                prompt.to_string(),
                batch_task.request_params.clone(),
            );
            batch_task.add_task(individual_task);
        }

        batch_task.status = ImageEditingTaskStatus::Processing;

        // 处理每个图像
        for (index, input_file) in image_files.iter().enumerate() {
            let output_file = Self::generate_output_filename(input_file, output_folder);

            // 更新进度
            let progress = (index as f32) / (image_files.len() as f32);
            if let Some(ref callback) = progress_callback {
                callback(progress, format!("正在处理: {}", input_file.file_name().unwrap_or_default().to_string_lossy()));
            }

            // 更新任务状态
            if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                task.set_processing();
            }

            // 处理单个图像
            match self.edit_single_image(input_file, &output_file, prompt, params).await {
                Ok(response) => {
                    if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                        task.set_completed(output_file.to_string_lossy().to_string(), response);
                    }
                    println!("✅ 完成: {}", input_file.file_name().unwrap_or_default().to_string_lossy());
                }
                Err(e) => {
                    if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                        task.set_failed(e.to_string());
                    }
                    println!("❌ 失败: {} - {}", input_file.file_name().unwrap_or_default().to_string_lossy(), e);
                }
            }

            // 更新批量任务进度
            batch_task.update_progress();
        }

        // 最终进度更新
        if let Some(ref callback) = progress_callback {
            callback(1.0, "批量处理完成".to_string());
        }

        println!("🎉 批量编辑完成！");
        println!("总计: {} 个文件", batch_task.total_images);
        println!("成功: {} 个文件", batch_task.successful_images);
        println!("失败: {} 个文件", batch_task.failed_images);

        Ok(batch_task)
    }

    /// 批量编辑图像（带任务状态更新回调）
    pub async fn edit_batch_images_with_callback(
        &self,
        input_folder: &Path,
        output_folder: &Path,
        prompt: &str,
        params: &ImageEditingParams,
        task_update_callback: Option<Box<dyn Fn(BatchImageEditingTask) + Send + Sync>>,
    ) -> Result<BatchImageEditingTask> {
        println!("🎨 开始批量编辑图像（带回调）");
        println!("输入文件夹: {}", input_folder.display());
        println!("输出文件夹: {}", output_folder.display());
        println!("提示词: {}", prompt);

        // 获取所有图像文件
        let image_files = Self::get_image_files(input_folder)?;
        println!("找到 {} 个图像文件", image_files.len());

        // 创建输出文件夹
        tokio::fs::create_dir_all(output_folder).await
            .map_err(|e| anyhow!("创建输出文件夹失败: {}", e))?;

        // 创建批量任务
        let task_id = Uuid::new_v4().to_string();
        let mut batch_task = BatchImageEditingTask::new(
            task_id,
            input_folder.to_string_lossy().to_string(),
            output_folder.to_string_lossy().to_string(),
            prompt.to_string(),
            ImageEditingRequest {
                model: self.config.model_id.clone(),
                prompt: prompt.to_string(),
                image: String::new(), // 每个任务单独设置
                response_format: Some(params.response_format.clone()),
                size: Some(params.size.clone()),
                seed: Some(params.seed),
                guidance_scale: Some(params.guidance_scale),
                watermark: Some(params.watermark),
            },
        );

        // 为每个图像文件创建单独的任务
        for (_index, input_file) in image_files.iter().enumerate() {
            let _output_file = Self::generate_output_filename(input_file, output_folder);
            let individual_task = ImageEditingTask::new(
                Uuid::new_v4().to_string(),
                input_file.to_string_lossy().to_string(),
                prompt.to_string(),
                batch_task.request_params.clone(),
            );
            batch_task.add_task(individual_task);
        }

        batch_task.status = ImageEditingTaskStatus::Processing;

        // 初始回调，通知任务已开始
        if let Some(ref callback) = task_update_callback {
            callback(batch_task.clone());
        }

        // 创建临时转换目录
        let temp_conversion_dir = Self::get_temp_conversion_dir().await?;
        let mut converted_files = Vec::new();

        // 处理每个图像
        for (index, input_file) in image_files.iter().enumerate() {
            let output_file = Self::generate_output_filename(input_file, output_folder);

            // 更新任务状态
            if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                task.set_processing();
            }

            // 检查是否需要格式转换
            let actual_input_file = if Self::needs_format_conversion(input_file) {
                println!("🔄 需要转换格式: {}", input_file.display());
                match Self::convert_image_format(input_file, &temp_conversion_dir).await {
                    Ok(converted_path) => {
                        converted_files.push(converted_path.clone());
                        converted_path
                    }
                    Err(e) => {
                        println!("❌ 格式转换失败: {} - {}", input_file.display(), e);
                        if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                            task.set_failed(format!("格式转换失败: {}", e));
                        }
                        batch_task.update_progress();
                        if let Some(ref callback) = task_update_callback {
                            callback(batch_task.clone());
                        }
                        continue;
                    }
                }
            } else {
                input_file.clone()
            };

            // 处理单个图像
            match self.edit_single_image(&actual_input_file, &output_file, prompt, params).await {
                Ok(response) => {
                    if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                        task.set_completed(output_file.to_string_lossy().to_string(), response);
                    }
                    println!("✅ 完成: {}", input_file.file_name().unwrap_or_default().to_string_lossy());
                }
                Err(e) => {
                    if let Some(task) = batch_task.individual_tasks.get_mut(index) {
                        task.set_failed(e.to_string());
                    }
                    println!("❌ 失败: {} - {}", input_file.file_name().unwrap_or_default().to_string_lossy(), e);
                }
            }

            // 更新批量任务进度
            batch_task.update_progress();

            // 每处理完一个图像就回调更新状态
            if let Some(ref callback) = task_update_callback {
                callback(batch_task.clone());
            }
        }

        // 清理临时转换文件
        if !converted_files.is_empty() {
            println!("🧹 清理 {} 个临时转换文件", converted_files.len());
            if let Err(e) = Self::cleanup_converted_files(&converted_files).await {
                println!("⚠️ 清理临时文件时出错: {}", e);
            }
        }

        println!("🎉 批量编辑完成！");
        println!("总计: {} 个文件", batch_task.total_images);
        println!("成功: {} 个文件", batch_task.successful_images);
        println!("失败: {} 个文件", batch_task.failed_images);

        // 最终回调
        if let Some(ref callback) = task_update_callback {
            callback(batch_task.clone());
        }

        Ok(batch_task)
    }

    /// 创建编辑任务（用于异步处理）
    pub async fn create_edit_task(
        &self,
        input_path: &Path,
        _output_path: &Path,
        prompt: &str,
        params: &ImageEditingParams,
    ) -> Result<ImageEditingTask> {
        let task_id = Uuid::new_v4().to_string();
        let request = ImageEditingRequest {
            model: self.config.model_id.clone(),
            prompt: prompt.to_string(),
            image: String::new(), // 稍后设置
            response_format: Some(params.response_format.clone()),
            size: Some(params.size.clone()),
            seed: Some(params.seed),
            guidance_scale: Some(params.guidance_scale),
            watermark: Some(params.watermark),
        };

        let task = ImageEditingTask::new(
            task_id,
            input_path.to_string_lossy().to_string(),
            prompt.to_string(),
            request,
        );

        Ok(task)
    }

    /// 执行编辑任务
    pub async fn execute_task(&self, task: &mut ImageEditingTask) -> Result<()> {
        task.set_processing();

        let input_path = Path::new(&task.input_image_path);
        let output_path = if let Some(ref output) = task.output_image_path {
            Path::new(output).to_path_buf()
        } else {
            // 生成默认输出路径
            let parent = input_path.parent().unwrap_or(Path::new("."));
            Self::generate_output_filename(input_path, parent)
        };

        let params = ImageEditingParams {
            guidance_scale: task.request_params.guidance_scale.unwrap_or(5.5),
            seed: task.request_params.seed.unwrap_or(-1),
            watermark: task.request_params.watermark.unwrap_or(false),
            response_format: task.request_params.response_format.clone().unwrap_or_else(|| "url".to_string()),
            size: task.request_params.size.clone().unwrap_or_else(|| "adaptive".to_string()),
        };

        match self.edit_single_image(input_path, &output_path, &task.prompt, &params).await {
            Ok(response) => {
                task.set_completed(output_path.to_string_lossy().to_string(), response);
                Ok(())
            }
            Err(e) => {
                task.set_failed(e.to_string());
                Err(e)
            }
        }
    }
}
