use std::collections::BTreeSet;
use std::fs;
use std::path::PathBuf;

use anyhow::{bail, Context, Result};
use inquire::Confirm;

use crate::project;
use crate::state::{MachineState, ProjectState, PROJECT_STATE_DIR};
use crate::ui::style;

use super::sync;

pub fn run(yes: bool) -> Result<()> {
    let cwd = std::env::current_dir().context("getting current directory")?;
    let Some(root) = project::discover_root(&cwd) else {
        bail!("not in a project (cwd: {})", cwd.display());
    };

    let state = ProjectState::load(&root)?;
    let wired: BTreeSet<PathBuf> = state
        .packages
        .values()
        .flat_map(|p| p.blocks.iter().map(|b| b.path.clone()))
        .collect();

    println!("aimgr deinit will:");
    if !wired.is_empty() {
        println!("  unwire managed blocks from:");
        for rel in &wired {
            println!("    {}", root.join(rel).display());
        }
    }
    println!("  remove {}", root.join(PROJECT_STATE_DIR).display());
    println!("  deregister {} from machine state", root.display());

    if !yes {
        let ok = Confirm::new("Proceed?").with_default(false).prompt()?;
        if !ok {
            return Ok(());
        }
    }

    for (name, pkg) in &state.packages {
        for rec in &pkg.blocks {
            sync::unwire_block(&root, name, rec)?;
        }
    }

    let aimgr_dir = root.join(PROJECT_STATE_DIR);
    if aimgr_dir.exists() {
        fs::remove_dir_all(&aimgr_dir)
            .with_context(|| format!("removing {}", aimgr_dir.display()))?;
    }

    let mut machine = MachineState::load()?;
    let before = machine.projects.len();
    machine.projects.retain(|p| p != &root);
    if machine.projects.len() != before {
        machine.save()?;
    }

    println!(
        "{} deinitialized {}",
        style::ok_mark(),
        style::bold(root.display())
    );
    Ok(())
}
