use std::{error::Error, sync::Arc};

use anyhow::Context;
use swc::{BoolOrDataConfig, JsMinifyExtras, config::JsMinifyOptions, try_with_handler};
use swc_common::{FileName, GLOBALS, SourceMap};
use swc_ecma_minifier::option::SimpleMangleCache;

pub fn minify(file_string: &str) -> Result<String, Box<dyn Error>> {
    let cm = Arc::<SourceMap>::default();

    let c = swc::Compiler::new(cm.clone());
    let output = match GLOBALS.set(&Default::default(), move || {
        try_with_handler(cm.clone(), Default::default(), |handler| {
            let fm = cm.new_source_file(FileName::Anon.into(), file_string.to_string());

            c.minify(
                fm,
                handler,
                &JsMinifyOptions {
                    compress: BoolOrDataConfig::from_bool(true),
                    mangle: BoolOrDataConfig::from_bool(true),
                    ..Default::default()
                },
                JsMinifyExtras::default()
                    .with_mangle_name_cache(Some(Arc::new(SimpleMangleCache::default()))),
            )
            .context("failed to minify")
        })
    }) {
        Ok(v) => v,
        Err(err) => {
            tracing::error!("{err}");
            return Err(err.to_pretty_string().into());
        }
    };

    Ok(output.code)
}
