use anyhow::Result;
use rusqlite::params;
use std::sync::Arc;
use crate::data::models::outfit_favorite::OutfitFavorite;
use crate::data::models::outfit_recommendation::OutfitRecommendation;
use crate::infrastructure::database::Database;

/// 穿搭方案收藏数据访问层
pub struct OutfitFavoriteRepository {
    database: Arc<Database>,
}

impl OutfitFavoriteRepository {
    /// 创建新的收藏仓库实例
    pub fn new(database: Arc<Database>) -> Self {
        Self { database }
    }

    /// 保存方案到收藏
    pub async fn save_to_favorites(
        &self,
        recommendation: OutfitRecommendation,
        custom_name: Option<String>,
    ) -> Result<OutfitFavorite> {
        let favorite = OutfitFavorite::new(recommendation, custom_name);
        
        // 序列化方案数据
        let recommendation_json = serde_json::to_string(&favorite.recommendation_data)?;
        
        self.database.with_connection(|conn| {
            conn.execute(
                "INSERT INTO outfit_favorites (id, recommendation_data, custom_name, created_at)
                 VALUES (?1, ?2, ?3, ?4)",
                params![
                    &favorite.id,
                    &recommendation_json,
                    &favorite.custom_name,
                    favorite.created_at.to_rfc3339()
                ],
            )?;
            Ok(())
        })?;

        Ok(favorite)
    }

    /// 获取所有收藏的方案
    pub async fn get_all_favorites(&self) -> Result<Vec<OutfitFavorite>> {
        Ok(self.database.with_connection(|conn| {
            let mut stmt = conn.prepare(
                "SELECT id, recommendation_data, custom_name, created_at
                 FROM outfit_favorites
                 ORDER BY created_at DESC"
            )?;

            let favorites = stmt.query_map([], |row| {
                let id: String = row.get(0)?;
                let recommendation_json: String = row.get(1)?;
                let custom_name: Option<String> = row.get(2)?;
                let created_at_str: String = row.get(3)?;

                // 反序列化方案数据
                let recommendation_data: OutfitRecommendation =
                    serde_json::from_str(&recommendation_json)
                        .map_err(|_e| rusqlite::Error::InvalidColumnType(
                            0, "recommendation_data".to_string(), rusqlite::types::Type::Text
                        ))?;

                let created_at = chrono::DateTime::parse_from_rfc3339(&created_at_str)
                    .map_err(|_| rusqlite::Error::InvalidColumnType(
                        3, "created_at".to_string(), rusqlite::types::Type::Text
                    ))?
                    .with_timezone(&chrono::Utc);

                Ok(OutfitFavorite {
                    id,
                    recommendation_data,
                    custom_name,
                    created_at,
                })
            })?.collect::<Result<Vec<_>, _>>()?;

            Ok(favorites)
        })?)
    }

    /// 根据ID获取收藏方案
    pub async fn get_favorite_by_id(&self, favorite_id: &str) -> Result<Option<OutfitFavorite>> {
        Ok(self.database.with_connection(|conn| {
            let mut stmt = conn.prepare(
                "SELECT id, recommendation_data, custom_name, created_at
                 FROM outfit_favorites
                 WHERE id = ?1"
            )?;

            let result = stmt.query_row([favorite_id], |row| {
                let id: String = row.get(0)?;
                let recommendation_json: String = row.get(1)?;
                let custom_name: Option<String> = row.get(2)?;
                let created_at_str: String = row.get(3)?;

                // 反序列化方案数据
                let recommendation_data: OutfitRecommendation =
                    serde_json::from_str(&recommendation_json)
                        .map_err(|_e| rusqlite::Error::InvalidColumnType(
                            0, "recommendation_data".to_string(), rusqlite::types::Type::Text
                        ))?;

                let created_at = chrono::DateTime::parse_from_rfc3339(&created_at_str)
                    .map_err(|_| rusqlite::Error::InvalidColumnType(
                        3, "created_at".to_string(), rusqlite::types::Type::Text
                    ))?
                    .with_timezone(&chrono::Utc);

                Ok(OutfitFavorite {
                    id,
                    recommendation_data,
                    custom_name,
                    created_at,
                })
            });

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

    /// 从收藏中移除方案
    pub async fn remove_from_favorites(&self, favorite_id: &str) -> Result<bool> {
        let rows_affected = self.database.with_connection(|conn| {
            conn.execute(
                "DELETE FROM outfit_favorites WHERE id = ?1",
                [favorite_id],
            )
        })?;

        Ok(rows_affected > 0)
    }

    /// 更新收藏方案的自定义名称
    pub async fn update_custom_name(
        &self,
        favorite_id: &str,
        custom_name: Option<String>,
    ) -> Result<bool> {
        let rows_affected = self.database.with_connection(|conn| {
            conn.execute(
                "UPDATE outfit_favorites SET custom_name = ?1 WHERE id = ?2",
                params![custom_name, favorite_id],
            )
        })?;

        Ok(rows_affected > 0)
    }

    /// 检查方案是否已收藏（基于方案ID）
    pub async fn is_recommendation_favorited(&self, recommendation_id: &str) -> Result<bool> {
        let count: i64 = self.database.with_connection(|conn| {
            conn.query_row(
                "SELECT COUNT(*) FROM outfit_favorites 
                 WHERE json_extract(recommendation_data, '$.id') = ?1",
                [recommendation_id],
                |row| row.get(0),
            )
        })?;

        Ok(count > 0)
    }

    /// 获取收藏总数
    pub async fn get_favorites_count(&self) -> Result<usize> {
        let count: i64 = self.database.with_connection(|conn| {
            conn.query_row(
                "SELECT COUNT(*) FROM outfit_favorites",
                [],
                |row| row.get(0),
            )
        })?;

        Ok(count as usize)
    }
}
