use night_fury_core::BrowserSession;
use serde_json::json;

use night_fury_cli_core::output::{output_err, output_ok, OutputMode};

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub(super) enum CoverageSub {
    Start,
    Stop,
    Unknown,
}

pub(super) fn resolve_coverage_sub(s: &str) -> CoverageSub {
    match s {
        "start" => CoverageSub::Start,
        "stop" => CoverageSub::Stop,
        _ => CoverageSub::Unknown,
    }
}

pub async fn dispatch(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let sub = parts.first().copied().unwrap_or("");
    match resolve_coverage_sub(sub) {
        CoverageSub::Start => start(session, mode).await,
        CoverageSub::Stop => stop(session, mode).await,
        CoverageSub::Unknown => output_err(
            mode,
            &format!("Unknown coverage subcommand: {sub}. Use 'start' or 'stop'"),
        ),
    }
}

async fn start(session: &BrowserSession, mode: OutputMode) {
    match session.start_coverage().await {
        Ok(()) => output_ok(
            mode,
            "Coverage collection started",
            json!({"action": "coverage_start"}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}

async fn stop(session: &BrowserSession, mode: OutputMode) {
    match session.stop_coverage().await {
        Ok(report) => {
            let js_count = report.js_entries.len();
            let css_count = report.css_entries.len();
            let human =
                format!("Coverage collected: {js_count} JS entries, {css_count} CSS entries");
            output_ok(
                mode,
                &human,
                json!({
                    "action": "coverage_stop",
                    "js_entries": js_count,
                    "css_entries": css_count,
                    "report": serde_json::to_value(&report).unwrap_or(json!(null)),
                }),
            );
        }
        Err(e) => output_err(mode, &e.to_string()),
    }
}

#[cfg(test)]
mod tests {
    use super::{resolve_coverage_sub, CoverageSub};

    #[test]
    fn resolves_known_subcommands() {
        assert_eq!(resolve_coverage_sub("start"), CoverageSub::Start);
        assert_eq!(resolve_coverage_sub("stop"), CoverageSub::Stop);
    }

    #[test]
    fn unknown_subcommand_returns_unknown() {
        assert_eq!(resolve_coverage_sub(""), CoverageSub::Unknown);
        assert_eq!(resolve_coverage_sub("pause"), CoverageSub::Unknown);
    }
}
