"""Shared dependencies: config, jinja env, auth helpers, audit, access checks.

Routers in app/routes/ import from here. Keep this module thin — it's the seam
between FastAPI plumbing and per-feature route logic.
"""

from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Optional

from fastapi import HTTPException, Request
from fastapi.responses import HTMLResponse
from jinja2 import Environment, FileSystemLoader, select_autoescape

import auth
from db import execute, query_one
from version import VERSION

# ---------- Config ----------

DATA_DIR = Path(os.environ.get("DATA_DIR", "/data"))
CRAWLS_DIR = DATA_DIR / "crawls"
REPORTS_DIR = DATA_DIR / "reports"
CRAWL_MAX_PAGES = int(os.environ.get("CRAWL_MAX_PAGES", "25"))

APP_BASE_URL = os.environ.get("APP_BASE_URL", "http://localhost:8000")
DEV_MAGIC_LINK_PRINT = os.environ.get("DEV_MAGIC_LINK_PRINT", "0") == "1"

BASE_DIR = Path(__file__).parent
TEMPLATES_DIR = BASE_DIR / "templates"
STATIC_DIR = BASE_DIR / "static"


# ---------- Jinja ----------

jinja_env = Environment(
    loader=FileSystemLoader(TEMPLATES_DIR),
    autoescape=select_autoescape(["html"]),
    trim_blocks=True,
    lstrip_blocks=True,
)
jinja_env.globals["app_version"] = VERSION


def render(template_name: str, **context) -> HTMLResponse:
    tmpl = jinja_env.get_template(template_name)
    return HTMLResponse(tmpl.render(**context))


# ---------- Auth helpers ----------

def current_user(request: Request) -> Optional[auth.CurrentUser]:
    uid = auth.read_session_cookie(request.cookies.get(auth.SESSION_COOKIE))
    if uid is None:
        return None
    return auth.load_user(uid)


def require_user(request: Request) -> auth.CurrentUser:
    user = current_user(request)
    if user is None:
        raise HTTPException(status_code=303, headers={"location": "/login"})
    return user


def require_internal(request: Request) -> auth.CurrentUser:
    user = require_user(request)
    if not user.is_internal:
        raise HTTPException(status_code=403, detail="Internal users only")
    return user


def user_can_access_client(user: auth.CurrentUser, client_id: int) -> bool:
    if user.is_internal:
        return True
    row = query_one(
        "SELECT 1 FROM user_client_access WHERE user_id = ? AND client_id = ?",
        (user.id, client_id),
    )
    return row is not None


# ---------- Audit ----------

def audit(actor_user_id: Optional[int], client_id: Optional[int],
          kind: str, payload: dict) -> None:
    """Append one row to audit_event. Use generously — it's the per-client timeline."""
    execute(
        "INSERT INTO audit_event (actor_user_id, client_id, kind, payload_json) VALUES (?, ?, ?, ?)",
        (actor_user_id, client_id, kind, json.dumps(payload)),
    )
