use anyhow::{anyhow, Result};

use crate::data::repositories::model_dynamic_repository::ModelDynamicRepository;
use crate::data::models::model_dynamic::{
    ModelDynamic, GeneratedVideo, CreateModelDynamicRequest, UpdateModelDynamicRequest,
    ModelDynamicStats, DynamicStatus, VideoGenerationStatus
};
use crate::business::errors::BusinessError;

/// 模特动态服务
/// 遵循 Tauri 开发规范的业务逻辑层设计原则
pub struct ModelDynamicService;

impl ModelDynamicService {
    /// 创建模特动态
    pub fn create_dynamic(
        repository: &ModelDynamicRepository,
        request: CreateModelDynamicRequest,
    ) -> Result<ModelDynamic> {
        // 验证请求数据
        if request.model_id.is_empty() {
            return Err(BusinessError::InvalidInput("模特ID不能为空".to_string()).into());
        }

        if request.description.trim().is_empty() {
            return Err(BusinessError::InvalidInput("动态描述不能为空".to_string()).into());
        }

        if request.prompt.trim().is_empty() {
            return Err(BusinessError::InvalidInput("提示词不能为空".to_string()).into());
        }

        if request.source_image_path.trim().is_empty() {
            return Err(BusinessError::InvalidInput("源图片路径不能为空".to_string()).into());
        }

        if request.video_count < 1 || request.video_count > 9 {
            return Err(BusinessError::InvalidInput("视频个数必须在1-9之间".to_string()).into());
        }

        // 创建动态
        let dynamic = repository.create(request)
            .map_err(|e| anyhow!("创建模特动态失败: {}", e))?;

        Ok(dynamic)
    }

    /// 获取模特动态详情
    pub fn get_dynamic_by_id(
        repository: &ModelDynamicRepository,
        id: &str,
    ) -> Result<Option<ModelDynamic>> {
        repository.get_by_id(id)
            .map_err(|e| anyhow!("获取模特动态详情失败: {}", e))
    }

    /// 获取模特的所有动态
    pub fn get_dynamics_by_model_id(
        repository: &ModelDynamicRepository,
        model_id: &str,
    ) -> Result<Vec<ModelDynamic>> {
        repository.get_by_model_id(model_id)
            .map_err(|e| anyhow!("获取模特动态列表失败: {}", e))
    }

    /// 更新模特动态
    pub fn update_dynamic(
        repository: &ModelDynamicRepository,
        id: &str,
        request: UpdateModelDynamicRequest,
    ) -> Result<ModelDynamic> {
        // 检查动态是否存在
        let dynamic = repository.get_by_id(id)?
            .ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", id)))?;

        // 验证状态转换
        if let Some(new_status) = &request.status {
            Self::validate_status_transition(&dynamic.status, new_status)?;
        }

        // 更新动态
        repository.update(id, request)
            .map_err(|e| anyhow!("更新模特动态失败: {}", e))
    }

    /// 删除模特动态
    pub fn delete_dynamic(
        repository: &ModelDynamicRepository,
        id: &str,
    ) -> Result<()> {
        // 检查动态是否存在
        let _dynamic = repository.get_by_id(id)?
            .ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", id)))?;

        // 删除动态
        repository.delete(id)
            .map_err(|e| anyhow!("删除模特动态失败: {}", e))
    }

    /// 获取模特动态统计
    pub fn get_stats_by_model_id(
        repository: &ModelDynamicRepository,
        model_id: &str,
    ) -> Result<ModelDynamicStats> {
        repository.get_stats_by_model_id(model_id)
            .map_err(|e| anyhow!("获取模特动态统计失败: {}", e))
    }

    /// 添加生成的视频
    pub fn add_generated_video(
        repository: &ModelDynamicRepository,
        dynamic_id: &str,
        video_path: String,
    ) -> Result<GeneratedVideo> {
        // 检查动态是否存在
        let mut dynamic = repository.get_by_id(dynamic_id)?
            .ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", dynamic_id)))?;

        // 创建视频对象
        let video = GeneratedVideo::new(dynamic_id.to_string(), video_path);

        // 添加到动态
        dynamic.add_generated_video(video.clone());

        // 更新动态状态
        if dynamic.status == DynamicStatus::Draft {
            dynamic.update_status(DynamicStatus::Publishing);
        }

        // 更新动态
        let request = UpdateModelDynamicRequest {
            title: None,
            description: None,
            prompt: None,
            status: Some(dynamic.status.clone()),
        };

        repository.update(dynamic_id, request)?;

        Ok(video)
    }

    /// 更新视频生成进度
    pub fn update_video_progress(
        repository: &ModelDynamicRepository,
        dynamic_id: &str,
        video_id: &str,
        progress: u32,
    ) -> Result<()> {
        // 检查动态是否存在
        let mut dynamic = repository.get_by_id(dynamic_id)?
            .ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", dynamic_id)))?;

        // 查找视频
        let video_index = dynamic.generated_videos.iter().position(|v| v.id == video_id)
            .ok_or_else(|| BusinessError::NotFound(format!("视频不存在: {}", video_id)))?;

        // 更新进度
        dynamic.generated_videos[video_index].update_progress(progress);

        // 检查是否所有视频都已完成
        let all_completed = dynamic.generated_videos.iter()
            .all(|v| v.status == VideoGenerationStatus::Completed || v.status == VideoGenerationStatus::Failed);

        // 如果所有视频都已完成，更新动态状态为已发布
        if all_completed && dynamic.status == DynamicStatus::Publishing {
            dynamic.update_status(DynamicStatus::Published);
        }

        // 更新动态
        let request = UpdateModelDynamicRequest {
            title: None,
            description: None,
            prompt: None,
            status: Some(dynamic.status.clone()),
        };

        repository.update(dynamic_id, request)?;

        Ok(())
    }

    /// 标记视频生成失败
    pub fn mark_video_as_failed(
        repository: &ModelDynamicRepository,
        dynamic_id: &str,
        video_id: &str,
        error_message: String,
    ) -> Result<()> {
        // 检查动态是否存在
        let mut dynamic = repository.get_by_id(dynamic_id)?
            .ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", dynamic_id)))?;

        // 查找视频
        let video_index = dynamic.generated_videos.iter().position(|v| v.id == video_id)
            .ok_or_else(|| BusinessError::NotFound(format!("视频不存在: {}", video_id)))?;

        // 标记为失败
        dynamic.generated_videos[video_index].mark_as_failed(error_message);

        // 检查是否所有视频都已完成
        let all_completed = dynamic.generated_videos.iter()
            .all(|v| v.status == VideoGenerationStatus::Completed || v.status == VideoGenerationStatus::Failed);

        // 如果所有视频都已完成，更新动态状态为已发布
        if all_completed && dynamic.status == DynamicStatus::Publishing {
            dynamic.update_status(DynamicStatus::Published);
        }

        // 更新动态
        let request = UpdateModelDynamicRequest {
            title: None,
            description: None,
            prompt: None,
            status: Some(dynamic.status.clone()),
        };

        repository.update(dynamic_id, request)?;

        Ok(())
    }

    /// 验证状态转换
    fn validate_status_transition(
        current_status: &DynamicStatus,
        new_status: &DynamicStatus,
    ) -> Result<()> {
        match (current_status, new_status) {
            // 允许的状态转换
            (DynamicStatus::Draft, DynamicStatus::Publishing) => Ok(()),
            (DynamicStatus::Publishing, DynamicStatus::Published) => Ok(()),
            (DynamicStatus::Publishing, DynamicStatus::Failed) => Ok(()),
            (DynamicStatus::Failed, DynamicStatus::Publishing) => Ok(()),
            // 相同状态
            (a, b) if a == b => Ok(()),
            // 不允许的状态转换
            _ => Err(BusinessError::InvalidState(format!(
                "不允许的状态转换: {:?} -> {:?}",
                current_status, new_status
            )).into()),
        }
    }
}
