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

// ==========================================
// 舊版結構體 (保留以向後兼容)
// ==========================================

#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct PersonIdentity {
    pub id: i32,
    pub person_id: String,
    pub face_identity_id: Option<i32>,
    pub speaker_id: Option<String>,
    pub video_uuid: String,
    pub confidence: f64,
    pub name: Option<String>,
    pub metadata: serde_json::Value,
    pub first_appearance_time: Option<f64>,
    pub last_appearance_time: Option<f64>,
    pub total_appearance_duration: f64,
    pub appearance_count: i32,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub is_confirmed: bool,
}

// ==========================================
// 新版結構體 (V5 身份綁定系統)
// ==========================================

/// 人物身份 (Identity) - 統一管理演員、公眾人物、家人朋友等
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct Identity {
    pub id: i32,
    pub name: String,
    pub embedding: Option<String>, // Vector embedding stored as text/json
    pub metadata: Option<serde_json::Value>,
    pub created_at: DateTime<Utc>,
}

/// 身份綁定記錄 (Identity Binding)
/// 將機器 ID (face_x, speaker_y) 綁定到 Identity
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct IdentityBinding {
    pub id: i64,
    pub identity_id: i64,
    pub binding_type: String,  // 'face', 'speaker'
    pub binding_value: String, // e.g. "face_1", "speaker_3"
    pub source: String,        // 'auto', 'manual'
    pub confidence: f64,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
}

/// 綁定請求 (用於 API)
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct BindIdentityRequest {
    pub identity_id: Option<i64>,
    pub name: Option<String>,   // 若未提供 identity_id，則建立新 Identity
    pub binding_type: String,   // 'face' 或 'speaker'
    pub binding_value: String,  // e.g. "face_1"
    pub source: Option<String>, // 預設 'manual'
}

/// 解綁請求
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct UnbindIdentityRequest {
    pub binding_type: String,
    pub binding_value: String,
}

/// 建議綁定請求 (由系統自動產生，人工確認)
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SuggestedBinding {
    pub binding_type: String,
    pub binding_value: String,
    pub suggested_identity_id: i64,
    pub suggested_identity_name: String,
    pub confidence: f64,
    pub reason: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct PersonAppearance {
    pub id: i32,
    pub person_id: String,
    pub video_uuid: String,
    pub start_time: f64,
    pub end_time: f64,
    pub duration: f64,
    pub face_detection_id: Option<i32>,
    pub asrx_segment_start: Option<f64>,
    pub asrx_segment_end: Option<f64>,
    pub confidence: f64,
    pub metadata: serde_json::Value,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct PersonMatch {
    pub face_id: String,
    pub speaker_id: String,
    pub confidence: f64,
    pub match_count: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PersonTimelineEntry {
    pub start_time: f64,
    pub end_time: f64,
    pub duration: f64,
    pub confidence: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PersonStatistics {
    pub total_appearances: i32,
    pub total_duration: f64,
    pub first_appearance: Option<f64>,
    pub last_appearance: Option<f64>,
    pub average_confidence: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreatePersonIdentityRequest {
    pub video_uuid: String,
    pub face_identity_id: Option<i32>,
    pub speaker_id: Option<String>,
    pub name: Option<String>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdatePersonIdentityRequest {
    pub name: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub is_confirmed: Option<bool>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PersonIdentityResponse {
    pub person_id: String,
    pub name: Option<String>,
    pub face_identity_id: Option<i32>,
    pub speaker_id: Option<String>,
    pub confidence: f64,
    pub appearance_count: i32,
    pub total_appearance_duration: f64,
    pub first_appearance_time: Option<f64>,
    pub last_appearance_time: Option<f64>,
    pub is_confirmed: bool,
}

impl From<PersonIdentity> for PersonIdentityResponse {
    fn from(person: PersonIdentity) -> Self {
        Self {
            person_id: person.person_id,
            name: person.name,
            face_identity_id: person.face_identity_id,
            speaker_id: person.speaker_id,
            confidence: person.confidence,
            appearance_count: person.appearance_count,
            total_appearance_duration: person.total_appearance_duration,
            first_appearance_time: person.first_appearance_time,
            last_appearance_time: person.last_appearance_time,
            is_confirmed: person.is_confirmed,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PersonTimelineResponse {
    pub person_id: String,
    pub name: Option<String>,
    pub timeline: Vec<PersonTimelineEntry>,
    pub statistics: PersonStatistics,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChunkPersonInfo {
    pub person_id: String,
    pub name: Option<String>,
    pub confidence: f64,
    pub overlap_duration: f64,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_person_identity_serialization() {
        let person = PersonIdentity {
            id: 1,
            person_id: "person_001".to_string(),
            face_identity_id: Some(123),
            speaker_id: Some("SPEAKER_00".to_string()),
            video_uuid: "video_abc".to_string(),
            confidence: 0.85,
            name: Some("张三".to_string()),
            metadata: serde_json::json!({"role": "host"}),
            first_appearance_time: Some(10.5),
            last_appearance_time: Some(350.2),
            total_appearance_duration: 120.5,
            appearance_count: 15,
            created_at: Utc::now(),
            updated_at: Utc::now(),
            is_confirmed: true,
        };

        let json = serde_json::to_string(&person).unwrap();
        assert!(json.contains("person_001"));
        assert!(json.contains("SPEAKER_00"));
        assert!(json.contains("张三"));
    }

    #[test]
    fn test_person_appearance_serialization() {
        let appearance = PersonAppearance {
            id: 1,
            person_id: "person_001".to_string(),
            video_uuid: "video_abc".to_string(),
            start_time: 10.5,
            end_time: 25.3,
            duration: 14.8,
            face_detection_id: Some(456),
            asrx_segment_start: Some(10.0),
            asrx_segment_end: Some(26.0),
            confidence: 0.92,
            metadata: serde_json::json!({}),
            created_at: Utc::now(),
        };

        let json = serde_json::to_string(&appearance).unwrap();
        assert!(json.contains("person_001"));
        assert!(json.contains("14.8"));
    }

    #[test]
    fn test_person_match() {
        let match_result = PersonMatch {
            face_id: "face_123".to_string(),
            speaker_id: "SPEAKER_00".to_string(),
            confidence: 0.85,
            match_count: 15,
        };

        assert_eq!(match_result.face_id, "face_123");
        assert!(match_result.confidence >= 0.0 && match_result.confidence <= 1.0);
    }

    #[test]
    fn test_person_statistics() {
        let stats = PersonStatistics {
            total_appearances: 15,
            total_duration: 120.5,
            first_appearance: Some(10.5),
            last_appearance: Some(350.2),
            average_confidence: 0.88,
        };

        assert_eq!(stats.total_appearances, 15);
        assert!(stats.total_duration > 0.0);
    }
}
