use crate::discovery::{discover_services, DiscoveredService};
use crate::infer::{infer_language, infer_platform};
use crate::manifest::{DiscoveryConfig, Manifest, DEFAULT_DISCOVERY_PATHS};
use anyhow::{bail, Result};
use std::path::{Path, PathBuf};

/// Render a human-friendly, annotated YAML scaffold for the discovered services.
pub fn render_yaml(services: &[DiscoveredService], root: &Path) -> String {
    let mut out = String::new();

    out.push_str("# Generated by `svccat init`\n");
    out.push_str("# Fill in the ~placeholder~ fields and commit this file.\n");
    out.push_str("# Run `svccat check` to verify there is no drift.\n\n");

    out.push_str("version: \"1\"\n\n");

    out.push_str("discovery:\n");
    out.push_str("  paths:\n");
    for p in DEFAULT_DISCOVERY_PATHS {
        out.push_str(&format!("    - {}\n", p));
    }
    out.push('\n');

    out.push_str("services:\n");

    if services.is_empty() {
        out.push_str("  []  # no services detected — add entries manually\n");
    } else {
        for svc in services {
            let lang = infer_language(root, &svc.path).unwrap_or_else(|| "~".to_string());
            out.push_str(&format!("  - name: {}\n", svc.name));
            out.push_str(&format!("    path: {}\n", svc.path));
            out.push_str(&format!("    language: {}\n", lang));
            match infer_platform(root, &svc.path) {
                Some(platform) => out.push_str(&format!("    platform: {}\n", platform)),
                None => out.push_str(
                    "    platform: ~  # e.g. gcp-cloud-run, fly.io, vercel, aws-lambda\n",
                ),
            }
            out.push_str("    role: ~      # e.g. api, worker, frontend, database\n");
            out.push_str("    url: ~       # e.g. https://my-service.example.com\n");
        }
    }

    out
}

/// Discover services and write a `services.yaml` scaffold to `output_path`.
pub fn run(root: &Path, output_path: PathBuf, force: bool) -> Result<()> {
    if output_path.exists() && !force {
        bail!(
            "{} already exists. Use --force to overwrite.",
            output_path.display()
        );
    }

    // Bootstrap discovery with a manifest that has no declared services.
    let bootstrap = Manifest {
        version: "1".to_string(),
        discovery: DiscoveryConfig {
            paths: vec![],
            markers: crate::manifest::default_markers_pub(),
            ignore: vec![],
        },
        policy: Default::default(),
        services: vec![],
    };

    let discovered = discover_services(root, &bootstrap);
    let yaml = render_yaml(&discovered, root);

    std::fs::write(&output_path, &yaml)?;

    let verb = if output_path.exists() {
        "Wrote"
    } else {
        "Created"
    };
    println!(
        "{} {} ({} service{} detected)",
        verb,
        output_path.display(),
        discovered.len(),
        if discovered.len() == 1 { "" } else { "s" }
    );
    println!("Edit the file, then run `svccat check` to verify.");

    Ok(())
}
