use std::{fmt::Display, str::FromStr};

use miette::Diagnostic;
use thiserror::Error;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IdpProvider {
    Auth0,
    Okta,
}

#[derive(Error, Debug, Diagnostic)]
pub enum ParseError {
    #[error("Invalid IDP Provider: {0} (must be 'auth0' or 'okta')")]
    InvalidProvider(String),
}

impl FromStr for IdpProvider {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "auth0" => Ok(IdpProvider::Auth0),
            "okta" => Ok(IdpProvider::Okta),
            _ => Err(ParseError::InvalidProvider(s.to_string())),
        }
    }
}

impl Display for IdpProvider {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Auth0 => f.write_str("auth0"),
            Self::Okta => f.write_str("okta"),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_round_trip() {
        for input in ["auth0", "okta"] {
            let parsed: IdpProvider = input.parse().unwrap();
            assert_eq!(input, parsed.to_string());
        }
    }
}
