use serde::{Deserialize, Serialize};

/// Overall PR status.  Combines review decision and merge readiness into a
/// single enum for quick querying.
///
/// Stored as `"draft"`, `"open"`, `"approved"`, `"changes_requested"`,
/// `"conflict"`, `"merged"`, or `"closed"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrStatus {
    Draft,
    Open,
    Approved,
    ChangesRequested,
    Conflict,
    Merged,
    Closed,
}

impl std::fmt::Display for PrStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PrStatus::Draft => write!(f, "draft"),
            PrStatus::Open => write!(f, "open"),
            PrStatus::Approved => write!(f, "approved"),
            PrStatus::ChangesRequested => write!(f, "changes_requested"),
            PrStatus::Conflict => write!(f, "conflict"),
            PrStatus::Merged => write!(f, "merged"),
            PrStatus::Closed => write!(f, "closed"),
        }
    }
}

impl std::str::FromStr for PrStatus {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "draft" => Ok(PrStatus::Draft),
            "open" => Ok(PrStatus::Open),
            "approved" => Ok(PrStatus::Approved),
            "changes_requested" => Ok(PrStatus::ChangesRequested),
            "conflict" => Ok(PrStatus::Conflict),
            "merged" => Ok(PrStatus::Merged),
            "closed" => Ok(PrStatus::Closed),
            _ => Err("unknown PR status"),
        }
    }
}

/// Overall review decision from a single reviewer.  Stored as `"pending"`,
/// `"approved"`, `"changes_requested"`, or `"comment"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ReviewState {
    Pending,
    Approved,
    ChangesRequested,
    Comment,
}

impl std::fmt::Display for ReviewState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ReviewState::Pending => write!(f, "pending"),
            ReviewState::Approved => write!(f, "approved"),
            ReviewState::ChangesRequested => write!(f, "changes_requested"),
            ReviewState::Comment => write!(f, "comment"),
        }
    }
}

impl std::str::FromStr for ReviewState {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "pending" => Ok(ReviewState::Pending),
            "approved" => Ok(ReviewState::Approved),
            "changes_requested" => Ok(ReviewState::ChangesRequested),
            "comment" => Ok(ReviewState::Comment),
            _ => Err("unknown review state"),
        }
    }
}

pub use pull_request::Entity as PullRequest;
pub use pull_request_commit::Entity as PullRequestCommit;
pub use pull_request_review::Entity as PullRequestReview;
pub use pull_request_review_comment::Entity as PullRequestReviewComment;
pub use pull_request_review_request::Entity as PullRequestReviewRequest;

pub mod pull_request;
pub mod pull_request_commit;
pub mod pull_request_review;
pub mod pull_request_review_comment;
pub mod pull_request_review_request;
