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

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum TrackerType {
    GitHub,
    GitLab,
    Gitea,
    Jira,
}

impl std::fmt::Display for TrackerType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::GitHub => write!(f, "github"),
            Self::GitLab => write!(f, "gitlab"),
            Self::Gitea => write!(f, "gitea"),
            Self::Jira => write!(f, "jira"),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum IssueStatus {
    Open,
    InProgress,
    Closed,
    Resolved,
}

impl std::fmt::Display for IssueStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Open => write!(f, "open"),
            Self::InProgress => write!(f, "in_progress"),
            Self::Closed => write!(f, "closed"),
            Self::Resolved => write!(f, "resolved"),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrackerIssue {
    #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
    pub id: Option<bson::oid::ObjectId>,
    pub finding_id: String,
    pub tracker_type: TrackerType,
    pub external_id: String,
    pub external_url: String,
    pub title: String,
    pub status: IssueStatus,
    #[serde(with = "super::serde_helpers::bson_datetime")]
    pub created_at: DateTime<Utc>,
    #[serde(with = "super::serde_helpers::bson_datetime")]
    pub updated_at: DateTime<Utc>,
}

impl TrackerIssue {
    pub fn new(
        finding_id: String,
        tracker_type: TrackerType,
        external_id: String,
        external_url: String,
        title: String,
    ) -> Self {
        let now = Utc::now();
        Self {
            id: None,
            finding_id,
            tracker_type,
            external_id,
            external_url,
            title,
            status: IssueStatus::Open,
            created_at: now,
            updated_at: now,
        }
    }
}
