#!/usr/bin/env python3
"""Local-only review page backed by the local PostgreSQL workflow database."""

from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
import json
import os
from pathlib import Path
import socket
from urllib.parse import parse_qs, urlparse

import db

try:
    import qrcode
except ImportError:  # QR generation is optional for local desktop-only review.
    qrcode = None


ROOT = Path(__file__).resolve().parent
QR_PATH = ROOT / "outputs" / "review-qr.png"
TASKS_DIR = ROOT / "outputs" / "tasks"
DATABASE_URL = os.environ.get("XHS_DATABASE_URL", db.DEFAULT_DATABASE_URL)


def local_ip():
    """Find the address reachable by another device on the same LAN."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        sock.connect(("8.8.8.8", 80))
        return sock.getsockname()[0]
    except OSError:
        return "127.0.0.1"
    finally:
        sock.close()


def make_qr(url):
    if qrcode is None:
        return False
    QR_PATH.parent.mkdir(parents=True, exist_ok=True)
    image = qrcode.make(url)
    image.save(QR_PATH)
    return True


def task_path(task_id):
    if not task_id or "/" in task_id or "\\" in task_id or task_id in {".", ".."}:
        raise ValueError("invalid task id")
    return TASKS_DIR / f"{task_id}.json"


def load_task(task_id):
    path = task_path(task_id)
    if not path.exists():
        raise FileNotFoundError(f"task not found: {task_id}")
    return json.loads(path.read_text(encoding="utf-8"))


class Handler(SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=str(ROOT), **kwargs)

    def do_POST(self):
        if urlparse(self.path).path != "/api/review":
            self.send_error(404)
            return

        try:
            length = int(self.headers.get("Content-Length", "0"))
            payload = json.loads(self.rfile.read(length) or b"{}")
            status = payload.get("status")
            notes = payload.get("notes", "")
            task_id = payload.get("task_id") or "current"
            if status not in {"已确认", "驳回"}:
                raise ValueError("status must be 已确认 or 驳回")
            task = db.get_task(task_id, DATABASE_URL)
            if task is None:
                task = load_task(task_id)
            db.record_review(task_id, status, notes, DATABASE_URL)
            queue_name = "publish_queue.jsonl" if status == "已确认" else "rework_queue.jsonl"
            queue_path = ROOT / "outputs" / queue_name
            queue_path.parent.mkdir(parents=True, exist_ok=True)
            event = {"task_id": task_id, "status": status, "notes": notes}
            with queue_path.open("a", encoding="utf-8") as queue:
                queue.write(json.dumps(event, ensure_ascii=False) + "\n")
            self._json_response({"ok": True, "status": status, "task_id": task_id})
        except Exception as exc:  # Keep the browser response readable for local diagnosis.
            self._json_response({"ok": False, "error": str(exc)}, status=400)

    def do_GET(self):
        parsed = urlparse(self.path)
        if parsed.path == "/api/task":
            try:
                task_id = parse_qs(parsed.query).get("task", ["current"])[0]
                task = db.get_task(task_id, DATABASE_URL)
                if task is None:
                    task = load_task(task_id)
                self._json_response({"ok": True, "task": task})
            except Exception as exc:
                self._json_response({"ok": False, "error": str(exc)}, status=404)
            return
        super().do_GET()

    def _json_response(self, payload, status=200):
        body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, format, *args):
        print(format % args)


if __name__ == "__main__":
    port = int(os.environ.get("REVIEW_PORT", "5178"))
    bind_host = os.environ.get("REVIEW_HOST", "0.0.0.0")
    public_host = os.environ.get("REVIEW_PUBLIC_HOST") or ("127.0.0.1" if bind_host == "127.0.0.1" else local_ip())
    review_url = os.environ.get("REVIEW_PUBLIC_URL") or "https://xhs.opennj.cn/review.html"
    qr_ready = make_qr(review_url)
    db.init_schema(DATABASE_URL)
    server = ThreadingHTTPServer((bind_host, port), Handler)
    print(f"Review page: {review_url}")
    print(f"QR code: {QR_PATH if qr_ready else 'unavailable (install qrcode in the active Python environment)'}")
    print(f"Listening on {bind_host}:{port}; local/LAN use only. Press Ctrl-C to stop.")
    server.serve_forever()
