"""Client CRUD, reviewer invitations, audit log."""

import json

from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse

import auth
from db import execute, query, query_one
from deps import APP_BASE_URL, DEV_MAGIC_LINK_PRINT, audit, render, require_internal

router = APIRouter()


@router.get("/clients", response_class=HTMLResponse)
def clients_list(request: Request):
    user = require_internal(request)
    rows = query(
        """SELECT c.id, c.name, c.primary_url, c.status, c.created_at, o.name AS org_name
           FROM client c JOIN organization o ON o.id = c.organization_id
           ORDER BY c.created_at DESC"""
    )
    return render("clients_list.html", user=user, clients=rows)


@router.get("/orgs/{org_id}/clients/new", response_class=HTMLResponse)
def client_new_form(request: Request, org_id: int, error: str = ""):
    user = require_internal(request)
    org = query_one("SELECT id, name FROM organization WHERE id = ?", (org_id,))
    if not org:
        raise HTTPException(404)
    return render("client_new.html", user=user, org=org, error=error)


@router.post("/orgs/{org_id}/clients/new")
def client_new_submit(
    request: Request, org_id: int,
    name: str = Form(...), primary_url: str = Form(...),
    permission_confirmed: str = Form(""),
):
    user = require_internal(request)
    org = query_one("SELECT id, name FROM organization WHERE id = ?", (org_id,))
    if not org:
        raise HTTPException(404)
    name = name.strip()
    primary_url = primary_url.strip()
    if not name or not primary_url:
        return render("client_new.html", user=user, org=org,
                      error="Name and URL are required.")
    if not (primary_url.startswith("http://") or primary_url.startswith("https://")):
        return render("client_new.html", user=user, org=org,
                      error="URL must start with http:// or https://")
    if permission_confirmed != "on":
        return render("client_new.html", user=user, org=org,
                      error="You must confirm authorization to analyze this site.")
    if query_one("SELECT id FROM client WHERE organization_id = ? AND name = ?",
                 (org_id, name)):
        return render("client_new.html", user=user, org=org,
                      error="A client with that name already exists in this organization.")
    client_id = execute(
        """INSERT INTO client (organization_id, name, primary_url,
                               permission_confirmed_by, permission_confirmed_at)
           VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)""",
        (org_id, name, primary_url, user.id),
    )
    audit(user.id, client_id, "client.create",
          {"name": name, "primary_url": primary_url, "org_id": org_id})
    return RedirectResponse(f"/clients/{client_id}", status_code=303)


@router.get("/clients/{client_id}", response_class=HTMLResponse)
def client_detail(request: Request, client_id: int):
    user = require_internal(request)
    client = query_one(
        """SELECT c.id, c.name, c.primary_url, c.status, c.created_at,
                  o.id AS org_id, o.name AS org_name
           FROM client c JOIN organization o ON o.id = c.organization_id
           WHERE c.id = ?""", (client_id,),
    )
    if not client:
        raise HTTPException(404)
    crawls = query(
        """SELECT id, started_at, finished_at, status, ai_spend_cents, error
           FROM crawl_run WHERE client_id = ? ORDER BY started_at DESC LIMIT 20""",
        (client_id,),
    )
    reports = query(
        """SELECT id, title, version, status, created_at, sent_to_client_at, approved_at
           FROM report WHERE client_id = ? ORDER BY created_at DESC""",
        (client_id,),
    )
    reviewers = query(
        """SELECT u.id, u.email, u.name, uca.role
           FROM user_client_access uca JOIN user u ON u.id = uca.user_id
           WHERE uca.client_id = ? ORDER BY u.email""",
        (client_id,),
    )
    return render("client_detail.html",
                  user=user, client=client, crawls=crawls, reports=reports,
                  reviewers=reviewers)


@router.post("/clients/{client_id}/invite")
def client_invite_reviewer(
    request: Request, client_id: int,
    email: str = Form(...), name: str = Form(""),
):
    user = require_internal(request)
    if not query_one("SELECT id FROM client WHERE id = ?", (client_id,)):
        raise HTTPException(404)
    email = email.lower().strip()
    if "@" not in email:
        raise HTTPException(400, "Invalid email")
    existing_user = query_one("SELECT id, role FROM user WHERE email = ?", (email,))
    if existing_user:
        invitee_id = existing_user["id"]
    else:
        invitee_id = execute(
            "INSERT INTO user (email, name, role) VALUES (?, ?, 'client')",
            (email, name.strip() or None),
        )
    execute(
        """INSERT OR IGNORE INTO user_client_access (user_id, client_id, role)
           VALUES (?, ?, 'reviewer')""",
        (invitee_id, client_id),
    )
    token = auth.issue_magic_link(invitee_id, client_id_scope=client_id)
    link = f"{APP_BASE_URL}/auth/magic?token={token}"
    if DEV_MAGIC_LINK_PRINT:
        print(f"================ MAGIC LINK for {email} ================\n"
              f"{link}\n"
              f"================================================================")
    audit(user.id, client_id, "client.invite_reviewer",
          {"invitee_email": email, "invitee_id": invitee_id})
    return RedirectResponse(f"/clients/{client_id}?invited={email}", status_code=303)


@router.get("/clients/{client_id}/audit", response_class=HTMLResponse)
def client_audit(request: Request, client_id: int):
    user = require_internal(request)
    client = query_one(
        """SELECT c.id, c.name, o.id AS org_id, o.name AS org_name
           FROM client c JOIN organization o ON o.id = c.organization_id
           WHERE c.id = ?""", (client_id,),
    )
    if not client:
        raise HTTPException(404)
    events = query(
        """SELECT a.id, a.kind, a.payload_json, a.created_at,
                  u.email AS actor_email
           FROM audit_event a LEFT JOIN user u ON u.id = a.actor_user_id
           WHERE a.client_id = ? ORDER BY a.created_at DESC LIMIT 200""",
        (client_id,),
    )
    events_view = []
    for e in events:
        d = dict(e)
        try:
            d["payload"] = json.loads(d["payload_json"]) if d["payload_json"] else {}
        except json.JSONDecodeError:
            d["payload"] = {}
        events_view.append(d)
    return render("client_audit.html", user=user, client=client, events=events_view)
