use anyhow::Result;
use rusqlite::{params, Row};
use chrono::{DateTime, Utc};
use std::sync::Arc;
use crate::data::models::custom_tag::*;
use crate::infrastructure::database::Database;

/// 自定义标签仓库
/// 遵循 Tauri 开发规范的数据访问层设计
pub struct CustomTagRepository {
    database: Arc<Database>,
}

impl CustomTagRepository {
    pub fn new(database: Arc<Database>) -> Self {
        Self { database }
    }

    /// 创建标签分类
    pub async fn create_category(&self, request: CreateCustomTagCategoryRequest) -> Result<CustomTagCategory> {
        let id = uuid::Uuid::new_v4().to_string();
        let now = Utc::now();
        
        let category = CustomTagCategory {
            id: id.clone(),
            name: request.name,
            description: request.description,
            color: request.color.unwrap_or_else(|| "#3b82f6".to_string()),
            icon: request.icon,
            sort_order: 0,
            is_active: true,
            created_at: now,
            updated_at: now,
        };

        self.database.with_connection(|conn| {
            // 获取最大排序值
            let max_sort_order: i32 = conn.query_row(
                "SELECT COALESCE(MAX(sort_order), 0) FROM custom_tag_categories",
                [],
                |row| row.get(0)
            ).unwrap_or(0);

            conn.execute(
                "INSERT INTO custom_tag_categories 
                 (id, name, description, color, icon, sort_order, is_active, created_at, updated_at) 
                 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)",
                params![
                    &category.id,
                    &category.name,
                    &category.description,
                    &category.color,
                    &category.icon,
                    max_sort_order + 1,
                    if category.is_active { 1 } else { 0 },
                    category.created_at.to_rfc3339(),
                    category.updated_at.to_rfc3339()
                ],
            )?;
            Ok(())
        })?;

        Ok(category)
    }

    /// 获取所有标签分类
    pub async fn get_all_categories(&self, active_only: bool) -> Result<Vec<CustomTagCategory>> {
        Ok(self.database.with_connection(|conn| {
            let sql = if active_only {
                "SELECT id, name, description, color, icon, sort_order, is_active, created_at, updated_at
                 FROM custom_tag_categories WHERE is_active = 1 ORDER BY sort_order, name"
            } else {
                "SELECT id, name, description, color, icon, sort_order, is_active, created_at, updated_at
                 FROM custom_tag_categories ORDER BY sort_order, name"
            };

            let mut stmt = conn.prepare(sql)?;
            let category_iter = stmt.query_map([], |row| {
                Self::row_to_category(row)
            })?;

            let mut categories = Vec::new();
            for category in category_iter {
                categories.push(category?);
            }
            Ok(categories)
        })?)
    }

    /// 根据ID获取标签分类
    pub async fn get_category_by_id(&self, id: &str) -> Result<Option<CustomTagCategory>> {
        Ok(self.database.with_connection(|conn| {
            let mut stmt = conn.prepare(
                "SELECT id, name, description, color, icon, sort_order, is_active, created_at, updated_at
                 FROM custom_tag_categories WHERE id = ?1"
            )?;

            let result = stmt.query_row([id], |row| {
                Self::row_to_category(row)
            });

            match result {
                Ok(category) => Ok(Some(category)),
                Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
                Err(e) => Err(e),
            }
        })?)
    }

    /// 更新标签分类
    pub async fn update_category(&self, id: &str, request: UpdateCustomTagCategoryRequest) -> Result<Option<CustomTagCategory>> {
        let now = Utc::now();

        Ok(self.database.with_connection(|conn| {
            let mut updates = Vec::new();
            let mut params: Vec<Box<dyn rusqlite::ToSql>> = Vec::new();

            if let Some(name) = &request.name {
                updates.push("name = ?");
                params.push(Box::new(name.clone()));
            }
            if let Some(description) = &request.description {
                updates.push("description = ?");
                params.push(Box::new(description.clone()));
            }
            if let Some(color) = &request.color {
                updates.push("color = ?");
                params.push(Box::new(color.clone()));
            }
            if let Some(icon) = &request.icon {
                updates.push("icon = ?");
                params.push(Box::new(icon.clone()));
            }
            if let Some(sort_order) = request.sort_order {
                updates.push("sort_order = ?");
                params.push(Box::new(sort_order));
            }
            if let Some(is_active) = request.is_active {
                updates.push("is_active = ?");
                params.push(Box::new(if is_active { 1 } else { 0 }));
            }

            if updates.is_empty() {
                return Ok(None);
            }

            updates.push("updated_at = ?");
            params.push(Box::new(now.to_rfc3339()));
            params.push(Box::new(id.to_string()));

            let sql = format!(
                "UPDATE custom_tag_categories SET {} WHERE id = ?",
                updates.join(", ")
            );

            let params_refs: Vec<&dyn rusqlite::ToSql> = params.iter().map(|p| p.as_ref()).collect();
            let affected = conn.execute(&sql, &params_refs[..])?;

            if affected > 0 {
                // 返回更新后的分类
                let mut stmt = conn.prepare(
                    "SELECT id, name, description, color, icon, sort_order, is_active, created_at, updated_at 
                     FROM custom_tag_categories WHERE id = ?1"
                )?;

                let category = stmt.query_row([id], |row| {
                    Ok(Self::row_to_category(row)?)
                })?;

                Ok(Some(category))
            } else {
                Ok(None)
            }
        })?)
    }

    /// 删除标签分类
    pub async fn delete_category(&self, id: &str) -> Result<bool> {
        Ok(self.database.with_connection(|conn| {
            let affected = conn.execute(
                "DELETE FROM custom_tag_categories WHERE id = ?1",
                [id],
            )?;
            Ok(affected > 0)
        })?)
    }

    /// 创建标签
    pub async fn create_tag(&self, request: CreateCustomTagRequest) -> Result<CustomTag> {
        let id = uuid::Uuid::new_v4().to_string();
        let now = Utc::now();
        
        let tag = CustomTag {
            id: id.clone(),
            category_id: request.category_id,
            name: request.name,
            description: request.description,
            color: request.color,
            sort_order: 0,
            usage_count: 0,
            is_active: true,
            created_at: now,
            updated_at: now,
        };

        self.database.with_connection(|conn| {
            // 获取该分类下的最大排序值
            let max_sort_order: i32 = conn.query_row(
                "SELECT COALESCE(MAX(sort_order), 0) FROM custom_tags WHERE category_id = ?1",
                [&tag.category_id],
                |row| row.get(0)
            ).unwrap_or(0);

            conn.execute(
                "INSERT INTO custom_tags 
                 (id, category_id, name, description, color, sort_order, usage_count, is_active, created_at, updated_at) 
                 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)",
                params![
                    &tag.id,
                    &tag.category_id,
                    &tag.name,
                    &tag.description,
                    &tag.color,
                    max_sort_order + 1,
                    tag.usage_count,
                    if tag.is_active { 1 } else { 0 },
                    tag.created_at.to_rfc3339(),
                    tag.updated_at.to_rfc3339()
                ],
            )?;
            Ok(())
        })?;

        Ok(tag)
    }

    /// 获取标签列表
    pub async fn get_tags(&self, filter: TagFilter) -> Result<Vec<CustomTagWithCategory>> {
        Ok(self.database.with_connection(|conn| {
            let mut where_clauses = Vec::new();
            let mut params: Vec<Box<dyn rusqlite::ToSql>> = Vec::new();

            if let Some(category_ids) = &filter.category_ids {
                if !category_ids.is_empty() {
                    let placeholders = category_ids.iter().map(|_| "?").collect::<Vec<_>>().join(",");
                    where_clauses.push(format!("t.category_id IN ({})", placeholders));
                    for id in category_ids {
                        params.push(Box::new(id.clone()));
                    }
                }
            }

            if let Some(name_search) = &filter.name_search {
                where_clauses.push("t.name LIKE ?".to_string());
                params.push(Box::new(format!("%{}%", name_search)));
            }

            if let Some(active_only) = filter.active_only {
                if active_only {
                    where_clauses.push("t.is_active = 1".to_string());
                    where_clauses.push("c.is_active = 1".to_string());
                }
            }

            let where_clause = if where_clauses.is_empty() {
                String::new()
            } else {
                format!("WHERE {}", where_clauses.join(" AND "))
            };

            let sql = format!(
                "SELECT t.id, t.category_id, t.name, t.description, t.color, t.sort_order,
                        t.usage_count, t.is_active, t.created_at, t.updated_at,
                        c.id, c.name, c.description, c.color, c.icon, c.sort_order,
                        c.is_active, c.created_at, c.updated_at
                 FROM custom_tags t
                 JOIN custom_tag_categories c ON t.category_id = c.id
                 {} ORDER BY c.sort_order, t.sort_order, t.name",
                where_clause
            );

            let mut stmt = conn.prepare(&sql)?;
            let params_refs: Vec<&dyn rusqlite::ToSql> = params.iter().map(|p| p.as_ref()).collect();
            let tag_iter = stmt.query_map(&params_refs[..], |row| {
                let tag = Self::row_to_tag(row)?;
                let category = Self::row_to_category_from_join(row, 10)?;
                Ok(CustomTagWithCategory { tag, category })
            })?;

            let mut tags = Vec::new();
            for tag in tag_iter {
                tags.push(tag?);
            }
            Ok(tags)
        })?)
    }

    /// 将数据库行转换为标签分类
    fn row_to_category(row: &Row) -> rusqlite::Result<CustomTagCategory> {
        let created_at_str: String = row.get(7)?;
        let updated_at_str: String = row.get(8)?;

        let created_at = DateTime::parse_from_rfc3339(&created_at_str)
            .map_err(|_e| rusqlite::Error::InvalidColumnType(7, "created_at".to_string(), rusqlite::types::Type::Text))?
            .with_timezone(&Utc);
        let updated_at = DateTime::parse_from_rfc3339(&updated_at_str)
            .map_err(|_e| rusqlite::Error::InvalidColumnType(8, "updated_at".to_string(), rusqlite::types::Type::Text))?
            .with_timezone(&Utc);

        Ok(CustomTagCategory {
            id: row.get(0)?,
            name: row.get(1)?,
            description: row.get(2)?,
            color: row.get(3)?,
            icon: row.get(4)?,
            sort_order: row.get(5)?,
            is_active: row.get::<_, i32>(6)? != 0,
            created_at,
            updated_at,
        })
    }

    /// 将数据库行转换为标签分类（从JOIN查询）
    fn row_to_category_from_join(row: &Row, offset: usize) -> rusqlite::Result<CustomTagCategory> {
        let created_at_str: String = row.get(offset + 7)?;
        let updated_at_str: String = row.get(offset + 8)?;

        let created_at = DateTime::parse_from_rfc3339(&created_at_str)
            .map_err(|_e| rusqlite::Error::InvalidColumnType(offset + 7, "created_at".to_string(), rusqlite::types::Type::Text))?
            .with_timezone(&Utc);
        let updated_at = DateTime::parse_from_rfc3339(&updated_at_str)
            .map_err(|_e| rusqlite::Error::InvalidColumnType(offset + 8, "updated_at".to_string(), rusqlite::types::Type::Text))?
            .with_timezone(&Utc);

        Ok(CustomTagCategory {
            id: row.get(offset)?,
            name: row.get(offset + 1)?,
            description: row.get(offset + 2)?,
            color: row.get(offset + 3)?,
            icon: row.get(offset + 4)?,
            sort_order: row.get(offset + 5)?,
            is_active: row.get::<_, i32>(offset + 6)? != 0,
            created_at,
            updated_at,
        })
    }

    /// 将数据库行转换为标签
    fn row_to_tag(row: &Row) -> rusqlite::Result<CustomTag> {
        let created_at_str: String = row.get(8)?;
        let updated_at_str: String = row.get(9)?;

        let created_at = DateTime::parse_from_rfc3339(&created_at_str)
            .map_err(|_e| rusqlite::Error::InvalidColumnType(8, "created_at".to_string(), rusqlite::types::Type::Text))?
            .with_timezone(&Utc);
        let updated_at = DateTime::parse_from_rfc3339(&updated_at_str)
            .map_err(|_e| rusqlite::Error::InvalidColumnType(9, "updated_at".to_string(), rusqlite::types::Type::Text))?
            .with_timezone(&Utc);

        Ok(CustomTag {
            id: row.get(0)?,
            category_id: row.get(1)?,
            name: row.get(2)?,
            description: row.get(3)?,
            color: row.get(4)?,
            sort_order: row.get(5)?,
            usage_count: row.get(6)?,
            is_active: row.get::<_, i32>(7)? != 0,
            created_at,
            updated_at,
        })
    }

    /// 根据ID获取标签
    pub async fn get_tag_by_id(&self, id: &str) -> Result<Option<CustomTag>> {
        Ok(self.database.with_connection(|conn| {
            let mut stmt = conn.prepare(
                "SELECT id, category_id, name, description, color, sort_order, usage_count, is_active, created_at, updated_at
                 FROM custom_tags WHERE id = ?1"
            )?;

            let result = stmt.query_row([id], |row| {
                Self::row_to_tag(row)
            });

            match result {
                Ok(tag) => Ok(Some(tag)),
                Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
                Err(e) => Err(e),
            }
        })?)
    }

    /// 更新标签
    pub async fn update_tag(&self, id: &str, request: UpdateCustomTagRequest) -> Result<Option<CustomTag>> {
        let now = Utc::now();

        Ok(self.database.with_connection(|conn| {
            let mut updates = Vec::new();
            let mut params: Vec<Box<dyn rusqlite::ToSql>> = Vec::new();

            if let Some(name) = &request.name {
                updates.push("name = ?");
                params.push(Box::new(name.clone()));
            }
            if let Some(description) = &request.description {
                updates.push("description = ?");
                params.push(Box::new(description.clone()));
            }
            if let Some(color) = &request.color {
                updates.push("color = ?");
                params.push(Box::new(color.clone()));
            }
            if let Some(sort_order) = request.sort_order {
                updates.push("sort_order = ?");
                params.push(Box::new(sort_order));
            }
            if let Some(is_active) = request.is_active {
                updates.push("is_active = ?");
                params.push(Box::new(if is_active { 1 } else { 0 }));
            }

            if updates.is_empty() {
                return Ok(None);
            }

            updates.push("updated_at = ?");
            params.push(Box::new(now.to_rfc3339()));
            params.push(Box::new(id.to_string()));

            let sql = format!(
                "UPDATE custom_tags SET {} WHERE id = ?",
                updates.join(", ")
            );

            let params_refs: Vec<&dyn rusqlite::ToSql> = params.iter().map(|p| p.as_ref()).collect();
            let affected = conn.execute(&sql, &params_refs[..])?;

            if affected > 0 {
                // 返回更新后的标签
                let mut stmt = conn.prepare(
                    "SELECT id, category_id, name, description, color, sort_order, usage_count, is_active, created_at, updated_at
                     FROM custom_tags WHERE id = ?1"
                )?;

                let tag = stmt.query_row([id], |row| {
                    Self::row_to_tag(row)
                })?;

                Ok(Some(tag))
            } else {
                Ok(None)
            }
        })?)
    }

    /// 删除标签
    pub async fn delete_tag(&self, id: &str) -> Result<bool> {
        Ok(self.database.with_connection(|conn| {
            let affected = conn.execute(
                "DELETE FROM custom_tags WHERE id = ?1",
                [id],
            )?;
            Ok(affected > 0)
        })?)
    }

    /// 增加标签使用次数
    pub async fn increment_tag_usage(&self, tag_id: &str) -> Result<()> {
        Ok(self.database.with_connection(|conn| {
            conn.execute(
                "UPDATE custom_tags SET usage_count = usage_count + 1, updated_at = ?1 WHERE id = ?2",
                [&Utc::now().to_rfc3339(), tag_id],
            )?;
            Ok(())
        })?)
    }

    /// 创建标签关联
    pub async fn create_tag_association(&self, tag_id: &str, entity_type: &str, entity_id: &str) -> Result<TagAssociation> {
        let association = TagAssociation {
            id: uuid::Uuid::new_v4().to_string(),
            tag_id: tag_id.to_string(),
            entity_type: entity_type.to_string(),
            entity_id: entity_id.to_string(),
            created_at: Utc::now(),
        };

        self.database.with_connection(|conn| {
            conn.execute(
                "INSERT OR IGNORE INTO tag_associations (id, tag_id, entity_type, entity_id, created_at)
                 VALUES (?1, ?2, ?3, ?4, ?5)",
                params![
                    &association.id,
                    &association.tag_id,
                    &association.entity_type,
                    &association.entity_id,
                    association.created_at.to_rfc3339()
                ],
            )?;
            Ok(())
        })?;

        // 增加标签使用次数
        self.increment_tag_usage(tag_id).await?;

        Ok(association)
    }

    /// 删除标签关联
    pub async fn delete_tag_association(&self, tag_id: &str, entity_type: &str, entity_id: &str) -> Result<bool> {
        Ok(self.database.with_connection(|conn| {
            let affected = conn.execute(
                "DELETE FROM tag_associations WHERE tag_id = ?1 AND entity_type = ?2 AND entity_id = ?3",
                [tag_id, entity_type, entity_id],
            )?;
            Ok(affected > 0)
        })?)
    }

    /// 获取实体的标签
    pub async fn get_entity_tags(&self, entity_type: &str, entity_id: &str) -> Result<Vec<CustomTagWithCategory>> {
        Ok(self.database.with_connection(|conn| {
            let sql = "SELECT t.id, t.category_id, t.name, t.description, t.color, t.sort_order,
                              t.usage_count, t.is_active, t.created_at, t.updated_at,
                              c.id, c.name, c.description, c.color, c.icon, c.sort_order,
                              c.is_active, c.created_at, c.updated_at
                       FROM custom_tags t
                       JOIN custom_tag_categories c ON t.category_id = c.id
                       JOIN tag_associations a ON t.id = a.tag_id
                       WHERE a.entity_type = ?1 AND a.entity_id = ?2 AND t.is_active = 1 AND c.is_active = 1
                       ORDER BY c.sort_order, t.sort_order, t.name";

            let mut stmt = conn.prepare(sql)?;
            let tag_iter = stmt.query_map([entity_type, entity_id], |row| {
                let tag = Self::row_to_tag(row)?;
                let category = Self::row_to_category_from_join(row, 10)?;
                Ok(CustomTagWithCategory { tag, category })
            })?;

            let mut tags = Vec::new();
            for tag in tag_iter {
                tags.push(tag?);
            }
            Ok(tags)
        })?)
    }

    /// 获取标签统计信息
    pub async fn get_tag_statistics(&self) -> Result<TagStatistics> {
        Ok(self.database.with_connection(|conn| {
            // 获取总体统计
            let total_tags: i32 = conn.query_row("SELECT COUNT(*) FROM custom_tags", [], |row| row.get(0))?;
            let active_tags: i32 = conn.query_row("SELECT COUNT(*) FROM custom_tags WHERE is_active = 1", [], |row| row.get(0))?;
            let total_categories: i32 = conn.query_row("SELECT COUNT(*) FROM custom_tag_categories", [], |row| row.get(0))?;
            let active_categories: i32 = conn.query_row("SELECT COUNT(*) FROM custom_tag_categories WHERE is_active = 1", [], |row| row.get(0))?;
            let total_associations: i32 = conn.query_row("SELECT COUNT(*) FROM tag_associations", [], |row| row.get(0))?;

            // 获取按分类统计
            let mut stmt = conn.prepare(
                "SELECT c.id, c.name, c.description, c.color, c.icon, c.sort_order, c.is_active, c.created_at, c.updated_at,
                        COUNT(t.id) as tag_count,
                        COUNT(a.id) as association_count
                 FROM custom_tag_categories c
                 LEFT JOIN custom_tags t ON c.id = t.category_id AND t.is_active = 1
                 LEFT JOIN tag_associations a ON t.id = a.tag_id
                 WHERE c.is_active = 1
                 GROUP BY c.id
                 ORDER BY c.sort_order, c.name"
            )?;

            let category_iter = stmt.query_map([], |row| {
                let category = Self::row_to_category(row)?;
                let tag_count: i32 = row.get(9)?;
                let association_count: i32 = row.get(10)?;
                Ok(CategoryTagCount {
                    category,
                    tag_count,
                    association_count,
                })
            })?;

            let mut by_category = Vec::new();
            for category_count in category_iter {
                by_category.push(category_count?);
            }

            Ok(TagStatistics {
                total_tags,
                active_tags,
                total_categories,
                active_categories,
                total_associations,
                by_category,
            })
        })?)
    }
}
