use crate::domain::entities::{blocked_ip, blocked_sender};
use anyhow::Result;
use sea_orm::{
    ActiveModelTrait, ColumnTrait, Condition, DatabaseConnection, EntityTrait, QueryFilter,
    QueryOrder, Set,
};

/// 黑名单数据访问（发件人 + IP）
pub struct BlacklistRepository {
    db: DatabaseConnection,
}

impl BlacklistRepository {
    pub fn new(db: DatabaseConnection) -> Self {
        Self { db }
    }

    fn active_condition<C>(col: C) -> Condition
    where
        C: sea_orm::ColumnTrait,
    {
        let now = chrono::Utc::now().naive_utc();
        Condition::any().add(col.is_null()).add(col.gt(now))
    }

    // ===== 发件黑名单 =====

    /// 查询某 kind+value 是否在生效中的黑名单
    pub async fn find_active_sender(
        &self,
        kind: &str,
        value: &str,
    ) -> Result<Option<blocked_sender::Model>> {
        Ok(blocked_sender::Entity::find()
            .filter(blocked_sender::Column::Kind.eq(kind))
            .filter(blocked_sender::Column::Value.eq(value))
            .filter(Self::active_condition(blocked_sender::Column::ExpiresAt))
            .one(&self.db)
            .await?)
    }

    pub async fn add_sender(
        &self,
        kind: String,
        value: String,
        reason: String,
        source: String,
        expires_at: Option<chrono::NaiveDateTime>,
    ) -> Result<blocked_sender::Model> {
        let model = blocked_sender::ActiveModel {
            kind: Set(kind),
            value: Set(value),
            reason: Set(reason),
            source: Set(source),
            expires_at: Set(expires_at),
            ..Default::default()
        };
        Ok(model.insert(&self.db).await?)
    }

    pub async fn list_senders(&self) -> Result<Vec<blocked_sender::Model>> {
        Ok(blocked_sender::Entity::find()
            .order_by_desc(blocked_sender::Column::CreatedAt)
            .all(&self.db)
            .await?)
    }

    pub async fn delete_sender(&self, id: i64) -> Result<()> {
        blocked_sender::Entity::delete_by_id(id)
            .exec(&self.db)
            .await?;
        Ok(())
    }

    // ===== IP 黑名单 =====

    pub async fn find_active_ip(&self, ip: &str) -> Result<Option<blocked_ip::Model>> {
        Ok(blocked_ip::Entity::find()
            .filter(blocked_ip::Column::Ip.eq(ip))
            .filter(Self::active_condition(blocked_ip::Column::ExpiresAt))
            .one(&self.db)
            .await?)
    }

    pub async fn add_ip(
        &self,
        ip: String,
        reason: String,
        source: String,
        expires_at: Option<chrono::NaiveDateTime>,
    ) -> Result<blocked_ip::Model> {
        let model = blocked_ip::ActiveModel {
            ip: Set(ip),
            reason: Set(reason),
            source: Set(source),
            expires_at: Set(expires_at),
            ..Default::default()
        };
        Ok(model.insert(&self.db).await?)
    }

    pub async fn list_ips(&self) -> Result<Vec<blocked_ip::Model>> {
        Ok(blocked_ip::Entity::find()
            .order_by_desc(blocked_ip::Column::CreatedAt)
            .all(&self.db)
            .await?)
    }

    pub async fn delete_ip(&self, id: i64) -> Result<()> {
        blocked_ip::Entity::delete_by_id(id).exec(&self.db).await?;
        Ok(())
    }
}
