"""Optional local AI layer — Ollama + Qwen3:4b. Additive, never required."""

from __future__ import annotations

import json
import platform
import subprocess
import time
import urllib.error
import urllib.request

OLLAMA_HOST = "http://localhost:11434"
MODEL = "qwen3:4b"

_available_cache: bool | None = None


def is_available() -> bool:
    """Return True if Ollama is running and qwen3:4b is pulled. Cached after first check."""
    global _available_cache
    if _available_cache is not None:
        return _available_cache
    _available_cache = _check()
    return _available_cache


def _check() -> bool:
    try:
        req = urllib.request.Request(f"{OLLAMA_HOST}/api/tags")
        with urllib.request.urlopen(req, timeout=2) as resp:
            data = json.loads(resp.read())
            models = [m.get("name", "") for m in data.get("models", [])]
            return any(MODEL in m for m in models)
    except Exception:
        return False


def _running() -> bool:
    try:
        urllib.request.urlopen(f"{OLLAMA_HOST}/api/tags", timeout=2)
        return True
    except Exception:
        return False


_PROMPT = """\
You are helping an early-stage investor evaluate a startup pitch.

Pitch:
{text}

ML scores (1-10): overall {score:.1f} | team {team:.1f} | traction {traction:.1f} | market {market:.1f} | risk {risk:.1f}
Recommendation: {action}

Respond with exactly this format (no thinking tags, no preamble):

EXPLANATION: <2-3 sentences explaining the score. Be specific — cite what in the pitch drove it up or down.>
QUESTIONS:
- <sharp question to ask before a meeting>
- <sharp question to ask before a meeting>
- <sharp question to ask before a meeting>"""


def explain(text: str, result: dict) -> dict | None:
    """
    Generate a plain-English explanation and follow-up questions for a scored pitch.
    Returns { explanation, questions } or None if unavailable or on failure.
    """
    if not is_available():
        return None
    sub = result.get("sub") or result.get("sub_scores") or {}
    prompt = _PROMPT.format(
        text=text[:3000],
        score=result.get("pred_score", 0),
        team=sub.get("team", 0),
        traction=sub.get("traction", 0),
        market=sub.get("market", 0),
        risk=sub.get("risk", 0),
        action=result.get("final_action", ""),
    )
    try:
        body = json.dumps({
            "model": MODEL,
            "prompt": prompt,
            "stream": False,
            "options": {"num_predict": 320, "temperature": 0.3},
        }).encode()
        req = urllib.request.Request(
            f"{OLLAMA_HOST}/api/generate",
            data=body,
            headers={"Content-Type": "application/json"},
            method="POST",
        )
        with urllib.request.urlopen(req, timeout=60) as resp:
            raw = json.loads(resp.read()).get("response", "")
            return _parse(raw)
    except Exception:
        return None


def _parse(raw: str) -> dict | None:
    explanation = ""
    questions = []
    in_q = False
    for line in raw.strip().splitlines():
        line = line.strip()
        if line.startswith("EXPLANATION:"):
            explanation = line[len("EXPLANATION:"):].strip()
        elif line.startswith("QUESTIONS:"):
            in_q = True
        elif in_q and line.startswith("-"):
            q = line[1:].strip()
            if q:
                questions.append(q)
    if not explanation and not questions:
        return None
    return {"explanation": explanation, "questions": questions}


# ── /install-local flow ───────────────────────────────────────────────────────

def install_flow() -> bool:
    """Walk the user through installing Ollama and pulling qwen3:4b. Returns True on success."""
    global _available_cache
    print()
    print("  Local AI explanations  ·  Ollama + Qwen3-4B  (~2.5 GB download)")
    print()

    if is_available():
        print("  Already installed and ready.")
        return True

    if _running():
        print("  Ollama is running. Pulling model...")
        return _pull()

    os_name = platform.system()
    print("  Ollama is not installed on this machine.")
    print()

    ok = False
    if os_name == "Darwin":
        ok = _install_macos()
    elif os_name == "Linux":
        ok = _install_linux()
    elif os_name == "Windows":
        ok = _install_windows()
    else:
        print(f"  Unsupported platform: {os_name}")
        print("  Visit https://ollama.com to install manually, then run /install-local again.")
        return False

    if not ok:
        return False

    print("  Waiting for Ollama to start...")
    for _ in range(12):
        time.sleep(1)
        if _running():
            break

    if not _running():
        print("  Ollama doesn't seem to be running yet.")
        print("  Start it manually, then run /install-local again.")
        return False

    return _pull()


def _install_macos() -> bool:
    has_brew = subprocess.run(["which", "brew"], capture_output=True).returncode == 0
    if not has_brew:
        print("  Homebrew is not installed.")
        ans = input("  Install Homebrew first? [y/N]: ").strip().lower()
        if ans not in {"y", "yes"}:
            print("  Skipped. Visit https://brew.sh, install Homebrew, then run /install-local again.")
            return False
        print("  Installing Homebrew...")
        subprocess.run(
            "curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash",
            shell=True,
        )

    ans = input("  Install Ollama via Homebrew? [y/N]: ").strip().lower()
    if ans not in {"y", "yes"}:
        print("  Skipped.")
        return False
    print("  Running: brew install ollama")
    subprocess.run(["brew", "install", "ollama"])
    print("  Starting Ollama...")
    subprocess.Popen(["ollama", "serve"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    return True


def _install_linux() -> bool:
    print("  We'll run:  curl -fsSL https://ollama.com/install.sh | sh")
    ans = input("  Continue? [y/N]: ").strip().lower()
    if ans not in {"y", "yes"}:
        print("  Skipped.")
        return False
    subprocess.run("curl -fsSL https://ollama.com/install.sh | sh", shell=True)
    return True


def _install_windows() -> bool:
    print("  We'll run:  winget install Ollama.Ollama")
    ans = input("  Continue? [y/N]: ").strip().lower()
    if ans not in {"y", "yes"}:
        print("  Skipped.")
        return False
    subprocess.run(["winget", "install", "Ollama.Ollama"])
    return True


def _pull() -> bool:
    global _available_cache
    print(f"  Pulling {MODEL}  (this may take a few minutes)...")
    result = subprocess.run(["ollama", "pull", MODEL])
    if result.returncode == 0:
        _available_cache = True
        print(f"  Done. AI explanations are now active for every pitch.")
        return True
    print(f"  Failed. Try running manually: ollama pull {MODEL}")
    return False
