import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
import { initDb } from "./db.js";
import { startReminderScheduler } from "./scheduler.js";
import {
  handleHealth,
  handleGetCalendars,
  handleGetCalendar,
  handleGetEvents,
  handleCreateEvent,
  handleGetEvent,
  handleUpdateEvent,
  handleDeleteEvent,
  handleUpdateEventPeople,
  handleCreateReminder,
  handleDeleteReminder,
  handleGetGoogleCachedEvents,
  handleGetSharedCalendars,
  handleGetSyncConfig,
  handlePutSyncConfig,
} from "./routes.js";
import { startGoogleSync } from "./google-calendar.js";

const PORT = parseInt(process.env.CALENDAR_SERVICE_PORT || "8084", 10);

type Handler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;

function matchRoute(method: string, url: string): Handler | null {
  if (method === "GET" && url === "/health") return handleHealth;

  if (method === "GET" && url === "/calendars") return handleGetCalendars;

  const calMatch = url.match(/^\/calendars\/([^/]+)$/);
  if (calMatch) {
    const id = decodeURIComponent(calMatch[1]);
    if (method === "GET") return (req, res) => handleGetCalendar(req, res, id);
  }

  if (method === "GET" && url.startsWith("/events?")) return handleGetEvents;
  if (method === "GET" && url === "/events") return handleGetEvents;
  if (method === "POST" && url === "/events") return handleCreateEvent;

  const eventPeopleMatch = url.match(/^\/events\/([^/]+)\/people$/);
  if (eventPeopleMatch) {
    const id = decodeURIComponent(eventPeopleMatch[1]);
    if (method === "PUT") return (req, res) => handleUpdateEventPeople(req, res, id);
  }

  const eventMatch = url.match(/^\/events\/([^/]+)$/);
  if (eventMatch) {
    const id = decodeURIComponent(eventMatch[1]);
    if (method === "GET") return (req, res) => handleGetEvent(req, res, id);
    if (method === "PUT") return (req, res) => handleUpdateEvent(req, res, id);
    if (method === "DELETE") return (req, res) => handleDeleteEvent(req, res, id);
  }

  if (method === "POST" && url === "/reminders") return handleCreateReminder;

  const reminderMatch = url.match(/^\/reminders\/([^/]+)$/);
  if (reminderMatch) {
    const id = decodeURIComponent(reminderMatch[1]);
    if (method === "DELETE") return (req, res) => handleDeleteReminder(req, res, id);
  }

  if (method === "GET" && (url === "/google/cached-events" || url.startsWith("/google/cached-events?"))) {
    return handleGetGoogleCachedEvents;
  }

  if (method === "GET" && url === "/google/shared-calendars") return handleGetSharedCalendars;
  if (method === "GET" && url === "/google/sync-config") return handleGetSyncConfig;
  if (method === "PUT" && url === "/google/sync-config") return handlePutSyncConfig;

  return null;
}

initDb();
startReminderScheduler();
startGoogleSync();

const server = createServer(async (req, res) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");

  if (req.method === "OPTIONS") {
    res.writeHead(204);
    res.end();
    return;
  }

  const parsedUrl = new URL(req.url || "/", `http://localhost:${PORT}`);
  const handler = matchRoute(req.method || "GET", parsedUrl.pathname + parsedUrl.search);

  if (!handler) {
    res.writeHead(404, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ error: "Not found" }));
    return;
  }

  try {
    await handler(req, res);
  } catch (e) {
    console.error("Unhandled error:", e);
    if (!res.headersSent) {
      res.writeHead(500, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ error: "Internal server error" }));
    }
  }
});

server.listen(PORT, () => {
  console.log(`Calendar service listening on port ${PORT}`);
});
