"""Ollama auto-start guard — ensures Ollama is running before requests.

If `ollama serve` is not reachable on localhost:11434, this module will
attempt to start it as a background subprocess and wait for it to become
available.  The start is attempted at most once per application session.
"""

from __future__ import annotations

import logging
import subprocess
import sys
import time
import urllib.error
import urllib.request

log = logging.getLogger(__name__)

_OLLAMA_URL = "http://localhost:11434/api/tags"
_HEALTH_TIMEOUT = 2.0  # seconds for the reachability check
_STARTUP_WAIT = 10.0   # max seconds to wait after launching ollama serve
_POLL_INTERVAL = 0.5   # seconds between polls while waiting for startup

# Module-level flag: only try to auto-start once per session
_already_tried: bool = False


def _is_reachable() -> bool:
    """Return True if Ollama HTTP API responds within the timeout."""
    try:
        req = urllib.request.Request(_OLLAMA_URL, headers={"Accept": "application/json"})
        with urllib.request.urlopen(req, timeout=_HEALTH_TIMEOUT) as resp:
            resp.read()
        return True
    except Exception:
        return False


def ensure_ollama_running() -> bool:
    """Make sure Ollama is reachable; auto-start if needed.

    Returns True if Ollama is reachable after this call, False otherwise.
    Only attempts to start ``ollama serve`` once per process lifetime.
    """
    global _already_tried

    # Fast path: already running
    if _is_reachable():
        return True

    # Only try once per session
    if _already_tried:
        log.warning("[ollama-guard] Ollama unreachable and auto-start already attempted")
        return False

    _already_tried = True
    log.info("[ollama-guard] Ollama not reachable — attempting to start 'ollama serve'")

    try:
        kwargs: dict = {}
        if sys.platform == "win32":
            # Hide console window on Windows
            si = subprocess.STARTUPINFO()  # type: ignore[attr-defined]
            si.dwFlags |= subprocess.STARTF_USESHOWWINDOW  # type: ignore[attr-defined]
            si.wShowWindow = 0  # SW_HIDE
            kwargs["startupinfo"] = si
            kwargs["creationflags"] = (
                subprocess.CREATE_NO_WINDOW | subprocess.DETACHED_PROCESS  # type: ignore[attr-defined]
            )

        subprocess.Popen(
            ["ollama", "serve"],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            stdin=subprocess.DEVNULL,
            start_new_session=True,
            **kwargs,
        )
    except FileNotFoundError:
        log.error("[ollama-guard] 'ollama' command not found in PATH")
        return False
    except Exception as exc:
        log.error("[ollama-guard] Failed to start ollama serve: %s", exc)
        return False

    # Wait for Ollama to become reachable
    deadline = time.monotonic() + _STARTUP_WAIT
    while time.monotonic() < deadline:
        time.sleep(_POLL_INTERVAL)
        if _is_reachable():
            log.info("[ollama-guard] Ollama is now reachable")
            return True

    log.error("[ollama-guard] Ollama did not become reachable within %.0fs", _STARTUP_WAIT)
    return False
