"""init: interactively create a new agent and add it to bot-bottle.json."""

from __future__ import annotations

import argparse
import json
import os
import re
import sys
from pathlib import Path
from typing import Any

from ...log import die, info, warn
from ..constants import PROG
from ...util import read_tty_line


def cmd_init(argv: list[str]) -> int:
    parser = argparse.ArgumentParser(prog=f"{PROG} init", add_help=True)
    parser.add_argument("scope", choices=["user", "project"])
    args = parser.parse_args(argv)

    if args.scope == "user":
        target_file = Path(os.environ["HOME"]) / "bot-bottle.json"
    else:
        target_file = Path(os.getcwd()) / "bot-bottle.json"

    print(file=sys.stderr)
    info(f"bot-bottle init — adding a new agent to {target_file}")
    print(file=sys.stderr)

    # Agent name
    agent_name = ""
    while not agent_name:
        sys.stderr.write("Agent name: ")
        sys.stderr.flush()
        agent_name = read_tty_line().replace(" ", "-")
        if not agent_name:
            warn("agent name cannot be empty")

    if not re.match(r"^[a-z0-9][a-z0-9-]*$", agent_name):
        warn(
            f"agent name '{agent_name}' contains non-slug characters; "
            f"it will still work but may cause container naming issues"
        )

    existing: dict[str, Any] = {}
    if target_file.is_file():
        try:
            existing = json.loads(target_file.read_text())
        except json.JSONDecodeError:
            die(f"{target_file} exists but is not valid JSON; fix or remove it first")
        if agent_name in (existing.get("agents") or {}):
            sys.stderr.write(
                f'bot-bottle: agent "{agent_name}" already exists in '
                f'{target_file}. Overwrite? [y/N] '
            )
            sys.stderr.flush()
            ow = read_tty_line()
            if ow not in ("y", "Y", "yes", "YES"):
                info("aborted")
                return 0

    # Skills
    print(file=sys.stderr)
    sys.stderr.write("Skills (space or comma separated, or Enter for none): ")
    sys.stderr.flush()
    skills_input = read_tty_line()
    skill_list: list[str] = []
    if skills_input:
        cleaned = skills_input.replace(",", " ")
        skill_list = [s for s in cleaned.split() if s]

    # Prompt
    print(file=sys.stderr)
    info(
        "System prompt — enter text, then a lone '.' on its own line to "
        "finish (just '.' to leave empty):"
    )
    prompt_lines: list[str] = []
    while True:
        line = read_tty_line()
        if line == ".":
            break
        prompt_lines.append(line)
    prompt_content = "\n".join(prompt_lines)

    # Bottle association
    print(file=sys.stderr)
    sys.stderr.write("Associate this agent with a bottle? [y/N] ")
    sys.stderr.flush()
    bottle_yn = read_tty_line()
    bottle_name = ""
    bottle_env: dict[str, str] = {}
    bottle_ssh: list[dict[str, Any]] = []
    bottle_exists_already = False
    if bottle_yn in ("y", "Y", "yes", "YES"):
        while not bottle_name:
            sys.stderr.write("  Bottle name: ")
            sys.stderr.flush()
            bottle_name = read_tty_line().replace(" ", "-")
            if not bottle_name:
                warn("bottle name cannot be empty")

        if bottle_name in (existing.get("bottles") or {}):
            bottle_exists_already = True
            info(
                f"Bottle '{bottle_name}' already exists in {target_file}; "
                f"agent will reference it."
            )
        else:
            info(f"Creating new bottle '{bottle_name}'.")
            bottle_env = _prompt_for_env_vars()
            sys.stderr.write("  Add SSH host entries to this bottle? [y/N] ")
            sys.stderr.flush()
            ssh_yn = read_tty_line()
            if ssh_yn in ("y", "Y", "yes", "YES"):
                bottle_ssh = _prompt_for_ssh_entries()

    # Build agent JSON
    agent_def: dict[str, Any] = {"skills": skill_list, "prompt": prompt_content}
    if bottle_name:
        agent_def["bottle"] = bottle_name

    merged: dict[str, Any] = {
        "bottles": dict(existing.get("bottles") or {}),
        "agents": dict(existing.get("agents") or {}),
    }
    if bottle_name and not bottle_exists_already:
        merged["bottles"][bottle_name] = {"env": bottle_env, "ssh": bottle_ssh}
    merged["agents"][agent_name] = agent_def

    target_file.write_text(json.dumps(merged, indent=2) + "\n")
    info(f"Agent '{agent_name}' written to {target_file}.")
    info(f"Run '{PROG} info {agent_name}' to verify.")
    print(file=sys.stderr)
    return 0


def _prompt_for_env_vars() -> dict[str, str]:
    print(file=sys.stderr)
    info(
        "Env vars — enter each var name then its mode. Press Enter with "
        "no name to finish."
    )
    info(
        "  Modes:  secret (prompt at runtime) | interpolated (read from "
        "host env) | literal (hardcoded value)"
    )
    out: dict[str, str] = {}
    while True:
        print(file=sys.stderr)
        sys.stderr.write("  Var name (or Enter to finish): ")
        sys.stderr.flush()
        vname = read_tty_line()
        if not vname:
            break
        sys.stderr.write("  Mode [secret/interpolated/literal] (default: secret): ")
        sys.stderr.flush()
        vmode = read_tty_line() or "secret"
        if vmode == "secret":
            sys.stderr.write(f'  Prompt message shown to user (default: "enter {vname}"): ')
            sys.stderr.flush()
            smsg = read_tty_line()
            value = f"?{smsg}" if smsg else "?"
        elif vmode == "interpolated":
            sys.stderr.write(f"  Host env var to read from (default: {vname}): ")
            sys.stderr.flush()
            hvar = read_tty_line() or vname
            value = "${" + hvar + "}"
        elif vmode == "literal":
            sys.stderr.write("  Value: ")
            sys.stderr.flush()
            value = read_tty_line()
        else:
            warn(f"unknown mode '{vmode}'; using secret")
            value = "?"
        out[vname] = value
    return out


def _prompt_for_ssh_entries() -> list[dict[str, Any]]:
    out: list[dict[str, Any]] = []
    while True:
        print(file=sys.stderr)
        sys.stderr.write("    SSH Host alias (or Enter to finish): ")
        sys.stderr.flush()
        shost = read_tty_line()
        if not shost:
            break
        sys.stderr.write("    Hostname (actual hostname or IP): ")
        sys.stderr.flush()
        shostname = read_tty_line()
        sys.stderr.write("    User: ")
        sys.stderr.flush()
        suser = read_tty_line()
        sys.stderr.write("    Port (default: 22): ")
        sys.stderr.flush()
        sport_raw = read_tty_line() or "22"
        if not sport_raw.isdigit():
            warn("port must be a number; defaulting to 22")
            sport_raw = "22"
        sport = int(sport_raw)
        sys.stderr.write("    IdentityFile (path to private key on host): ")
        sys.stderr.flush()
        sidentity = read_tty_line()
        sys.stderr.write("    KnownHostKey (optional, Enter to skip): ")
        sys.stderr.flush()
        skhk = read_tty_line()

        entry: dict[str, Any] = {
            "Host": shost,
            "Hostname": shostname,
            "User": suser,
            "Port": sport,
            "IdentityFile": sidentity,
        }
        if skhk:
            entry["KnownHostKey"] = skhk
        out.append(entry)
    return out
