use chrono::{DateTime, Utc};
use rusqlite::{Connection, Result, Row};
use std::sync::Arc;

use crate::data::models::material_usage::{
    CreateMaterialUsageRecordRequest, MaterialUsageRecord, MaterialUsageStats, MaterialUsageType,
    ProjectMaterialUsageOverview,
};
use crate::infrastructure::database::Database;

/// 素材使用记录仓库
/// 负责管理素材使用记录的数据库操作
pub struct MaterialUsageRepository {
    database: Arc<Database>,
}

impl MaterialUsageRepository {
    /// 创建新的素材使用记录仓库实例
    pub fn new(database: Arc<Database>) -> Self {
        Self { database }
    }

    /// 创建素材使用记录
    pub fn create_usage_record(
        &self,
        request: CreateMaterialUsageRecordRequest,
    ) -> Result<MaterialUsageRecord> {
        if !self.database.has_pool() {
            return Err(rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some("连接池未启用，无法安全执行数据库操作".to_string()),
            ));
        }

        let conn = self.database.acquire_from_pool().map_err(|e| {
            rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some(format!("获取连接池连接失败: {}", e)),
            )
        })?;
        let record = request.to_entity();

        conn.execute(
            "INSERT INTO material_usage_records (
                id, material_segment_id, material_id, project_id,
                template_matching_result_id, template_id, binding_id,
                track_segment_id, usage_type, usage_context, created_at
            ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)",
            rusqlite::params![
                &record.id,
                &record.material_segment_id,
                &record.material_id,
                &record.project_id,
                &record.template_matching_result_id,
                &record.template_id,
                &record.binding_id,
                &record.track_segment_id,
                &serde_json::to_string(&record.usage_type).unwrap(),
                &record.usage_context,
                &record.created_at.to_rfc3339(),
            ],
        )?;

        // 更新素材片段的使用状态
        self.update_segment_usage_status(&conn, &record.material_segment_id)?;

        Ok(record)
    }

    /// 批量创建素材使用记录
    pub fn create_usage_records_batch(
        &self,
        requests: Vec<CreateMaterialUsageRecordRequest>,
    ) -> Result<Vec<MaterialUsageRecord>> {
        if !self.database.has_pool() {
            return Err(rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some("连接池未启用，无法安全执行数据库操作".to_string()),
            ));
        }

        let conn = self.database.acquire_from_pool().map_err(|e| {
            rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some(format!("获取连接池连接失败: {}", e)),
            )
        })?;
        let mut records = Vec::new();

        // 开始事务
        let tx = conn.unchecked_transaction()?;

        for request in requests {
            let record = request.to_entity();

            tx.execute(
                "INSERT INTO material_usage_records (
                    id, material_segment_id, material_id, project_id,
                    template_matching_result_id, template_id, binding_id,
                    track_segment_id, usage_type, usage_context, created_at
                ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)",
                rusqlite::params![
                    &record.id,
                    &record.material_segment_id,
                    &record.material_id,
                    &record.project_id,
                    &record.template_matching_result_id,
                    &record.template_id,
                    &record.binding_id,
                    &record.track_segment_id,
                    &serde_json::to_string(&record.usage_type).unwrap(),
                    &record.usage_context,
                    &record.created_at.to_rfc3339(),
                ],
            )?;

            // 更新素材片段的使用状态
            self.update_segment_usage_status_in_tx(&tx, &record.material_segment_id)?;

            records.push(record);
        }

        // 提交事务
        tx.commit()?;

        Ok(records)
    }

    /// 更新素材片段的使用状态
    fn update_segment_usage_status(&self, conn: &Connection, segment_id: &str) -> Result<()> {
        // 获取当前使用次数
        let usage_count: u32 = conn.query_row(
            "SELECT COUNT(*) FROM material_usage_records WHERE material_segment_id = ?1",
            [segment_id],
            |row| row.get(0),
        )?;

        // 更新素材片段的使用状态
        conn.execute(
            "UPDATE material_segments SET 
                usage_count = ?1, 
                is_used = ?2, 
                last_used_at = ?3 
             WHERE id = ?4",
            rusqlite::params![
                usage_count,
                usage_count > 0,
                Utc::now().to_rfc3339(),
                segment_id
            ],
        )?;

        Ok(())
    }

    /// 在事务中更新素材片段的使用状态
    fn update_segment_usage_status_in_tx(
        &self,
        tx: &rusqlite::Transaction,
        segment_id: &str,
    ) -> Result<()> {
        // 获取当前使用次数
        let usage_count: u32 = tx.query_row(
            "SELECT COUNT(*) FROM material_usage_records WHERE material_segment_id = ?1",
            [segment_id],
            |row| row.get(0),
        )?;

        // 更新素材片段的使用状态
        tx.execute(
            "UPDATE material_segments SET 
                usage_count = ?1, 
                is_used = ?2, 
                last_used_at = ?3 
             WHERE id = ?4",
            rusqlite::params![
                usage_count,
                usage_count > 0,
                Utc::now().to_rfc3339(),
                segment_id
            ],
        )?;

        Ok(())
    }

    /// 获取素材使用记录列表
    pub fn get_usage_records_by_project(
        &self,
        project_id: &str,
    ) -> Result<Vec<MaterialUsageRecord>> {
        if !self.database.has_pool() {
            return Err(rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some("连接池未启用，无法安全执行数据库操作".to_string()),
            ));
        }

        let conn = self.database.acquire_from_pool().map_err(|e| {
            rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some(format!("获取连接池连接失败: {}", e)),
            )
        })?;
        let mut stmt = conn.prepare(
            "SELECT id, material_segment_id, material_id, project_id,
                    template_matching_result_id, template_id, binding_id,
                    track_segment_id, usage_type, usage_context, created_at
             FROM material_usage_records 
             WHERE project_id = ?1 
             ORDER BY created_at DESC",
        )?;

        let rows = stmt.query_map([project_id], |row| self.row_to_usage_record(row))?;

        let mut records = Vec::new();
        for row in rows {
            records.push(row?);
        }

        Ok(records)
    }

    /// 获取素材使用记录（按模板匹配结果ID）
    pub fn get_usage_records_by_matching_result(
        &self,
        matching_result_id: &str,
    ) -> Result<Vec<MaterialUsageRecord>> {
        if !self.database.has_pool() {
            return Err(rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some("连接池未启用，无法安全执行数据库操作".to_string()),
            ));
        }

        let conn = self.database.acquire_from_pool().map_err(|e| {
            rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some(format!("获取连接池连接失败: {}", e)),
            )
        })?;
        let mut stmt = conn.prepare(
            "SELECT id, material_segment_id, material_id, project_id,
                    template_matching_result_id, template_id, binding_id,
                    track_segment_id, usage_type, usage_context, created_at
             FROM material_usage_records
             WHERE template_matching_result_id = ?1
             ORDER BY created_at DESC",
        )?;

        let rows = stmt.query_map([matching_result_id], |row| self.row_to_usage_record(row))?;

        let mut records = Vec::new();
        for row in rows {
            records.push(row?);
        }

        Ok(records)
    }

    /// 批量删除使用记录（按模板匹配结果ID）
    pub fn delete_usage_records_by_matching_results(
        &self,
        matching_result_ids: &[String],
    ) -> Result<u32> {
        if !self.database.has_pool() {
            return Err(rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some("连接池未启用，无法安全执行数据库操作".to_string()),
            ));
        }

        let conn = self.database.acquire_from_pool().map_err(|e| {
            rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some(format!("获取连接池连接失败: {}", e)),
            )
        })?;

        // 开始事务
        let tx = conn.unchecked_transaction()?;

        let mut total_deleted = 0;
        let mut affected_segment_ids = std::collections::HashSet::new();

        for matching_result_id in matching_result_ids {
            // 获取要删除的记录的片段ID
            let mut stmt = tx.prepare(
                "SELECT material_segment_id FROM material_usage_records WHERE template_matching_result_id = ?1"
            )?;

            let segment_ids: Result<Vec<String>, _> = stmt
                .query_map([matching_result_id], |row| Ok(row.get::<_, String>(0)?))?
                .collect();

            let segment_ids = segment_ids?;
            for segment_id in segment_ids {
                affected_segment_ids.insert(segment_id);
            }

            // 删除使用记录
            let deleted = tx.execute(
                "DELETE FROM material_usage_records WHERE template_matching_result_id = ?1",
                [matching_result_id],
            )?;

            total_deleted += deleted as u32;
        }

        // 重置所有受影响片段的使用状态
        for segment_id in &affected_segment_ids {
            self.update_segment_usage_status_in_tx(&tx, segment_id)?;
        }

        // 提交事务
        tx.commit()?;

        Ok(total_deleted)
    }

    /// 获取素材使用统计信息
    pub fn get_material_usage_stats(&self, project_id: &str) -> Result<Vec<MaterialUsageStats>> {
        if !self.database.has_pool() {
            return Err(rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some("连接池未启用，无法安全执行数据库操作".to_string()),
            ));
        }

        let conn = self.database.acquire_from_pool().map_err(|e| {
            rusqlite::Error::SqliteFailure(
                rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE),
                Some(format!("获取连接池连接失败: {}", e)),
            )
        })?;
        let mut stmt = conn.prepare(
            "SELECT 
                m.id as material_id,
                m.name as material_name,
                COUNT(ms.id) as total_segments,
                COUNT(CASE WHEN ms.is_used = 1 THEN 1 END) as used_segments,
                COALESCE(SUM(ms.usage_count), 0) as total_usage_count,
                MAX(ms.last_used_at) as last_used_at
             FROM materials m
             LEFT JOIN material_segments ms ON m.id = ms.material_id
             WHERE m.project_id = ?1
             GROUP BY m.id, m.name
             ORDER BY m.name",
        )?;

        let rows = stmt.query_map([project_id], |row| {
            let material_id: String = row.get("material_id")?;
            let material_name: String = row.get("material_name")?;
            let total_segments: u32 = row.get::<_, i64>("total_segments")? as u32;
            let used_segments: u32 = row.get::<_, i64>("used_segments")? as u32;
            let total_usage_count: u32 = row.get::<_, i64>("total_usage_count")? as u32;
            let last_used_at: Option<DateTime<Utc>> = row
                .get::<_, Option<String>>("last_used_at")?
                .and_then(|s| DateTime::parse_from_rfc3339(&s).ok())
                .map(|dt| dt.with_timezone(&Utc));

            Ok(MaterialUsageStats::new(
                material_id,
                material_name,
                total_segments,
                used_segments,
                total_usage_count,
                last_used_at,
            ))
        })?;

        let mut stats = Vec::new();
        for row in rows {
            stats.push(row?);
        }

        Ok(stats)
    }

    /// 获取项目素材使用概览
    pub fn get_project_usage_overview(
        &self,
        project_id: &str,
    ) -> Result<ProjectMaterialUsageOverview> {
        let materials_stats = self.get_material_usage_stats(project_id)?;
        Ok(ProjectMaterialUsageOverview::new(
            project_id.to_string(),
            materials_stats,
        ))
    }

    /// 将数据库行转换为素材使用记录对象
    fn row_to_usage_record(&self, row: &Row) -> Result<MaterialUsageRecord> {
        let usage_type_str: String = row.get("usage_type")?;
        let usage_type: MaterialUsageType =
            serde_json::from_str(&usage_type_str).unwrap_or(MaterialUsageType::TemplateMatching);

        let created_at_str: String = row.get("created_at")?;
        let created_at = DateTime::parse_from_rfc3339(&created_at_str)
            .map_err(|_| {
                rusqlite::Error::InvalidColumnType(
                    10,
                    "created_at".to_string(),
                    rusqlite::types::Type::Text,
                )
            })?
            .with_timezone(&Utc);

        Ok(MaterialUsageRecord {
            id: row.get("id")?,
            material_segment_id: row.get("material_segment_id")?,
            material_id: row.get("material_id")?,
            project_id: row.get("project_id")?,
            template_matching_result_id: row.get("template_matching_result_id")?,
            template_id: row.get("template_id")?,
            binding_id: row.get("binding_id")?,
            track_segment_id: row.get("track_segment_id")?,
            usage_type,
            usage_context: row.get("usage_context")?,
            created_at,
        })
    }
}
