use serde::{Deserialize, Serialize, Deserializer};
use chrono::{DateTime, Utc};

/// 模板匹配结果实体模型
/// 遵循 Tauri 开发规范的数据模型设计原则
/// 保存一次完整的模板匹配结果，包含所有匹配的片段信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateMatchingResult {
    pub id: String,
    pub project_id: String,
    pub template_id: String,
    pub binding_id: String,
    pub result_name: String, // 用户自定义的结果名称
    pub description: Option<String>,
    pub total_segments: u32,
    pub matched_segments: u32,
    pub failed_segments: u32,
    pub success_rate: f64,
    pub used_materials: u32,
    pub used_models: u32,
    pub matching_duration_ms: u64, // 匹配耗时（毫秒）
    pub quality_score: Option<f64>, // 匹配质量评分
    pub status: MatchingResultStatus,
    pub metadata: Option<String>, // JSON格式的额外元数据
    pub export_count: u32, // 导出次数
    pub is_exported: bool, // 是否已导出
    pub last_exported_at: Option<DateTime<Utc>>, // 最后导出时间
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub is_active: bool,
}

/// 匹配结果状态
#[derive(Debug, Clone, Serialize, PartialEq)]
pub enum MatchingResultStatus {
    /// 匹配成功
    Success,
    /// 部分匹配成功
    PartialSuccess,
    /// 匹配失败
    Failed,
    /// 匹配被取消
    Cancelled,
}

/// 自定义反序列化实现，处理空字符串和无效值
impl<'de> Deserialize<'de> for MatchingResultStatus {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        match s.as_str() {
            "Success" => Ok(MatchingResultStatus::Success),
            "PartialSuccess" => Ok(MatchingResultStatus::PartialSuccess),
            "Failed" => Ok(MatchingResultStatus::Failed),
            "Cancelled" => Ok(MatchingResultStatus::Cancelled),
            "" => {
                // 空字符串被视为无效值，返回错误让调用者处理
                Err(serde::de::Error::custom("Empty string is not a valid MatchingResultStatus"))
            }
            _ => Err(serde::de::Error::unknown_variant(&s, &["Success", "PartialSuccess", "Failed", "Cancelled"])),
        }
    }
}

impl Default for MatchingResultStatus {
    fn default() -> Self {
        Self::Success
    }
}

/// 匹配片段结果实体模型
/// 保存每个成功匹配的片段详细信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MatchingSegmentResult {
    pub id: String,
    pub matching_result_id: String, // 关联的匹配结果ID
    pub track_segment_id: String,   // 模板轨道片段ID
    pub track_segment_name: String,
    pub material_segment_id: String, // 匹配到的素材片段ID
    pub material_id: String,         // 素材ID
    pub material_name: String,
    pub model_id: Option<String>,    // 模特ID
    pub model_name: Option<String>,
    pub match_score: f64,            // 匹配评分
    pub match_reason: String,        // 匹配原因
    pub segment_duration: u64,       // 片段时长（微秒）
    pub start_time: u64,             // 在模板中的开始时间（微秒）
    pub end_time: u64,               // 在模板中的结束时间（微秒）
    pub properties: Option<String>,  // JSON格式的片段属性
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

/// 匹配失败片段结果实体模型
/// 保存匹配失败的片段信息，用于分析和改进
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MatchingFailedSegmentResult {
    pub id: String,
    pub matching_result_id: String, // 关联的匹配结果ID
    pub track_segment_id: String,   // 模板轨道片段ID
    pub track_segment_name: String,
    pub matching_rule_type: String, // 匹配规则类型
    pub matching_rule_data: Option<String>, // 匹配规则数据（JSON格式）
    pub failure_reason: String,     // 失败原因
    pub failure_details: Option<String>, // 失败详情（JSON格式）
    pub segment_duration: u64,      // 片段时长（微秒）
    pub start_time: u64,            // 在模板中的开始时间（微秒）
    pub end_time: u64,              // 在模板中的结束时间（微秒）
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

impl TemplateMatchingResult {
    /// 创建新的模板匹配结果实例
    pub fn new(
        id: String,
        project_id: String,
        template_id: String,
        binding_id: String,
        result_name: String,
    ) -> Self {
        let now = Utc::now();
        Self {
            id,
            project_id,
            template_id,
            binding_id,
            result_name,
            description: None,
            total_segments: 0,
            matched_segments: 0,
            failed_segments: 0,
            success_rate: 0.0,
            used_materials: 0,
            used_models: 0,
            matching_duration_ms: 0,
            quality_score: None,
            status: MatchingResultStatus::default(),
            metadata: None,
            export_count: 0,
            is_exported: false,
            last_exported_at: None,
            created_at: now,
            updated_at: now,
            is_active: true,
        }
    }

    /// 更新匹配统计信息
    pub fn update_statistics(
        &mut self,
        total_segments: u32,
        matched_segments: u32,
        failed_segments: u32,
        used_materials: u32,
        used_models: u32,
        matching_duration_ms: u64,
    ) {
        self.total_segments = total_segments;
        self.matched_segments = matched_segments;
        self.failed_segments = failed_segments;
        self.success_rate = if total_segments > 0 {
            (matched_segments as f64) / (total_segments as f64) * 100.0
        } else {
            0.0
        };
        self.used_materials = used_materials;
        self.used_models = used_models;
        self.matching_duration_ms = matching_duration_ms;
        self.updated_at = Utc::now();

        // 根据成功率设置状态
        self.status = if self.success_rate >= 100.0 {
            MatchingResultStatus::Success
        } else if self.success_rate > 0.0 {
            MatchingResultStatus::PartialSuccess
        } else {
            MatchingResultStatus::Failed
        };
    }

    /// 设置质量评分
    pub fn set_quality_score(&mut self, score: f64) {
        self.quality_score = Some(score);
        self.updated_at = Utc::now();
    }

    /// 设置描述
    pub fn set_description(&mut self, description: String) {
        self.description = Some(description);
        self.updated_at = Utc::now();
    }

    /// 设置元数据
    pub fn set_metadata(&mut self, metadata: String) {
        self.metadata = Some(metadata);
        self.updated_at = Utc::now();
    }

    /// 检查是否为成功的匹配结果
    pub fn is_successful(&self) -> bool {
        matches!(self.status, MatchingResultStatus::Success | MatchingResultStatus::PartialSuccess)
    }

    /// 获取状态显示名称
    pub fn status_display_name(&self) -> String {
        match self.status {
            MatchingResultStatus::Success => "匹配成功".to_string(),
            MatchingResultStatus::PartialSuccess => "部分成功".to_string(),
            MatchingResultStatus::Failed => "匹配失败".to_string(),
            MatchingResultStatus::Cancelled => "已取消".to_string(),
        }
    }

    /// 标记为已导出
    pub fn mark_as_exported(&mut self) {
        self.is_exported = true;
        self.export_count += 1;
        self.last_exported_at = Some(Utc::now());
        self.updated_at = Utc::now();
    }

    /// 重置导出状态
    pub fn reset_export_status(&mut self) {
        self.is_exported = false;
        self.last_exported_at = None;
        self.updated_at = Utc::now();
    }
}

impl MatchingSegmentResult {
    /// 创建新的匹配片段结果实例
    pub fn new(
        id: String,
        matching_result_id: String,
        track_segment_id: String,
        track_segment_name: String,
        material_segment_id: String,
        material_id: String,
        material_name: String,
        match_score: f64,
        match_reason: String,
        segment_duration: u64,
        start_time: u64,
        end_time: u64,
    ) -> Self {
        let now = Utc::now();
        Self {
            id,
            matching_result_id,
            track_segment_id,
            track_segment_name,
            material_segment_id,
            material_id,
            material_name,
            model_id: None,
            model_name: None,
            match_score,
            match_reason,
            segment_duration,
            start_time,
            end_time,
            properties: None,
            created_at: now,
            updated_at: now,
        }
    }

    /// 设置模特信息
    pub fn set_model_info(&mut self, model_id: String, model_name: String) {
        self.model_id = Some(model_id);
        self.model_name = Some(model_name);
        self.updated_at = Utc::now();
    }

    /// 设置片段属性
    pub fn set_properties(&mut self, properties: String) {
        self.properties = Some(properties);
        self.updated_at = Utc::now();
    }
}

impl MatchingFailedSegmentResult {
    /// 创建新的匹配失败片段结果实例
    pub fn new(
        id: String,
        matching_result_id: String,
        track_segment_id: String,
        track_segment_name: String,
        matching_rule_type: String,
        failure_reason: String,
        segment_duration: u64,
        start_time: u64,
        end_time: u64,
    ) -> Self {
        let now = Utc::now();
        Self {
            id,
            matching_result_id,
            track_segment_id,
            track_segment_name,
            matching_rule_type,
            matching_rule_data: None,
            failure_reason,
            failure_details: None,
            segment_duration,
            start_time,
            end_time,
            created_at: now,
            updated_at: now,
        }
    }

    /// 设置匹配规则数据
    pub fn set_matching_rule_data(&mut self, rule_data: String) {
        self.matching_rule_data = Some(rule_data);
        self.updated_at = Utc::now();
    }

    /// 设置失败详情
    pub fn set_failure_details(&mut self, details: String) {
        self.failure_details = Some(details);
        self.updated_at = Utc::now();
    }
}

/// 创建模板匹配结果请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateTemplateMatchingResultRequest {
    pub project_id: String,
    pub template_id: String,
    pub binding_id: String,
    pub result_name: String,
    pub description: Option<String>,
}

/// 自定义反序列化函数，处理空字符串状态
fn deserialize_optional_status<'de, D>(deserializer: D) -> Result<Option<MatchingResultStatus>, D::Error>
where
    D: Deserializer<'de>,
{
    let opt = Option::<String>::deserialize(deserializer)?;
    match opt {
        Some(s) if s.is_empty() => Ok(None), // 空字符串转换为 None
        Some(s) => match s.as_str() {
            "Success" => Ok(Some(MatchingResultStatus::Success)),
            "PartialSuccess" => Ok(Some(MatchingResultStatus::PartialSuccess)),
            "Failed" => Ok(Some(MatchingResultStatus::Failed)),
            "Cancelled" => Ok(Some(MatchingResultStatus::Cancelled)),
            _ => Err(serde::de::Error::unknown_variant(&s, &["Success", "PartialSuccess", "Failed", "Cancelled"])),
        },
        None => Ok(None),
    }
}

/// 模板匹配结果查询选项
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct TemplateMatchingResultQueryOptions {
    #[serde(default)]
    pub project_id: Option<String>,
    #[serde(default)]
    pub template_id: Option<String>,
    #[serde(default)]
    pub binding_id: Option<String>,
    #[serde(default, deserialize_with = "deserialize_optional_status")]
    pub status: Option<MatchingResultStatus>,
    #[serde(default)]
    pub limit: Option<u32>,
    #[serde(default)]
    pub offset: Option<u32>,
    #[serde(default)]
    pub search_keyword: Option<String>,
    #[serde(default)]
    pub sort_by: Option<String>, // "created_at", "success_rate", "result_name"
    #[serde(default)]
    pub sort_order: Option<String>, // "asc", "desc"
}
