use anyhow::{Result, anyhow};
use std::path::Path;
use crate::data::models::model::{
    Model, ModelPhoto, CreateModelRequest, UpdateModelRequest,
    ModelQueryParams, Gender, PhotoType, ModelStatus
};
use crate::data::repositories::model_repository::ModelRepository;
use crate::business::services::cloud_upload_service::CloudUploadService;

/// 模特业务服务
/// 遵循 Tauri 开发规范的业务逻辑层设计
pub struct ModelService;

impl ModelService {
    /// 创建模特
    pub fn create_model(
        repository: &ModelRepository,
        request: CreateModelRequest,
    ) -> Result<Model> {
        // 创建模特实例
        let mut model = Model::new(request.name, request.gender);
        
        // 设置可选字段
        if let Some(stage_name) = request.stage_name {
            model.stage_name = Some(stage_name);
        }
        
        if let Some(age) = request.age {
            model.age = Some(age);
        }
        
        if let Some(height) = request.height {
            model.height = Some(height);
        }
        
        if let Some(weight) = request.weight {
            model.weight = Some(weight);
        }
        
        if let Some(measurements) = request.measurements {
            model.measurements = Some(measurements);
        }
        
        if let Some(description) = request.description {
            model.description = Some(description);
        }
        
        if let Some(tags) = request.tags {
            model.tags = tags;
        }
        
        if let Some(contact_info) = request.contact_info {
            model.contact_info = Some(contact_info);
        }
        
        if let Some(social_media) = request.social_media {
            model.social_media = Some(social_media);
        }

        // 验证模特数据
        model.validate().map_err(|e| anyhow!("验证失败: {}", e))?;

        // 保存到数据库
        repository.create(&model)
            .map_err(|e| anyhow!("创建模特失败: {}", e))?;

        Ok(model)
    }

    /// 获取模特详情
    pub fn get_model_by_id(
        repository: &ModelRepository,
        id: &str,
    ) -> Result<Option<Model>> {
        // 使用 get_basic_by_id 避免死锁问题
        // 在MaterialCard等组件中只需要基本信息，不需要照片
        repository.get_basic_by_id(id)
            .map_err(|e| anyhow!("获取模特详情失败: {}", e))
    }

    /// 获取所有模特
    pub fn get_all_models(
        repository: &ModelRepository,
    ) -> Result<Vec<Model>> {
        println!("ModelService::get_all_models 开始执行");
        let result = repository.get_all()
            .map_err(|e| {
                println!("repository.get_all() 失败: {}", e);
                anyhow!("获取模特列表失败: {}", e)
            });
        println!("ModelService::get_all_models 执行完成，结果: {:?}", result.is_ok());
        result
    }

    /// 搜索模特
    pub fn search_models(
        repository: &ModelRepository,
        params: ModelQueryParams,
    ) -> Result<Vec<Model>> {
        repository.search(&params)
            .map_err(|e| anyhow!("搜索模特失败: {}", e))
    }

    /// 更新模特信息
    pub fn update_model(
        repository: &ModelRepository,
        id: &str,
        request: UpdateModelRequest,
    ) -> Result<Model> {
        // 获取现有模特基本信息（避免死锁）
        let mut model = repository.get_basic_by_id(id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", id))?;

        // 更新字段
        if let Some(name) = request.name {
            model.name = name;
        }
        
        if request.stage_name.is_some() {
            model.stage_name = request.stage_name;
        }
        
        if request.age.is_some() {
            model.age = request.age;
        }
        
        if request.height.is_some() {
            model.height = request.height;
        }
        
        if request.weight.is_some() {
            model.weight = request.weight;
        }
        
        if request.measurements.is_some() {
            model.measurements = request.measurements;
        }
        
        if request.description.is_some() {
            model.description = request.description;
        }
        
        if let Some(tags) = request.tags {
            model.tags = tags;
        }
        
        if request.contact_info.is_some() {
            model.contact_info = request.contact_info;
        }
        
        if request.social_media.is_some() {
            model.social_media = request.social_media;
        }
        
        if let Some(status) = request.status {
            model.status = status;
        }
        
        if request.rating.is_some() {
            model.rating = request.rating;
        }

        // 更新时间戳
        model.updated_at = chrono::Utc::now();

        // 验证更新后的数据
        model.validate().map_err(|e| anyhow!("验证失败: {}", e))?;

        // 保存到数据库
        repository.update(&model)
            .map_err(|e| anyhow!("更新模特失败: {}", e))?;

        // 不加载照片信息，避免死锁
        // 前端会在更新成功后重新刷新列表
        model.photos = Vec::new();

        Ok(model)
    }

    /// 删除模特
    pub fn delete_model(
        repository: &ModelRepository,
        id: &str,
    ) -> Result<()> {
        println!("ModelService::delete_model 开始执行，ID: {}", id);

        // 直接执行删除操作，不需要先检查是否存在
        // 如果模特不存在，UPDATE 语句会返回 0 行受影响，这是正常的
        println!("执行软删除操作...");
        repository.delete(id)
            .map_err(|e| {
                println!("repository.delete 失败: {}", e);
                anyhow!("删除模特失败: {}", e)
            })?;

        println!("ModelService::delete_model 执行成功");
        Ok(())
    }

    /// 永久删除模特
    pub fn delete_model_permanently(
        repository: &ModelRepository,
        id: &str,
    ) -> Result<()> {
        // 检查模特是否存在
        let _model = repository.get_by_id(id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", id))?;

        // 物理删除模特
        repository.delete_permanently(id)
            .map_err(|e| anyhow!("永久删除模特失败: {}", e))?;

        Ok(())
    }

    /// 添加模特照片
    pub fn add_model_photo(
        repository: &ModelRepository,
        model_id: &str,
        file_path: String,
        photo_type: PhotoType,
        description: Option<String>,
        tags: Option<Vec<String>>,
    ) -> Result<ModelPhoto> {
        // 检查模特是否存在
        let _model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 验证文件路径
        let path = Path::new(&file_path);
        if !path.exists() {
            return Err(anyhow!("文件不存在: {}", file_path));
        }

        // 获取文件信息
        let metadata = std::fs::metadata(&file_path)
            .map_err(|e| anyhow!("获取文件信息失败: {}", e))?;
        
        let file_size = metadata.len();
        let file_name = path.file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("unknown")
            .to_string();

        // 创建照片对象
        let mut photo = ModelPhoto::new(
            model_id.to_string(),
            file_path,
            file_name,
            file_size,
            photo_type,
        );

        if let Some(desc) = description {
            photo.description = Some(desc);
        }

        if let Some(photo_tags) = tags {
            photo.tags = photo_tags;
        }

        // 保存到数据库
        repository.add_photo(&photo)
            .map_err(|e| anyhow!("添加照片失败: {}", e))?;

        Ok(photo)
    }

    /// 添加模特照片（上传到云端）
    pub async fn add_model_photo_with_cloud_upload(
        repository: &ModelRepository,
        model_id: &str,
        file_path: String,
        photo_type: PhotoType,
        description: Option<String>,
        tags: Option<Vec<String>>,
    ) -> Result<ModelPhoto> {
        // 检查模特是否存在
        let _model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 验证文件路径
        let path = Path::new(&file_path);
        if !path.exists() {
            return Err(anyhow!("文件不存在: {}", file_path));
        }

        // 获取文件信息
        let metadata = std::fs::metadata(&file_path)
            .map_err(|e| anyhow!("获取文件信息失败: {}", e))?;

        let file_size = metadata.len();
        let file_name = path.file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("unknown")
            .to_string();

        println!("📤 正在上传模特照片到云存储: {}", file_path);

        // 上传到云存储
        let upload_service = CloudUploadService::new();
        let remote_key = format!("models/photos/{}/{}", model_id, file_name);

        let upload_result = upload_service.upload_file(&file_path, Some(remote_key), None).await
            .map_err(|e| anyhow!("上传文件失败: {}", e))?;

        if !upload_result.success {
            let error_msg = upload_result.error_message
                .unwrap_or_else(|| "未知上传错误".to_string());
            return Err(anyhow!("照片上传失败: {}", error_msg));
        }

        // 获取云端URL
        let cloud_url = if let Some(remote_url) = upload_result.remote_url {
            // 转换S3 URL为CDN URL
            Self::convert_s3_to_cdn_url(&remote_url)
        } else if let Some(urn) = upload_result.urn {
            // 转换S3 URN为CDN URL
            Self::convert_s3_to_cdn_url(&urn)
        } else {
            return Err(anyhow!("上传成功但未返回URL"));
        };

        println!("✅ 模特照片上传成功: {}", cloud_url);

        // 创建照片对象，使用云端URL作为file_path
        let mut photo = ModelPhoto::new(
            model_id.to_string(),
            cloud_url, // 使用云端URL而不是本地路径
            file_name,
            file_size,
            photo_type,
        );

        if let Some(desc) = description {
            photo.description = Some(desc);
        }

        if let Some(photo_tags) = tags {
            photo.tags = photo_tags;
        }

        // 保存到数据库
        repository.add_photo(&photo)
            .map_err(|e| anyhow!("添加照片失败: {}", e))?;

        Ok(photo)
    }

    /// 将S3 URL转换为可访问的CDN地址
    fn convert_s3_to_cdn_url(s3_url: &str) -> String {
        // 将 s3://ap-northeast-2/modal-media-cache/ 替换为 https://cdn.roasmax.cn/
        if s3_url.starts_with("s3://ap-northeast-2/modal-media-cache/") {
            s3_url.replace("s3://ap-northeast-2/modal-media-cache/", "https://cdn.roasmax.cn/")
        } else {
            // 如果不是预期的S3格式，返回原URL
            s3_url.to_string()
        }
    }

    /// 删除模特照片
    pub fn delete_model_photo(
        repository: &ModelRepository,
        model_id: &str,
        photo_id: &str,
    ) -> Result<()> {
        // 检查模特是否存在
        let _model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 检查照片是否属于该模特
        let photos = repository.get_photos(model_id)?;
        let _photo = photos.iter().find(|p| p.id == photo_id)
            .ok_or_else(|| anyhow!("照片不存在或不属于该模特"))?;

        // 删除照片记录
        repository.delete_photo(photo_id)
            .map_err(|e| anyhow!("删除照片失败: {}", e))?;

        // TODO: 删除实际文件（可选）
        // std::fs::remove_file(&photo.file_path)?;

        Ok(())
    }

    /// 设置封面照片
    pub fn set_cover_photo(
        repository: &ModelRepository,
        model_id: &str,
        photo_id: &str,
    ) -> Result<()> {
        // 检查模特是否存在
        let _model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 检查照片是否属于该模特
        let photos = repository.get_photos(model_id)?;
        let _photo = photos.iter().find(|p| p.id == photo_id)
            .ok_or_else(|| anyhow!("照片不存在或不属于该模特"))?;

        // 设置封面照片
        repository.set_cover_photo(model_id, photo_id)
            .map_err(|e| anyhow!("设置封面照片失败: {}", e))?;

        Ok(())
    }

    /// 添加标签
    pub fn add_tag(
        repository: &ModelRepository,
        model_id: &str,
        tag: String,
    ) -> Result<()> {
        // 获取模特
        let mut model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 添加标签
        model.add_tag(tag);

        // 保存更新
        repository.update(&model)
            .map_err(|e| anyhow!("添加标签失败: {}", e))?;

        Ok(())
    }

    /// 移除标签
    pub fn remove_tag(
        repository: &ModelRepository,
        model_id: &str,
        tag: &str,
    ) -> Result<()> {
        // 获取模特
        let mut model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 移除标签
        model.remove_tag(tag);

        // 保存更新
        repository.update(&model)
            .map_err(|e| anyhow!("移除标签失败: {}", e))?;

        Ok(())
    }

    /// 更新模特状态
    pub fn update_model_status(
        repository: &ModelRepository,
        model_id: &str,
        status: ModelStatus,
    ) -> Result<()> {
        // 获取模特
        let mut model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 更新状态
        model.update_status(status);

        // 保存更新
        repository.update(&model)
            .map_err(|e| anyhow!("更新状态失败: {}", e))?;

        Ok(())
    }

    /// 设置模特评分
    pub fn set_model_rating(
        repository: &ModelRepository,
        model_id: &str,
        rating: Option<f32>,
    ) -> Result<()> {
        // 获取模特
        let mut model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 设置评分
        model.set_rating(rating);

        // 保存更新
        repository.update(&model)
            .map_err(|e| anyhow!("设置评分失败: {}", e))?;

        Ok(())
    }

    /// 设置头像
    pub fn set_avatar(
        repository: &ModelRepository,
        model_id: &str,
        avatar_path: Option<String>,
    ) -> Result<()> {
        // 获取模特
        let mut model = repository.get_by_id(model_id)?
            .ok_or_else(|| anyhow!("模特不存在: {}", model_id))?;

        // 验证头像文件路径
        if let Some(ref path) = avatar_path {
            if !Path::new(path).exists() {
                return Err(anyhow!("头像文件不存在: {}", path));
            }
        }

        // 设置头像
        model.set_avatar(avatar_path);

        // 保存更新
        repository.update(&model)
            .map_err(|e| anyhow!("设置头像失败: {}", e))?;

        Ok(())
    }

    /// 获取模特统计信息
    pub fn get_model_statistics(
        repository: &ModelRepository,
    ) -> Result<ModelStatistics> {
        let models = repository.get_all()?;
        
        let total_count = models.len();
        let active_count = models.iter().filter(|m| matches!(m.status, ModelStatus::Active)).count();
        let inactive_count = models.iter().filter(|m| matches!(m.status, ModelStatus::Inactive)).count();
        let retired_count = models.iter().filter(|m| matches!(m.status, ModelStatus::Retired)).count();
        let suspended_count = models.iter().filter(|m| matches!(m.status, ModelStatus::Suspended)).count();
        
        let male_count = models.iter().filter(|m| matches!(m.gender, Gender::Male)).count();
        let female_count = models.iter().filter(|m| matches!(m.gender, Gender::Female)).count();
        let other_count = models.iter().filter(|m| matches!(m.gender, Gender::Other)).count();
        
        let average_rating = if !models.is_empty() {
            let rated_models: Vec<_> = models.iter().filter_map(|m| m.rating).collect();
            if !rated_models.is_empty() {
                Some(rated_models.iter().sum::<f32>() / rated_models.len() as f32)
            } else {
                None
            }
        } else {
            None
        };

        Ok(ModelStatistics {
            total_count,
            active_count,
            inactive_count,
            retired_count,
            suspended_count,
            male_count,
            female_count,
            other_count,
            average_rating,
        })
    }
}

/// 模特统计信息
#[derive(Debug, serde::Serialize)]
pub struct ModelStatistics {
    pub total_count: usize,
    pub active_count: usize,
    pub inactive_count: usize,
    pub retired_count: usize,
    pub suspended_count: usize,
    pub male_count: usize,
    pub female_count: usize,
    pub other_count: usize,
    pub average_rating: Option<f32>,
}
