use crate::domain::entities::email;
use anyhow::Result;
use sea_orm::{
    ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QueryOrder,
    QuerySelect, Set,
};

/// 接收邮件数据访问
pub struct EmailRepository {
    db: DatabaseConnection,
}

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

    #[allow(dead_code)]
    pub async fn insert(&self, model: email::ActiveModel) -> Result<email::Model> {
        Ok(model.insert(&self.db).await?)
    }

    pub async fn find_by_id(&self, id: i64) -> Result<Option<email::Model>> {
        Ok(email::Entity::find_by_id(id).one(&self.db).await?)
    }

    /// 分页列出某邮箱的邮件（按接收时间倒序）
    pub async fn list_by_mailbox(
        &self,
        mailbox_id: i64,
        limit: u64,
        offset: u64,
    ) -> Result<Vec<email::Model>> {
        Ok(email::Entity::find()
            .filter(email::Column::MailboxId.eq(mailbox_id))
            .filter(email::Column::Status.eq("received"))
            .order_by_desc(email::Column::ReceivedAt)
            .offset(offset)
            .limit(limit)
            .all(&self.db)
            .await?)
    }

    #[allow(dead_code)]
    pub async fn delete_by_id(&self, id: i64) -> Result<()> {
        email::Entity::delete_by_id(id).exec(&self.db).await?;
        Ok(())
    }

    #[allow(dead_code)]
    pub async fn delete_by_mailbox(&self, mailbox_id: i64) -> Result<u64> {
        let res = email::Entity::delete_many()
            .filter(email::Column::MailboxId.eq(mailbox_id))
            .exec(&self.db)
            .await?;
        Ok(res.rows_affected)
    }

    /// 列出已过期邮件（清理任务用）
    pub async fn list_expired(&self, batch_size: u64) -> Result<Vec<email::Model>> {
        let now = chrono::Utc::now().naive_utc();
        Ok(email::Entity::find()
            .filter(email::Column::ExpiresAt.lte(now))
            .limit(batch_size)
            .all(&self.db)
            .await?)
    }

    /// 更新状态（如隔离邮件放行）
    #[allow(dead_code)]
    pub async fn update_status(&self, id: i64, status: &str) -> Result<()> {
        let m = email::Entity::find_by_id(id)
            .one(&self.db)
            .await?
            .ok_or_else(|| anyhow::anyhow!("邮件不存在"))?;
        let mut active: email::ActiveModel = m.into();
        active.status = Set(status.into());
        active.update(&self.db).await?;
        Ok(())
    }

    #[allow(dead_code)]
    pub async fn set_abuse_score(&self, id: i64, score: i32) -> Result<()> {
        let m = email::Entity::find_by_id(id)
            .one(&self.db)
            .await?
            .ok_or_else(|| anyhow::anyhow!("邮件不存在"))?;
        let mut active: email::ActiveModel = m.into();
        active.abuse_score = Set(score);
        active.update(&self.db).await?;
        Ok(())
    }
}
