#!/usr/bin/env python3
"""
Platform Gateway — Auth, session, proxy, dashboard aggregation.
Owns platform identity. Does NOT own business logic.

This file is thin routing only. All logic lives in submodules.
"""

import json
from datetime import datetime
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler

from config import (
    PORT, TRIPS_API_TOKEN, KINDLE_EMAIL_1, KINDLE_EMAIL_2,
    KINDLE_LABELS, SMTP2GO_API_KEY, SMTP2GO_FROM_EMAIL,
)
from database import init_db
from sessions import get_session_user, get_service_token
import proxy as _proxy_module
from proxy import proxy_request, load_service_map, resolve_service
from responses import ResponseMixin
from auth import handle_login, handle_logout, handle_register
from dashboard import (
    handle_dashboard, handle_apps, handle_me, handle_connections,
    handle_set_connection, handle_pin, handle_unpin, handle_get_pinned,
)
from command import handle_command
from integrations.booklore import (
    handle_booklore_libraries, handle_booklore_import,
    handle_booklore_books, handle_booklore_cover,
)
from integrations.kindle import handle_send_to_kindle, handle_send_file_to_kindle
from integrations.karakeep import handle_karakeep_save, handle_karakeep_delete
from integrations.qbittorrent import handle_downloads_status
from integrations.image_proxy import handle_image_proxy


class GatewayHandler(ResponseMixin, BaseHTTPRequestHandler):

    def log_message(self, format, *args):
        print(f"[{datetime.now().strftime('%H:%M:%S')}] {args[0]}")

    # ── Routing ──

    def do_OPTIONS(self):
        self.send_response(204)
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Access-Control-Allow-Headers", "Content-Type, Authorization, Cookie")
        self.send_header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
        self.end_headers()

    def do_GET(self):
        path = self.path.split("?")[0]

        # Image serving -- try services
        if path.startswith("/images/"):
            user = self._get_user()
            for service_id, target in _proxy_module.SERVICE_MAP.items():
                headers = {}
                if user:
                    svc_token = get_service_token(user["id"], service_id)
                    if svc_token:
                        headers["Authorization"] = f"Bearer {svc_token['auth_token']}"
                if not headers.get("Authorization") and service_id == "trips" and TRIPS_API_TOKEN:
                    headers["Authorization"] = f"Bearer {TRIPS_API_TOKEN}"
                status, resp_headers, resp_body = proxy_request(f"{target}{path}", "GET", headers, timeout=15)
                if status == 200:
                    self.send_response(200)
                    ct = resp_headers.get("Content-Type", "application/octet-stream")
                    self.send_header("Content-Type", ct)
                    self.send_header("Content-Length", len(resp_body))
                    self.send_header("Cache-Control", "public, max-age=86400")
                    self.end_headers()
                    self.wfile.write(resp_body)
                    return
            self._send_json({"error": "Image not found"}, 404)
            return

        if path == "/api/health":
            self._send_json({"status": "ok", "service": "gateway"})
            return

        if path == "/api/auth/me":
            user = self._get_user()
            if user:
                self._send_json({
                    "authenticated": True,
                    "user": {"id": user["id"], "username": user["username"], "display_name": user["display_name"]}
                })
            else:
                self._send_json({"authenticated": False, "user": None})
            return

        if path == "/api/apps":
            user = self._require_auth()
            if user:
                handle_apps(self, user)
            return

        if path == "/api/me":
            user = self._require_auth()
            if user:
                handle_me(self, user)
            return

        if path == "/api/me/connections":
            user = self._require_auth()
            if user:
                handle_connections(self, user)
            return

        if path == "/api/dashboard":
            user = self._require_auth()
            if user:
                handle_dashboard(self, user)
            return

        if path == "/api/pinned":
            user = self._require_auth()
            if user:
                handle_get_pinned(self, user)
            return

        if path == "/api/booklore/books":
            user = self._require_auth()
            if user:
                handle_booklore_books(self)
            return

        if path == "/api/kindle/targets":
            user = self._require_auth()
            if not user:
                return
            kindle_labels = KINDLE_LABELS.split(",")
            targets = []
            if KINDLE_EMAIL_1:
                targets.append({"id": "1", "label": kindle_labels[0].strip() if kindle_labels else "Kindle 1", "email": KINDLE_EMAIL_1})
            if KINDLE_EMAIL_2:
                targets.append({"id": "2", "label": kindle_labels[1].strip() if len(kindle_labels) > 1 else "Kindle 2", "email": KINDLE_EMAIL_2})
            self._send_json({"targets": targets, "configured": bool(SMTP2GO_API_KEY and SMTP2GO_FROM_EMAIL)})
            return

        if path.startswith("/api/booklore/books/") and path.endswith("/cover"):
            user = self._require_auth()
            if user:
                book_id = path.split("/")[4]
                handle_booklore_cover(self, book_id)
            return

        if path == "/api/downloads/status":
            user = self._require_auth()
            if user:
                handle_downloads_status(self)
            return

        if path == "/api/booklore/libraries":
            user = self._require_auth()
            if user:
                handle_booklore_libraries(self)
            return

        if path == "/api/image-proxy":
            user = self._require_auth()
            if user:
                handle_image_proxy(self)
            return

        if path.startswith("/api/"):
            self._proxy("GET", path)
            return

        self._send_json({"error": "Not found"}, 404)

    def do_POST(self):
        path = self.path.split("?")[0]
        body = self._read_body()

        if path == "/api/auth/login":
            handle_login(self, body)
            return

        if path == "/api/auth/logout":
            handle_logout(self)
            return

        if path == "/api/auth/register":
            self._send_json({"error": "Registration is disabled"}, 403)
            return

        if path == "/api/me/connections":
            user = self._require_auth()
            if user:
                handle_set_connection(self, user, body)
            return

        if path == "/api/pin":
            user = self._require_auth()
            if user:
                handle_pin(self, user, body)
            return

        if path == "/api/unpin":
            user = self._require_auth()
            if user:
                handle_unpin(self, user, body)
            return

        if path == "/api/kindle/send-file":
            user = self._require_auth()
            if user:
                handle_send_file_to_kindle(self, body)
            return

        if path.startswith("/api/booklore/books/") and path.endswith("/send-to-kindle"):
            user = self._require_auth()
            if user:
                book_id = path.split("/")[4]
                handle_send_to_kindle(self, book_id, body)
            return

        if path == "/api/booklore/import":
            user = self._require_auth()
            if user:
                handle_booklore_import(self, body)
            return

        if path == "/api/karakeep/save":
            user = self._require_auth()
            if user:
                handle_karakeep_save(self, body)
            return

        if path == "/api/karakeep/delete":
            user = self._require_auth()
            if user:
                handle_karakeep_delete(self, body)
            return

        if path == "/api/command":
            user = self._require_auth()
            if user:
                handle_command(self, user, body)
            return

        if path.startswith("/api/"):
            self._proxy("POST", path, body)
            return

        self._send_json({"error": "Not found"}, 404)

    def do_PUT(self):
        path = self.path.split("?")[0]
        body = self._read_body()
        if path.startswith("/api/"):
            self._proxy("PUT", path, body)
            return
        self._send_json({"error": "Not found"}, 404)

    def do_PATCH(self):
        path = self.path.split("?")[0]
        body = self._read_body()
        if path.startswith("/api/"):
            self._proxy("PATCH", path, body)
            return
        self._send_json({"error": "Not found"}, 404)

    def do_DELETE(self):
        path = self.path.split("?")[0]
        body = self._read_body()
        if path.startswith("/api/"):
            self._proxy("DELETE", path, body)
            return
        self._send_json({"error": "Not found"}, 404)

    # ── Service proxy ──

    def _proxy(self, method, path, body=None):
        user = self._get_user()

        service_id, target, backend_path = resolve_service(path)

        if not target:
            self._send_json({"error": "Unknown service"}, 404)
            return

        from config import MINIFLUX_API_KEY, INVENTORY_SERVICE_API_KEY, BUDGET_SERVICE_API_KEY, TASKS_SERVICE_API_KEY
        headers = {}
        ct = self.headers.get("Content-Type")
        if ct:
            headers["Content-Type"] = ct

        # Inject service-level auth
        if service_id == "reader" and MINIFLUX_API_KEY:
            headers["X-Auth-Token"] = MINIFLUX_API_KEY
        elif service_id == "trips" and TRIPS_API_TOKEN:
            headers["Authorization"] = f"Bearer {TRIPS_API_TOKEN}"
        elif service_id == "inventory" and INVENTORY_SERVICE_API_KEY:
            headers["X-API-Key"] = INVENTORY_SERVICE_API_KEY
        elif service_id == "budget" and BUDGET_SERVICE_API_KEY:
            headers["X-API-Key"] = BUDGET_SERVICE_API_KEY
        elif service_id == "tasks":
            # Inject user identity for the task manager
            if user:
                headers["X-Gateway-User-Id"] = str(user["id"])
                headers["X-Gateway-User-Name"] = user.get("display_name", user.get("username", ""))
        elif service_id == "brain":
            # Inject user identity for the brain service
            if user:
                headers["X-Gateway-User-Id"] = str(user["id"])
                headers["X-Gateway-User-Name"] = user.get("display_name", user.get("username", ""))
        elif user:
            svc_token = get_service_token(user["id"], service_id)
            if svc_token:
                if svc_token["auth_type"] == "bearer":
                    headers["Authorization"] = f"Bearer {svc_token['auth_token']}"
                elif svc_token["auth_type"] == "cookie":
                    headers["Cookie"] = f"session={svc_token['auth_token']}"

        if "Authorization" not in headers:
            auth = self.headers.get("Authorization")
            if auth:
                headers["Authorization"] = auth

        for h in ["X-API-Key", "X-Telegram-User-Id"]:
            val = self.headers.get(h)
            if val:
                headers[h] = val

        query = self.path.split("?", 1)[1] if "?" in self.path else ""
        full_url = f"{target}{backend_path}"
        if query:
            full_url += f"?{query}"

        status, resp_headers, resp_body = proxy_request(full_url, method, headers, body)

        self.send_response(status)
        for k, v in resp_headers.items():
            k_lower = k.lower()
            if k_lower in ("content-type", "content-disposition"):
                self.send_header(k, v)
        self.send_header("Content-Length", len(resp_body))
        self.end_headers()
        self.wfile.write(resp_body)


# ── Main ──

def main():
    init_db()
    load_service_map()

    print(f"[Gateway] Services: {_proxy_module.SERVICE_MAP}")
    print(f"[Gateway] Listening on port {PORT}")

    server = ThreadingHTTPServer(("0.0.0.0", PORT), GatewayHandler)
    server.serve_forever()


if __name__ == "__main__":
    main()
