use crate::{api, config};

/// `sprouts whoami` — fetch the current user from `GET /auth/me`.
///
/// If the access token has expired, transparently rotate it with the saved
/// refresh token (so an active session never forces a re-login).
pub fn run() -> anyhow::Result<()> {
    let mut config = config::load()?;
    let Some(token) = config.token.clone() else {
        println!("Not logged in. Run `sprouts login`.");
        return Ok(());
    };
    let api_url = config.api_url();

    let user = match api::me(&api_url, &token) {
        Ok(user) => user,
        Err(api::Error::Unauthorized) => match refresh_session(&mut config, &api_url)? {
            Some(user) => user,
            None => {
                println!("Session expired. Run `sprouts login`.");
                return Ok(());
            }
        },
        Err(err) => return Err(anyhow::anyhow!("{err}")),
    };

    println!("Logged in.");
    if let Some(email) = &user.email {
        println!("  email:  {email}");
    }
    if let Some(wallet) = &user.wallet_address {
        println!("  wallet: {wallet}");
    }
    println!("  user:   {}", user.id);
    Ok(())
}

/// Rotate the session with the saved refresh token, persist it, and return the
/// user. Returns `None` if there's no refresh token or it's no longer valid.
fn refresh_session(config: &mut config::Config, api_url: &str) -> anyhow::Result<Option<api::User>> {
    let Some(refresh_token) = config.refresh_token.clone() else {
        return Ok(None);
    };
    match api::refresh(api_url, &refresh_token) {
        Ok(session) => {
            config.token = Some(session.token);
            config.refresh_token = Some(session.refresh_token);
            config.user_id = Some(session.user.id.clone());
            config.email = session.user.email.clone();
            config::save(config)?;
            Ok(Some(session.user))
        }
        Err(_) => Ok(None),
    }
}
