import { Router } from "express";
import { google } from "googleapis";
import { z } from "zod";
import { requireAuth, requireCapability } from "../../middleware/auth";
import {
  getOwnerGoogleClient,
  GoogleNotConnectedError,
  isAuthError,
} from "../../lib/google-user";

export const calendarRouter = Router();
calendarRouter.use(requireAuth);

// Traduit les erreurs Google en réponses HTTP claires pour le frontend.
function handleGoogleError(res: import("express").Response, err: unknown) {
  if (err instanceof GoogleNotConnectedError) {
    return res.status(409).json({ error: "not_connected", message: "Compte Google non connecté." });
  }
  if (isAuthError(err)) {
    return res
      .status(409)
      .json({ error: "reconnect", message: "Connexion Google expirée, veuillez la reconnecter." });
  }
  console.error("Calendar API error:", err);
  return res.status(502).json({ error: "google_error", message: "Erreur lors de l'accès à Google Agenda." });
}

// GET /calendar/events — événements à venir (lecture).
calendarRouter.get("/events", requireCapability("agenda:read"), async (req, res) => {
  try {
    const auth = await getOwnerGoogleClient();
    const calendar = google.calendar({ version: "v3", auth });

    const timeMin = req.query.timeMin ? String(req.query.timeMin) : new Date().toISOString();
    const timeMax = req.query.timeMax ? String(req.query.timeMax) : undefined;
    const maxResults = Math.min(Number(req.query.maxResults) || 250, 2500);

    const { data } = await calendar.events.list({
      calendarId: "primary",
      timeMin,
      timeMax,
      maxResults,
      singleEvents: true,
      orderBy: "startTime",
    });

    const events = (data.items ?? []).map((e) => ({
      id: e.id,
      summary: e.summary ?? "(sans titre)",
      start: e.start?.dateTime ?? e.start?.date ?? null,
      end: e.end?.dateTime ?? e.end?.date ?? null,
      allDay: !e.start?.dateTime,
      location: e.location ?? null,
      description: e.description ?? null,
      htmlLink: e.htmlLink ?? null,
    }));

    return res.json({ events });
  } catch (err) {
    return handleGoogleError(res, err);
  }
});

const createSchema = z.object({
  summary: z.string().min(1),
  start: z.string().min(1), // ISO 8601 (RFC3339)
  end: z.string().min(1),
  location: z.string().optional(),
  description: z.string().optional(),
});

// POST /calendar/events — créer un RDV (écriture, admin/super_admin).
calendarRouter.post("/events", requireCapability("agenda:write"), async (req, res) => {
  const parsed = createSchema.safeParse(req.body);
  if (!parsed.success) {
    return res.status(400).json({ error: "invalid", message: "Champs invalides (titre, début, fin requis)." });
  }
  const { summary, start, end, location, description } = parsed.data;

  try {
    const auth = await getOwnerGoogleClient();
    const calendar = google.calendar({ version: "v3", auth });

    const { data } = await calendar.events.insert({
      calendarId: "primary",
      requestBody: {
        summary,
        location,
        description,
        start: { dateTime: start },
        end: { dateTime: end },
      },
    });

    return res.status(201).json({
      event: { id: data.id, summary: data.summary, htmlLink: data.htmlLink },
    });
  } catch (err) {
    return handleGoogleError(res, err);
  }
});

// DELETE /calendar/events/:id — supprimer un RDV (écriture).
calendarRouter.delete("/events/:id", requireCapability("agenda:write"), async (req, res) => {
  try {
    const auth = await getOwnerGoogleClient();
    const calendar = google.calendar({ version: "v3", auth });
    await calendar.events.delete({ calendarId: "primary", eventId: String(req.params.id) });
    return res.json({ ok: true });
  } catch (err) {
    return handleGoogleError(res, err);
  }
});
