use anyhow::{Result, anyhow};
use std::sync::Arc;
use rusqlite::{params, Row};

use crate::data::models::template::{
    Template, TemplateMaterial, Track, TrackSegment, CanvasConfig,
    TemplateMaterialType, TrackType, ImportStatus, UploadStatus,
    CreateTemplateRequest, SegmentMatchingRule
};
use crate::infrastructure::database::Database;

/// 模板服务
/// 遵循 Tauri 开发规范的业务逻辑设计原则
pub struct TemplateService {
    database: Arc<Database>,
}

/// 模板查询选项
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct TemplateQueryOptions {
    pub project_id: Option<String>,
    pub import_status: Option<ImportStatus>,
    pub limit: Option<u32>,
    pub offset: Option<u32>,
    pub search_keyword: Option<String>,
}

/// 模板列表响应
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TemplateListResponse {
    pub templates: Vec<Template>,
    pub total: u32,
}

impl TemplateService {
    /// 创建新的模板服务实例
    pub fn new(database: Arc<Database>) -> Self {
        Self { database }
    }

    /// 创建模板
    pub async fn create_template(&self, request: CreateTemplateRequest) -> Result<String> {
        let template = Template::new(
            request.name,
            CanvasConfig {
                width: 1920,
                height: 1080,
                ratio: "16:9".to_string(),
            },
            0,
            30.0,
        );

        self.save_template(&template).await?;
        Ok(template.id)
    }

    /// 保存模板到数据库
    pub async fn save_template(&self, template: &Template) -> Result<()> {
        let conn = self.database.get_connection();
        let conn = conn.lock().map_err(|e| anyhow!("获取数据库连接失败: {}", e))?;

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

        // 如果模板已存在，先删除相关数据以避免外键冲突
        tx.execute("DELETE FROM track_segments WHERE track_id IN (SELECT id FROM tracks WHERE template_id = ?1)", params![template.id])?;
        tx.execute("DELETE FROM tracks WHERE template_id = ?1", params![template.id])?;
        tx.execute("DELETE FROM template_materials WHERE template_id = ?1", params![template.id])?;

        // 保存模板基本信息
        tx.execute(
            "INSERT OR REPLACE INTO templates (
                id, name, description, canvas_width, canvas_height,
                canvas_ratio, duration, fps, import_status, source_file_path,
                created_at, updated_at, is_active
            ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)",
            params![
                template.id,
                template.name,
                template.description,
                template.canvas_config.width,
                template.canvas_config.height,
                template.canvas_config.ratio,
                template.duration as i64,
                template.fps,
                format!("{:?}", template.import_status),
                template.source_file_path,
                template.created_at.to_rfc3339(),
                template.updated_at.to_rfc3339(),
                template.is_active
            ],
        )?;

        // 删除逻辑已在上面处理，这里不需要重复删除

        // 保存素材
        for material in &template.materials {
            tx.execute(
                "INSERT OR REPLACE INTO template_materials (
                    id, template_id, original_id, name, material_type, original_path,
                    remote_url, file_size, duration, width, height, upload_status,
                    file_exists, upload_success, metadata, created_at, updated_at
                ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17)",
                params![
                    material.id,
                    material.template_id,
                    material.original_id,
                    material.name,
                    format!("{:?}", material.material_type),
                    material.original_path,
                    material.remote_url,
                    material.file_size.map(|s| s as i64),
                    material.duration.map(|d| d as i64),
                    material.width.map(|w| w as i64),
                    material.height.map(|h| h as i64),
                    format!("{:?}", material.upload_status),
                    material.file_exists,
                    material.upload_success,
                    material.metadata,
                    material.created_at.to_rfc3339(),
                    material.updated_at.to_rfc3339()
                ],
            )?;
        }

        // 保存轨道
        for track in &template.tracks {
            tx.execute(
                "INSERT OR REPLACE INTO tracks (
                    id, template_id, name, track_type, track_index,
                    created_at, updated_at
                ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
                params![
                    track.id,
                    track.template_id,
                    track.name,
                    format!("{:?}", track.track_type),
                    track.track_index,
                    track.created_at.to_rfc3339(),
                    track.updated_at.to_rfc3339()
                ],
            )?;

            // 保存轨道片段
            for segment in &track.segments {
                let matching_rule_json = serde_json::to_string(&segment.matching_rule)
                    .unwrap_or_else(|_| r#"{"FixedMaterial":{}}"#.to_string());

                tx.execute(
                    "INSERT OR REPLACE INTO track_segments (
                        id, track_id, template_material_id, name, start_time, end_time,
                        duration, segment_index, properties, matching_rule, created_at, updated_at
                    ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)",
                    params![
                        segment.id,
                        segment.track_id,
                        segment.template_material_id,
                        segment.name,
                        segment.start_time as i64,
                        segment.end_time as i64,
                        segment.duration as i64,
                        segment.segment_index,
                        segment.properties,
                        matching_rule_json,
                        segment.created_at.to_rfc3339(),
                        segment.updated_at.to_rfc3339()
                    ],
                )?;
            }
        }

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

    /// 根据ID获取模板
    pub async fn get_template_by_id(&self, template_id: &str) -> Result<Option<Template>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();

        // 查询模板基本信息
        let template_result = conn.query_row(
            "SELECT id, name, description, canvas_width, canvas_height,
                    canvas_ratio, duration, fps, import_status, source_file_path,
                    created_at, updated_at, is_active
             FROM templates WHERE id = ?1",
            params![template_id],
            |row| self.row_to_template_basic(row),
        );

        let mut template = match template_result {
            Ok(template) => template,
            Err(rusqlite::Error::QueryReturnedNoRows) => return Ok(None),
            Err(e) => return Err(e.into()),
        };

        // 查询素材
        let mut stmt = conn.prepare(
            "SELECT id, template_id, original_id, name, material_type, original_path,
                    remote_url, file_size, duration, width, height, upload_status,
                    file_exists, upload_success, metadata, created_at, updated_at
             FROM template_materials WHERE template_id = ?1"
        )?;

        let material_rows = stmt.query_map(params![template_id], |row| {
            self.row_to_template_material(row)
        })?;

        for material_result in material_rows {
            template.materials.push(material_result?);
        }

        // 查询轨道
        let mut stmt = conn.prepare(
            "SELECT id, template_id, name, track_type, track_index, created_at, updated_at
             FROM tracks WHERE template_id = ?1 ORDER BY track_index"
        )?;

        let track_rows = stmt.query_map(params![template_id], |row| {
            self.row_to_track_basic(row)
        })?;

        for track_result in track_rows {
            let mut track = track_result?;
            
            // 查询轨道片段
            let mut segment_stmt = conn.prepare(
                "SELECT id, track_id, template_material_id, name, start_time, end_time,
                        duration, segment_index, properties, matching_rule, created_at, updated_at
                 FROM track_segments WHERE track_id = ?1 ORDER BY segment_index"
            )?;

            let segment_rows = segment_stmt.query_map(params![track.id], |row| {
                self.row_to_track_segment(row)
            })?;

            for segment_result in segment_rows {
                track.segments.push(segment_result?);
            }

            template.tracks.push(track);
        }

        Ok(Some(template))
    }

    /// 查询模板列表
    pub async fn list_templates(&self, options: TemplateQueryOptions) -> Result<TemplateListResponse> {
        let conn = self.database.get_connection();
        let conn = conn.lock().map_err(|e| anyhow!("获取数据库连接失败: {}", e))?;

        // 简化的查询方法，使用具体的参数而不是动态构建
        if let Some(project_id) = &options.project_id {
            if let Some(import_status) = &options.import_status {
                // 有项目ID和状态过滤
                let status_str = format!("{:?}", import_status);
                let total: u32 = conn.query_row(
                    "SELECT COUNT(*) FROM templates WHERE is_active = 1 AND project_id = ?1 AND import_status = ?2",
                    params![project_id, status_str],
                    |row| Ok(row.get::<_, i64>(0)? as u32)
                )?;

                let mut sql = "SELECT id, name, description, project_id, canvas_width, canvas_height,
                        canvas_ratio, duration, fps, import_status, source_file_path,
                        created_at, updated_at, is_active
                 FROM templates WHERE is_active = 1 AND project_id = ?1 AND import_status = ?2 ORDER BY created_at DESC".to_string();

                if let Some(limit) = options.limit {
                    sql.push_str(&format!(" LIMIT {}", limit));
                    if let Some(offset) = options.offset {
                        sql.push_str(&format!(" OFFSET {}", offset));
                    }
                }

                let mut stmt = conn.prepare(&sql)?;
                let template_rows = stmt.query_map(params![project_id, status_str], |row| {
                    self.row_to_template_basic(row)
                })?;

                let mut templates = Vec::new();
                for template_result in template_rows {
                    let mut template = template_result?;
                    // 填充素材和轨道数量
                    self.fill_template_counts(&conn, &mut template)?;
                    templates.push(template);
                }

                return Ok(TemplateListResponse { templates, total });
            } else {
                // 只有项目ID过滤
                let total: u32 = conn.query_row(
                    "SELECT COUNT(*) FROM templates WHERE is_active = 1 AND project_id = ?1",
                    params![project_id],
                    |row| Ok(row.get::<_, i64>(0)? as u32)
                )?;

                let mut sql = "SELECT id, name, description, project_id, canvas_width, canvas_height,
                        canvas_ratio, duration, fps, import_status, source_file_path,
                        created_at, updated_at, is_active
                 FROM templates WHERE is_active = 1 AND project_id = ?1 ORDER BY created_at DESC".to_string();

                if let Some(limit) = options.limit {
                    sql.push_str(&format!(" LIMIT {}", limit));
                    if let Some(offset) = options.offset {
                        sql.push_str(&format!(" OFFSET {}", offset));
                    }
                }

                let mut stmt = conn.prepare(&sql)?;
                let template_rows = stmt.query_map(params![project_id], |row| {
                    self.row_to_template_basic(row)
                })?;

                let mut templates = Vec::new();
                for template_result in template_rows {
                    let mut template = template_result?;
                    // 填充素材和轨道数量
                    self.fill_template_counts(&conn, &mut template)?;
                    templates.push(template);
                }

                return Ok(TemplateListResponse { templates, total });
            }
        }

        // 默认查询所有活跃模板
        let total: u32 = conn.query_row(
            "SELECT COUNT(*) FROM templates WHERE is_active = 1",
            [],
            |row| Ok(row.get::<_, i64>(0)? as u32)
        )?;

        let mut sql = "SELECT id, name, description, canvas_width, canvas_height,
                canvas_ratio, duration, fps, import_status, source_file_path,
                created_at, updated_at, is_active
         FROM templates WHERE is_active = 1 ORDER BY created_at DESC".to_string();

        if let Some(limit) = options.limit {
            sql.push_str(&format!(" LIMIT {}", limit));
            if let Some(offset) = options.offset {
                sql.push_str(&format!(" OFFSET {}", offset));
            }
        }

        let mut stmt = conn.prepare(&sql)?;
        let template_rows = stmt.query_map([], |row| {
            self.row_to_template_basic(row)
        })?;

        let mut templates = Vec::new();
        for template_result in template_rows {
            let mut template = template_result?;
            // 填充素材和轨道数量
            self.fill_template_counts(&conn, &mut template)?;
            templates.push(template);
        }

        Ok(TemplateListResponse { templates, total })
    }

    /// 更新模板
    pub async fn update_template(&self, template: &Template) -> Result<()> {
        self.save_template(template).await
    }

    /// 删除模板
    pub async fn delete_template(&self, template_id: &str) -> Result<()> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();

        conn.execute(
            "UPDATE templates SET is_active = 0, updated_at = ?1 WHERE id = ?2",
            params![chrono::Utc::now().to_rfc3339(), template_id],
        )?;

        Ok(())
    }

    /// 数据库行转换为模板基本信息
    fn row_to_template_basic(&self, row: &Row) -> rusqlite::Result<Template> {
        let canvas_config = CanvasConfig {
            width: row.get::<_, i64>("canvas_width")? as u32,
            height: row.get::<_, i64>("canvas_height")? as u32,
            ratio: row.get("canvas_ratio")?,
        };

        let import_status_str: String = row.get("import_status")?;
        let import_status = match import_status_str.as_str() {
            "Pending" => ImportStatus::Pending,
            "Parsing" => ImportStatus::Parsing,
            "Uploading" => ImportStatus::Uploading,
            "Processing" => ImportStatus::Processing,
            "Completed" => ImportStatus::Completed,
            "Failed" => ImportStatus::Failed,
            _ => ImportStatus::Pending,
        };

        Ok(Template {
            id: row.get("id")?,
            name: row.get("name")?,
            description: row.get("description")?,
            canvas_config,
            duration: row.get::<_, i64>("duration")? as u64,
            fps: row.get("fps")?,
            materials: Vec::new(), // 稍后填充
            tracks: Vec::new(),    // 稍后填充
            import_status,
            source_file_path: row.get("source_file_path")?,
            created_at: {
                let created_at_str: String = row.get("created_at")?;
                chrono::DateTime::parse_from_rfc3339(&created_at_str)
                    .or_else(|_| {
                        // 尝试解析SQLite格式的日期
                        chrono::NaiveDateTime::parse_from_str(&created_at_str, "%Y-%m-%d %H:%M:%S")
                            .map(|dt| dt.and_utc().fixed_offset())
                    })
                    .map_err(|e| {
                        eprintln!("❌ 解析created_at失败: '{}', 错误: {}", created_at_str, e);
                        rusqlite::Error::InvalidColumnType(0, "created_at".to_string(), rusqlite::types::Type::Text)
                    })?
                    .with_timezone(&chrono::Utc)
            },
            updated_at: {
                let updated_at_str: String = row.get("updated_at")?;
                chrono::DateTime::parse_from_rfc3339(&updated_at_str)
                    .or_else(|_| {
                        // 尝试解析SQLite格式的日期
                        chrono::NaiveDateTime::parse_from_str(&updated_at_str, "%Y-%m-%d %H:%M:%S")
                            .map(|dt| dt.and_utc().fixed_offset())
                    })
                    .map_err(|e| {
                        eprintln!("❌ 解析updated_at失败: '{}', 错误: {}", updated_at_str, e);
                        rusqlite::Error::InvalidColumnType(0, "updated_at".to_string(), rusqlite::types::Type::Text)
                    })?
                    .with_timezone(&chrono::Utc)
            },
            is_active: row.get("is_active")?,
        })
    }

    /// 数据库行转换为模板素材
    fn row_to_template_material(&self, row: &Row) -> rusqlite::Result<TemplateMaterial> {
        let material_type_str: String = row.get("material_type")?;
        let material_type = match material_type_str.as_str() {
            "Video" => TemplateMaterialType::Video,
            "Audio" => TemplateMaterialType::Audio,
            "Image" => TemplateMaterialType::Image,
            "Text" => TemplateMaterialType::Text,
            "Effect" => TemplateMaterialType::Effect,
            "Sticker" => TemplateMaterialType::Sticker,
            "Canvas" => TemplateMaterialType::Canvas,
            other => TemplateMaterialType::Other(other.to_string()),
        };

        let upload_status_str: String = row.get("upload_status")?;
        let upload_status = match upload_status_str.as_str() {
            "Pending" => UploadStatus::Pending,
            "Uploading" => UploadStatus::Uploading,
            "Completed" => UploadStatus::Completed,
            "Failed" => UploadStatus::Failed,
            "Skipped" => UploadStatus::Skipped,
            _ => UploadStatus::Pending,
        };

        Ok(TemplateMaterial {
            id: row.get("id")?,
            template_id: row.get("template_id")?,
            original_id: row.get("original_id")?,
            name: row.get("name")?,
            material_type,
            original_path: row.get("original_path")?,
            remote_url: row.get("remote_url")?,
            file_size: row.get::<_, Option<i64>>("file_size")?.map(|s| s as u64),
            duration: row.get::<_, Option<i64>>("duration")?.map(|d| d as u64),
            width: row.get::<_, Option<i64>>("width")?.map(|w| w as u32),
            height: row.get::<_, Option<i64>>("height")?.map(|h| h as u32),
            upload_status,
            file_exists: row.get::<_, Option<bool>>("file_exists")?.unwrap_or(false),
            upload_success: row.get::<_, Option<bool>>("upload_success")?.unwrap_or(false),
            metadata: row.get("metadata")?,
            created_at: {
                let created_at_str: String = row.get("created_at")?;
                chrono::DateTime::parse_from_rfc3339(&created_at_str)
                    .or_else(|_| {
                        chrono::NaiveDateTime::parse_from_str(&created_at_str, "%Y-%m-%d %H:%M:%S")
                            .map(|dt| dt.and_utc().fixed_offset())
                    })
                    .map_err(|e| {
                        eprintln!("❌ 解析素材created_at失败: '{}', 错误: {}", created_at_str, e);
                        rusqlite::Error::InvalidColumnType(0, "created_at".to_string(), rusqlite::types::Type::Text)
                    })?
                    .with_timezone(&chrono::Utc)
            },
            updated_at: {
                let updated_at_str: String = row.get("updated_at")?;
                chrono::DateTime::parse_from_rfc3339(&updated_at_str)
                    .or_else(|_| {
                        chrono::NaiveDateTime::parse_from_str(&updated_at_str, "%Y-%m-%d %H:%M:%S")
                            .map(|dt| dt.and_utc().fixed_offset())
                    })
                    .map_err(|e| {
                        eprintln!("❌ 解析素材updated_at失败: '{}', 错误: {}", updated_at_str, e);
                        rusqlite::Error::InvalidColumnType(0, "updated_at".to_string(), rusqlite::types::Type::Text)
                    })?
                    .with_timezone(&chrono::Utc)
            },
        })
    }

    /// 数据库行转换为轨道基本信息
    fn row_to_track_basic(&self, row: &Row) -> rusqlite::Result<Track> {
        let track_type_str: String = row.get("track_type")?;
        let track_type = match track_type_str.as_str() {
            "Video" => TrackType::Video,
            "Audio" => TrackType::Audio,
            "Text" => TrackType::Text,
            "Sticker" => TrackType::Sticker,
            "Effect" => TrackType::Effect,
            other => TrackType::Other(other.to_string()),
        };

        Ok(Track {
            id: row.get("id")?,
            template_id: row.get("template_id")?,
            name: row.get("name")?,
            track_type,
            track_index: row.get::<_, i64>("track_index")? as u32,
            segments: Vec::new(), // 稍后填充
            created_at: chrono::DateTime::parse_from_rfc3339(&row.get::<_, String>("created_at")?)
                .unwrap()
                .with_timezone(&chrono::Utc),
            updated_at: chrono::DateTime::parse_from_rfc3339(&row.get::<_, String>("updated_at")?)
                .unwrap()
                .with_timezone(&chrono::Utc),
        })
    }

    /// 数据库行转换为轨道片段
    fn row_to_track_segment(&self, row: &Row) -> rusqlite::Result<TrackSegment> {
        // 解析匹配规则，如果解析失败则使用默认值
        let matching_rule = row.get::<_, Option<String>>("matching_rule")?
            .and_then(|rule_str| serde_json::from_str(&rule_str).ok())
            .unwrap_or_default();

        Ok(TrackSegment {
            id: row.get("id")?,
            track_id: row.get("track_id")?,
            template_material_id: row.get("template_material_id")?,
            name: row.get("name")?,
            start_time: row.get::<_, i64>("start_time")? as u64,
            end_time: row.get::<_, i64>("end_time")? as u64,
            duration: row.get::<_, i64>("duration")? as u64,
            segment_index: row.get::<_, i64>("segment_index")? as u32,
            properties: row.get("properties")?,
            matching_rule,
            created_at: chrono::DateTime::parse_from_rfc3339(&row.get::<_, String>("created_at")?)
                .unwrap()
                .with_timezone(&chrono::Utc),
            updated_at: chrono::DateTime::parse_from_rfc3339(&row.get::<_, String>("updated_at")?)
                .unwrap()
                .with_timezone(&chrono::Utc),
        })
    }

    /// 填充模板的真实素材和轨道数据
    fn fill_template_counts(&self, conn: &rusqlite::Connection, template: &mut Template) -> Result<()> {
        // 查询真实的素材数据
        let mut stmt = conn.prepare(
            "SELECT id, template_id, original_id, name, material_type, original_path,
                    remote_url, file_size, duration, width, height, upload_status,
                    file_exists, upload_success, metadata, created_at, updated_at
             FROM template_materials WHERE template_id = ?1"
        )?;

        let material_rows = stmt.query_map(params![template.id], |row| {
            self.row_to_template_material(row)
        })?;

        for material_result in material_rows {
            template.materials.push(material_result?);
        }

        // 查询真实的轨道数据
        let mut stmt = conn.prepare(
            "SELECT id, template_id, name, track_type, track_index, created_at, updated_at
             FROM tracks WHERE template_id = ?1 ORDER BY track_index"
        )?;

        let track_rows = stmt.query_map(params![template.id], |row| {
            self.row_to_track_basic(row)
        })?;

        for track_result in track_rows {
            let mut track = track_result?;

            // 查询每个轨道的真实片段数据
            let mut segment_stmt = conn.prepare(
                "SELECT id, track_id, template_material_id, name, start_time, end_time,
                        duration, segment_index, properties, matching_rule, created_at, updated_at
                 FROM track_segments WHERE track_id = ?1 ORDER BY segment_index"
            )?;

            let segment_rows = segment_stmt.query_map(params![track.id], |row| {
                self.row_to_track_segment(row)
            })?;

            for segment_result in segment_rows {
                track.segments.push(segment_result?);
            }

            template.tracks.push(track);
        }

        Ok(())
    }

    /// 更新轨道片段的匹配规则
    pub async fn update_segment_matching_rule(
        &self,
        segment_id: &str,
        matching_rule: SegmentMatchingRule,
    ) -> Result<()> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();

        let matching_rule_json = serde_json::to_string(&matching_rule)
            .map_err(|e| anyhow!("Failed to serialize matching rule: {}", e))?;

        let updated_rows = conn.execute(
            "UPDATE track_segments SET matching_rule = ?1, updated_at = ?2 WHERE id = ?3",
            params![
                matching_rule_json,
                chrono::Utc::now().to_rfc3339(),
                segment_id
            ],
        )?;

        if updated_rows == 0 {
            return Err(anyhow!("Track segment not found: {}", segment_id));
        }

        Ok(())
    }

    /// 获取轨道片段的匹配规则
    pub async fn get_segment_matching_rule(&self, segment_id: &str) -> Result<SegmentMatchingRule> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();

        let matching_rule_json: Option<String> = match conn.query_row(
            "SELECT matching_rule FROM track_segments WHERE id = ?1",
            params![segment_id],
            |row| row.get(0),
        ) {
            Ok(value) => Some(value),
            Err(rusqlite::Error::QueryReturnedNoRows) => None,
            Err(e) => return Err(anyhow!("Database error: {}", e)),
        };

        let matching_rule = matching_rule_json
            .and_then(|rule_str| serde_json::from_str(&rule_str).ok())
            .unwrap_or_default();

        Ok(matching_rule)
    }
}
