use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::event::{RoomInfo, UserInfo};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ThreadEventType {
    Created,
    Updated,
    Resolved,
    Archived,
    ParticipantJoined,
    ParticipantLeft,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum ThreadEvent {
    #[serde(rename = "thread.created")]
    Created(ThreadCreatedService),
    #[serde(rename = "thread.updated")]
    Updated(ThreadUpdatedService),
    #[serde(rename = "thread.resolved")]
    Resolved(ThreadResolvedService),
    #[serde(rename = "thread.archived")]
    Archived(ThreadArchivedService),
    #[serde(rename = "thread.participant_joined")]
    ParticipantJoined(ThreadParticipantJoinedService),
    #[serde(rename = "thread.participant_left")]
    ParticipantLeft(ThreadParticipantLeftService),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadCreatedService {
    pub id: Uuid,
    pub room: RoomInfo,
    pub parent: i64,
    pub created_by: UserInfo,
    pub participants: serde_json::Value,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadUpdatedService {
    pub id: Uuid,
    pub room: RoomInfo,
    pub last_message_at: Option<DateTime<Utc>>,
    pub last_message_preview: Option<String>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadResolvedService {
    pub id: Uuid,
    pub room: RoomInfo,
    pub resolved_by: UserInfo,
    pub resolved_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadArchivedService {
    pub id: Uuid,
    pub room: RoomInfo,
    pub archived_by: UserInfo,
    pub archived_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadParticipantJoinedService {
    pub id: Uuid,
    pub room: RoomInfo,
    pub user: UserInfo,
    pub joined_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadParticipantLeftService {
    pub id: Uuid,
    pub room: RoomInfo,
    pub user: UserInfo,
    pub left_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadCreateClient {
    pub room: RoomInfo,
    pub parent_seq: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadResolveClient {
    pub thread_id: Uuid,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadArchiveClient {
    pub thread_id: Uuid,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadLoadClient {
    pub thread_id: Uuid,
}

/// A single thread item returned in the list endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadListItem {
    pub id: Uuid,
    pub room: RoomInfo,
    pub seq: i64,
    pub parent_seq: i64,
    pub title: String,
    pub created_by: UserInfo,
    pub archived: bool,
    pub locked: bool,
    pub last_message_at: Option<DateTime<Utc>>,
    pub last_message_preview: Option<String>,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadListService {
    pub threads: Vec<ThreadListItem>,
}
