use anyhow::{anyhow, Result};

use crate::{claude, keychain, store};

/// Core switch logic. Snapshots the current account's tokens, then loads and
/// activates the target account.
pub fn switch_to(target_num: u32) -> Result<()> {
    let mut s = store::load_store()?;

    let target_info = s
        .accounts
        .get(&target_num.to_string())
        .ok_or_else(|| anyhow!("account {} not found", target_num))?
        .clone();

    // --- 1. Snapshot current active account (tokens may have refreshed since `add`) ---
    // Only re-snapshot if ~/.claude.json actually matches the account cloaked thinks
    // is active. If there's a mismatch we leave the stored state untouched — blindly
    // snapshotting the wrong account's data is what causes config corruption.
    if let Some(current_num) = s.active {
        if current_num != target_num {
            if let Some(current_info) = s.accounts.get(&current_num.to_string()).cloned() {
                let live_email = claude::read_claude_config()
                    .ok()
                    .and_then(|c| claude::extract_oauth_account(&c).ok())
                    .and_then(|o| claude::extract_email(&o).ok());

                if live_email.as_deref().map(|e| e.eq_ignore_ascii_case(&current_info.email))
                    == Some(true)
                {
                    // ~/.claude.json matches — safe to refresh the stored snapshot.
                    if let Ok(creds) = keychain::read_claude_credentials() {
                        if !creds.is_empty() {
                            store::save_account_credentials(
                                current_num,
                                &current_info.email,
                                &creds,
                            )?;
                        }
                    }
                    if let Ok(config) = claude::read_claude_config() {
                        if let Ok(oauth) = claude::extract_oauth_account(&config) {
                            store::save_account_config(current_num, &current_info.email, &oauth)?;
                        }
                    }
                }
                // If emails don't match, skip re-snapshot silently.
                // The stored state is the last known good snapshot.
            }
        }
    }

    // --- 2. Load target account's credentials and oauthAccount ---
    let target_creds = store::load_account_credentials(target_num, &target_info.email)?;
    let target_oauth = store::load_account_config(target_num, &target_info.email)?;

    // --- 3. Write target into Claude Code's live config ---
    keychain::write_claude_credentials(&target_creds)?;

    let mut config = claude::read_claude_config()?;
    claude::inject_oauth_account(&mut config, &target_oauth)?;
    claude::write_claude_config(&config)?;

    // --- 4. Update cloaked state ---
    s.active = Some(target_num);
    store::save_store(&s)?;

    println!(
        "Switched to account {} ({}). Restart Claude Code for the change to take effect.",
        target_num, target_info.email
    );

    Ok(())
}
