use chrono::{DateTime, Utc};
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
#[serde(rename_all = "snake_case")]
pub enum NotificationType {
    #[sea_orm(string_value = "mention")]
    Mention,
    #[sea_orm(string_value = "invitation")]
    Invitation,
    #[sea_orm(string_value = "role_change")]
    RoleChange,
    #[sea_orm(string_value = "room_created")]
    RoomCreated,
    #[sea_orm(string_value = "room_deleted")]
    RoomDeleted,
    #[sea_orm(string_value = "system_announcement")]
    SystemAnnouncement,
}

impl std::fmt::Display for NotificationType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            NotificationType::Mention => "mention",
            NotificationType::Invitation => "invitation",
            NotificationType::RoleChange => "role_change",
            NotificationType::RoomCreated => "room_created",
            NotificationType::RoomDeleted => "room_deleted",
            NotificationType::SystemAnnouncement => "system_announcement",
        };
        write!(f, "{}", s)
    }
}

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "room_notifications")]
#[serde(rename_all = "camelCase")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: Uuid,
    #[sea_orm(nullable)]
    pub room: Option<Uuid>,
    #[sea_orm(nullable)]
    pub project: Option<Uuid>,
    #[sea_orm(nullable)]
    pub user_id: Option<Uuid>,
    #[sea_orm(column_name = "notification_type")]
    pub notification_type: NotificationType,
    #[sea_orm(nullable)]
    pub related_message_id: Option<Uuid>,
    #[sea_orm(nullable)]
    pub related_user_id: Option<Uuid>,
    #[sea_orm(nullable)]
    pub related_room_id: Option<Uuid>,
    #[sea_orm(column_name = "title")]
    pub title: String,
    #[sea_orm(column_name = "content", nullable)]
    pub content: Option<String>,
    #[sea_orm(column_name = "metadata", nullable)]
    pub metadata: Option<Json>,
    #[sea_orm(column_name = "is_read")]
    pub is_read: bool,
    #[sea_orm(column_name = "is_archived")]
    pub is_archived: bool,
    #[sea_orm(column_name = "created_at")]
    pub created_at: DateTime<Utc>,
    #[sea_orm(column_name = "read_at", nullable)]
    pub read_at: Option<DateTime<Utc>>,
    #[sea_orm(column_name = "expires_at", nullable)]
    pub expires_at: Option<DateTime<Utc>>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
    #[sea_orm(
        belongs_to = "super::room::Entity",
        from = "Column::Room",
        to = "super::room::Column::Id"
    )]
    Room,
}

impl ActiveModelBehavior for ActiveModel {}
