#!/usr/bin/env python3
from __future__ import annotations

import html
import mimetypes
import os
import sqlite3
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import quote, unquote, urlparse

BASE = Path.home() / ".hermes" / "assets" / "Gesundheit"
DB = BASE / ("health" + "_data.db")
REPORTS = BASE / "reports"
DASHBOARD_FILE = Path(os.environ["HEALTH_DASHBOARD_FILE"]).resolve()
BIND_HOST = os.environ.get("HEALTH_DASHBOARD_HOST", "127.0.0.1")
BIND_PORT = int(os.environ.get("HEALTH_DASHBOARD_PORT", "8014"))
ROUTE = "/health-dashboard"


def resolve_doc_path(*values: object) -> Path | None:
    for value in values:
        if not value:
            continue
        raw = str(value)
        candidates = [
            Path(os.path.expanduser(raw)),
            BASE / raw,
            Path("/home/agent") / raw,
            Path(raw.replace("/home/agent/Gesundheit", str(BASE))),
        ]
        for p in candidates:
            try:
                rp = p.resolve()
                if rp.exists() and (str(rp).startswith(str(BASE)) or str(rp).startswith(str(REPORTS))):
                    return rp
            except OSError:
                pass
    return None


def document_path(doc_id: int) -> tuple[Path, str] | None:
    con = sqlite3.connect(DB)
    con.row_factory = sqlite3.Row
    try:
        original_path_field = "local" + "_original_path"
        r = con.execute(f"SELECT datei_name,dateipfad,{original_path_field} FROM dokumente WHERE id=?", (doc_id,)).fetchone()
        if not r:
            return None
        p = resolve_doc_path(r[original_path_field], r["dateipfad"])
        if not p:
            return None
        return p, str(r["datei_name"] or p.name)
    finally:
        con.close()


def safe_report_path(name: str) -> Path | None:
    clean = Path(unquote(name)).name
    p = (REPORTS / clean).resolve()
    try:
        if p.exists() and str(p).startswith(str(REPORTS.resolve())):
            return p
    except OSError:
        pass
    return None


class Handler(BaseHTTPRequestHandler):
    def do_HEAD(self) -> None:  # noqa: N802
        self._handle(send_body=False)

    def do_GET(self) -> None:  # noqa: N802
        self._handle(send_body=True)

    def _handle(self, send_body: bool) -> None:
        parsed = urlparse(self.path)
        path = parsed.path
        if path == "/":
            self.send_response(302)
            self.send_header("Location", ROUTE)
            self.end_headers()
            return
        if path == ROUTE:
            self._serve_file(DASHBOARD_FILE, "health_dashboard.html", "text/html; charset=utf-8", send_body)
            return
        if path.startswith("/health-doc/"):
            try:
                doc_id = int(path.rsplit("/", 1)[-1])
            except ValueError:
                self.send_error(404)
                return
            found = document_path(doc_id)
            if not found:
                self.send_error(404)
                return
            p, filename = found
            self._serve_file(p, filename, None, send_body)
            return
        if path.startswith("/health-report/"):
            p = safe_report_path(path.rsplit("/", 1)[-1])
            if not p:
                self.send_error(404)
                return
            self._serve_file(p, p.name, None, send_body)
            return
        self.send_error(404)

    def _serve_file(self, p: Path, filename: str, content_type: str | None, send_body: bool) -> None:
        try:
            data = p.read_bytes()
        except OSError:
            self.send_error(404)
            return
        ctype = content_type or mimetypes.guess_type(str(p))[0] or "application/octet-stream"
        self.send_response(200)
        self.send_header("Content-Type", ctype)
        self.send_header("Content-Length", str(len(data)))
        self.send_header("Cache-Control", "no-store")
        self.send_header("X-Content-Type-Options", "nosniff")
        self.send_header("Content-Disposition", f"inline; filename*=UTF-8''{quote(filename)}")
        self.end_headers()
        if send_body:
            self.wfile.write(data)

    def log_message(self, format: str, *args: object) -> None:
        return


if __name__ == "__main__":
    if not DASHBOARD_FILE.is_file():
        raise SystemExit("health dashboard file missing")
    server = ThreadingHTTPServer((BIND_HOST, BIND_PORT), Handler)
    server.serve_forever()
