// SPDX-License-Identifier: MIT
// Copyright (c) 2025-2026 SenWeaverCoding
// Licensed under the MIT License.

use anyhow::{Context, Result};
use std::path::PathBuf;
use std::process::Command;

const CHIP: &str = "STM32F401RETx";
const TARGET: &str = "thumbv7em-none-eabihf";

pub fn probe_rs_available() -> bool {
    crate::util::hidden_sync_command("probe-rs")
        .arg("--version")
        .output()
        .map(|o| o.status.success())
        .unwrap_or(false)
}

pub fn flash_nucleo_firmware() -> Result<()> {
    if !probe_rs_available() {
        anyhow::bail!(
            "probe-rs not found. Install it:\n  cargo install probe-rs-tools --locked\n\n\
             Or: curl -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh\n\n\
             Connect Nucleo via USB (ST-Link). Then run this command again."
        );
    }

    let repo_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let firmware_dir = repo_root.join("firmware").join("nucleo");
    if !firmware_dir.join("Cargo.toml").exists() {
        anyhow::bail!(
            "Nucleo firmware not found at {}. Run from sen repo root.",
            firmware_dir.display()
        );
    }

    println!("Building SenWeaverCoding Nucleo firmware...");
    let build = crate::util::hidden_sync_command("cargo")
        .args(["build", "--release", "--target", TARGET])
        .current_dir(&firmware_dir)
        .output()
        .context("cargo build failed")?;

    if !build.status.success() {
        let stderr = String::from_utf8_lossy(&build.stderr);
        anyhow::bail!("Build failed:\n{}", stderr);
    }

    let elf_path = firmware_dir
        .join("target")
        .join(TARGET)
        .join("release")
        .join("nucleo");

    if !elf_path.exists() {
        anyhow::bail!("Built binary not found at {}", elf_path.display());
    }

    println!("Flashing to Nucleo-F401RE (connect via USB)...");
    let flash = crate::util::hidden_sync_command("probe-rs")
        .args([
            "run",
            "--chip",
            CHIP,
            elf_path
                .to_str()
                .ok_or_else(|| anyhow::anyhow!("firmware path contains non-UTF-8 characters"))?,
        ])
        .output()
        .context("probe-rs run failed")?;

    if !flash.status.success() {
        let stderr = String::from_utf8_lossy(&flash.stderr);
        anyhow::bail!(
            "Flash failed:\n{}\n\n\
             Ensure Nucleo is connected via USB. The ST-Link is built into the board.",
            stderr
        );
    }

    println!("SenWeaverCoding Nucleo firmware flashed successfully.");
    println!("The Nucleo now supports: ping, capabilities, gpio_read, gpio_write.");
    println!(
        "Add to config.toml: board = \"nucleo-f401re\", transport = \"serial\", path = \"/dev/ttyACM0\""
    );
    Ok(())
}
