use crate::cli::{err, hint, ok, DEFAULT_PORT};
use anyhow::{anyhow, Result};
use clap::Parser;
use std::process::Command;

const WEBVIEW_PANEL_TYPE: &str = "adom/a1b2c3d4-0031-4000-a000-000000000031";

#[derive(Parser)]
pub struct Args {
    #[arg(long, default_value_t = DEFAULT_PORT)]
    pub port: u16,

    #[arg(long, default_value = "STEP Viewer")]
    pub tab_name: String,

    #[arg(long, default_value = "mdi:cube-outline")]
    pub display_icon: String,
}

pub fn run(args: Args) -> Result<()> {
    open_webview_tab(args.port, &args.tab_name, &args.display_icon)
}

pub fn open_webview_tab(port: u16, tab_name: &str, display_icon: &str) -> Result<()> {
    let proxy_uri = std::env::var("VSCODE_PROXY_URI").ok();
    let base_url = match &proxy_uri {
        Some(t) => t.replace("{{port}}", &port.to_string()),
        None => format!("http://127.0.0.1:{}/", port),
    };
    let sep = if base_url.contains('?') { '&' } else { '?' };
    let cb = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|d| d.as_millis())
        .unwrap_or(0);
    let webview_url = format!("{}{}_cb={}", base_url, sep, cb);

    let leaf_id = match find_leaf_pane_id() {
        Ok(id) => id,
        Err(e) => {
            err(format!("{e}"));
            hint("Open any web view tab first (or split a new pane), then re-run.");
            return Err(e);
        }
    };
    let initial_state = format!(r#"{{"url":"{}"}}"#, webview_url);

    let status = Command::new("adom-cli")
        .args([
            "hydrogen",
            "workspace",
            "add-tab",
            "--panel-id",
            &leaf_id,
            "--panel-type",
            WEBVIEW_PANEL_TYPE,
            "--display-name",
            tab_name,
            "--display-icon",
            display_icon,
            "--initial-state",
            &initial_state,
        ])
        .status()?;
    if !status.success() {
        return Err(anyhow!(
            "adom-cli workspace add-tab failed (is a tab already named '{}'? pass --tab-name to override)",
            tab_name
        ));
    }
    ok(format!("webview tab '{tab_name}' created"));
    Ok(())
}

/// Find a Web View pane to host the tab. Per memory `feedback_never_cover_vscode`:
/// only place tabs in panes that already host a Web View tab.
fn find_leaf_pane_id() -> Result<String> {
    let output = Command::new("adom-cli")
        .args(["hydrogen", "workspace", "tabs"])
        .output()?;
    let text = String::from_utf8_lossy(&output.stdout);
    let v: serde_json::Value = serde_json::from_str(&text)?;
    let tabs = v
        .get("tabs")
        .and_then(|t| t.as_array())
        .ok_or_else(|| anyhow!("adom-cli workspace tabs returned no tabs array"))?;
    for tab in tabs {
        let ptype = tab
            .get("panelType")
            .and_then(|p| p.as_str())
            .unwrap_or("");
        if ptype == WEBVIEW_PANEL_TYPE {
            if let Some(pid) = tab.get("panelId").and_then(|p| p.as_str()) {
                return Ok(pid.to_string());
            }
        }
    }
    Err(anyhow!(
        "no existing Web View pane found. Open any web view tab first or split a new pane."
    ))
}