use std::path::Path;

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

use crate::cli::ScopeFlags;
use crate::config::Config;
use crate::registry::tools;
use crate::state::{MachineState, ProjectIntent};

use super::permissions as perms;
use super::sync;
use super::use_package::{resolve_target, Target};

pub fn run(name: &str, flags: ScopeFlags) -> Result<()> {
    if tools::resolve(name)?.is_some() {
        bail!("`{name}` is a tool, not a package — try `aimgr uninstall {name}`");
    }
    let cwd = std::env::current_dir().context("getting current directory")?;
    let target = resolve_target(&cwd, flags.global, flags.all)?;

    match target {
        Target::Project(root) => {
            remove_from_project(&root, name)?;
            sync::reconcile_project(&root, false)?;
        }
        Target::Global => {
            remove_from_global(name)?;
        }
        Target::All => {
            remove_from_global(name)?;
            let machine = MachineState::load()?;
            for root in &machine.projects {
                remove_from_project(root, name)?;
                sync::reconcile_project(root, false)?;
            }
        }
    }
    Ok(())
}

fn remove_from_project(root: &Path, name: &str) -> Result<()> {
    let mut intent = ProjectIntent::load(root)?;
    let before = intent.packages.len();
    intent.packages.retain(|p| p != name);
    if intent.packages.len() != before {
        intent.save(root)?;
    }
    Ok(())
}

fn remove_from_global(name: &str) -> Result<()> {
    let mut cfg = Config::load()?;
    if cfg.remove_package(name) {
        cfg.save()?;
    }
    let mut machine = MachineState::load()?;
    if let Some(rec) = machine.packages.get_mut(name) {
        let perms = std::mem::take(&mut rec.permissions);
        if !perms.is_empty() {
            if let Err(e) = perms::unapply(&perms) {
                eprintln!(
                    "{} unapplying permissions for `{name}`: {e}",
                    crate::ui::style::warn_mark()
                );
            }
            machine.save()?;
        }
    }
    Ok(())
}
