use std::fmt::{Debug, Display};

use serde::{Deserialize, Serialize};

#[derive(Clone, PartialEq, Eq, Deserialize, Serialize, Default)]
pub struct User {
    pub username: String,
    pub displayname: Option<String>,
    pub email: String,
    pub password: String,
    pub pw_verify: String,
}

impl Debug for User {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self == &User::default() {
            write!(f, "Default User")
        } else {
            let pw_check = if self.password == self.pw_verify {
                "password matched"
            } else {
                "PASSWORD MISMATCH"
            };
            f.debug_struct("User")
                .field("username", &self.username)
                .field("displayname", &self.displayname)
                .field("email", &self.email)
                .field("pw-check", &pw_check)
                .finish()
        }
    }
}

impl Display for User {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let uname = &self.username;
        let dname = if let Some(ref n) = self.displayname {
            n
        } else {
            ""
        };
        let email = &self.email;
        write!(
            f,
            "Username: '{uname}', Displayname: '{dname}', Email: '{email}'"
        )
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
pub struct ForgejoUser<'u> {
    pub username: &'u str,
    pub full_name: String,
    pub email: &'u str,
    pub password: &'u str,
    pub must_change_password: bool,
}

impl<'u> From<&'u User> for ForgejoUser<'u> {
    fn from(user: &'u User) -> Self {
        Self {
            username: &user.username,
            full_name: user.displayname.to_owned().unwrap_or(user.username.clone()),
            email: &user.email,
            password: &user.password,
            must_change_password: false,
        }
    }
}