use crate::config_struct::{KNOWLEDGE_DIR, LOGS_DIR, PROMPTS_DIR, STATE_DIR};

const AI_SUBDIRS: &[&str] = &[
    STATE_DIR,
    LOGS_DIR,
    KNOWLEDGE_DIR,
    PROMPTS_DIR,
    "tools",
    "screenshots",
];

pub fn cmd_init(
    repo: &str,
    model_arg: Option<&str>,
    backend_arg: Option<&str>,
    llm_url_arg: Option<&str>,
    api_key_arg: Option<&str>,
    yes: bool,
) -> anyhow::Result<()> {
    let root = std::path::PathBuf::from(repo);
    let ai = root.join(".ai");

    let display_root = root.canonicalize().unwrap_or_else(|_| root.clone());
    println!("╭─ do_it init ────────────────────────────────────────────────╮");
    println!("│ repo: {}", display_root.display());
    println!("╰────────────────────────────────────────────────────────────╯");
    println!();

    for sub in AI_SUBDIRS {
        let dir = ai.join(sub);
        let existed = dir.exists();
        std::fs::create_dir_all(&dir)
            .map_err(|e| anyhow::anyhow!("Cannot create .ai/{sub}/: {e}"))?;
        if existed {
            println!("  ✓ exists   .ai/{sub}/");
        } else {
            println!("  ✓ created  .ai/{sub}/");
        }
    }
    println!();

    super::ensure_project_prompts(&root)?;

    let backend = if let Some(b) = backend_arg {
        b.to_string()
    } else if yes {
        "ollama".to_string()
    } else {
        prompt_input("LLM backend (ollama / openai / anthropic)", "ollama")
    };
    let backend = backend.trim().to_lowercase();
    let backend = match backend.as_str() {
        "openai" | "anthropic" => backend.clone(),
        _ => "ollama".to_string(),
    };

    let default_url = match backend.as_str() {
        "openai" => "https://api.openai.com",
        "anthropic" => "https://api.anthropic.com",
        _ => "http://localhost:11434",
    };
    let llm_url = if let Some(u) = llm_url_arg {
        u.to_string()
    } else if yes {
        default_url.to_string()
    } else {
        prompt_input("LLM service URL", default_url)
    };

    let default_model = match backend.as_str() {
        "openai" => "gpt-4o",
        "anthropic" => "claude-sonnet-4-5-20251001",
        _ => "qwen3.5:35b",
    };
    let model = if let Some(m) = model_arg {
        m.to_string()
    } else if yes {
        default_model.to_string()
    } else {
        prompt_input("Model", default_model)
    };

    let api_key_line = if let Some(k) = api_key_arg {
        format!("llm_api_key    = \"{k}\"")
    } else if backend != "ollama" && !yes {
        let k = prompt_input("API key (leave blank to set LLM_API_KEY env var later)", "");
        if k.is_empty() {
            "# llm_api_key = \"\"   # or set LLM_API_KEY env var".to_string()
        } else {
            format!("llm_api_key    = \"{k}\"")
        }
    } else {
        "# llm_api_key = \"\"   # or set LLM_API_KEY env var".to_string()
    };

    let config_path = root.join("config.toml");
    if config_path.exists() {
        println!("  ✓ exists   config.toml (not overwritten — edit manually to change backend)");
    } else {
        let config_content = format!(
            r#"# do_it configuration — generated by `do_it init`
# Run `do_it config` to see the resolved values.

# ── LLM backend ───────────────────────────────────────────────────────────────
# llm_backend: "ollama" | "openai" | "anthropic"
llm_backend    = "{backend}"
llm_url        = "{llm_url}"
{api_key_line}

model          = "{model}"
temperature    = 0.0
max_tokens     = 4096
history_window = 8
max_output_chars = 6000
max_depth      = 3

# ── Per-task-type model overrides (all optional) ──────────────────────────────
[models]
# thinking  = "{model}"
# coding    = "{model}"
# search    = "{model}"
# execution = "{model}"
# vision    = "{model}"

# ── Telegram (optional) ───────────────────────────────────────────────────────
# telegram_token   = "BOT_TOKEN"
# telegram_chat_id = "CHAT_ID"

# ── Browser backend (optional) ────────────────────────────────────────────────
# [browser]
# awp_url        = "http://127.0.0.1:9222"
# screenshot_dir = ".ai/screenshots"
"#,
            backend = backend,
            llm_url = llm_url,
            api_key_line = api_key_line,
            model = model,
        );
        std::fs::write(&config_path, &config_content)
            .map_err(|e| anyhow::anyhow!("Cannot write config.toml: {e}"))?;
        println!("  ✓ created  config.toml  (backend: {backend}, model: {model})");
    }

    let project_path = ai.join("project.toml");
    if project_path.exists() {
        println!("  ✓ exists   .ai/project.toml (not overwritten)");
    } else {
        let project_name = if yes {
            root.file_name()
                .and_then(|n| n.to_str())
                .unwrap_or("my-project")
                .to_string()
        } else {
            prompt_input(
                "Project name",
                root.file_name()
                    .and_then(|n| n.to_str())
                    .unwrap_or("my-project"),
            )
        };

        let project_content = format!(
            r#"# do_it project configuration

[project]
name        = "{project_name}"
description = ""
language    = ""      # e.g. "Rust", "TypeScript", "Python"
framework   = ""      # e.g. "Axum", "React", "FastAPI"

[build]
build   = ""          # e.g. "cargo build"
test    = ""          # e.g. "cargo test"
lint    = ""          # e.g. "cargo clippy"
serve   = ""          # e.g. "cargo run"

[conventions]
# code_style   = "..."
# commit_style = "conventional commits"
"#
        );
        std::fs::write(&project_path, project_content)
            .map_err(|e| anyhow::anyhow!("Cannot write .ai/project.toml: {e}"))?;
        println!("  ✓ created  .ai/project.toml");
    }

    let gitignore_path = root.join(".gitignore");
    let ai_entries = [".ai/state/", ".ai/logs/", ".ai/screenshots/"];

    if gitignore_path.exists() {
        let existing = std::fs::read_to_string(&gitignore_path).unwrap_or_default();
        let missing: Vec<&str> = ai_entries
            .iter()
            .copied()
            .filter(|e| !existing.contains(e))
            .collect();

        if missing.is_empty() {
            println!("  ✓ exists   .gitignore (do_it entries already present)");
        } else {
            let mut f = std::fs::OpenOptions::new()
                .append(true)
                .open(&gitignore_path)
                .map_err(|e| anyhow::anyhow!("Cannot open .gitignore: {e}"))?;
            use std::io::Write as _;
            writeln!(f, "\n# do_it — runtime state (do not commit)")?;
            for entry in &missing {
                writeln!(f, "{entry}")?;
            }
            println!("  ✓ updated  .gitignore (added: {})", missing.join(", "));
        }
    } else {
        let content = format!(
            "# do_it — runtime state (do not commit)\n{}\n",
            ai_entries.join("\n")
        );
        std::fs::write(&gitignore_path, content)
            .map_err(|e| anyhow::anyhow!("Cannot write .gitignore: {e}"))?;
        println!("  ✓ created  .gitignore");
    }

    println!();
    println!("  Workspace ready.");
    println!("  Next step:");
    println!("    do_it run --task \"describe your task here\" --role boss");
    println!();

    Ok(())
}

fn prompt_input(label: &str, default: &str) -> String {
    use std::io::Write as _;
    print!("  {label} [{}]: ", default);
    std::io::stdout().flush().ok();
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    let trimmed = line.trim();
    if trimmed.is_empty() {
        default.to_string()
    } else {
        trimmed.to_string()
    }
}
