import { Hono } from "hono";
import { withConsoleUserSession } from "@/middlewares/withConsoleUserSession";
import { withConsoleUserRole } from "@/middlewares/console-role";
import {
  commitViewpointImportHandler,
  countViewpointBookingsHandler,
  deleteViewpointDataHandler,
  listViewpointBookingsHandler,
  listViewpointImportsHandler,
  listViewpointMemberContactsHandler,
  syncViewpointBookingsHandler,
  syncViewpointFromCoreHandler,
  viewpointBookingAnalyticsHandler,
  viewpointDirectByPromoCodeHandler,
  viewpointFieldsHandler,
} from "@/controllers/admin/viewpoint/viewpoint.controller";

/**
 * Manually imported Viewpoint reports.
 *
 * Two layers of authorization, doing different jobs:
 *
 *   `withConsoleUserRole("promo-code-campaigns", ...)` — the same privilege that
 *   governs the bookings pages this data is shown on, so read access follows what a
 *   user can already see rather than inventing a second answer for the same screen.
 *
 *   the super-admin check inside the handlers — for importing and for syncing. Both
 *   write, and syncing additionally spends requests against a shared production
 *   system. That check lives in the controller, not here, because it needs the
 *   session the middleware above resolves.
 *
 * Reads are POST rather than GET: they carry filter arrays (sources, statuses,
 * membership numbers) which do not survive a query string cleanly. The rest of the
 * promo-code endpoints already do this, so the console's client is uniform.
 */
export const ViewpointRoutes = new Hono();

ViewpointRoutes.use("*", withConsoleUserSession());

// The field catalogue and the per-header mapping guess. Read-only, and needed
// before an import can be described, so it sits behind read rather than import.
ViewpointRoutes.post(
  "/fields",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => viewpointFieldsHandler(ctx),
);

ViewpointRoutes.post(
  "/imports",
  // "create" is the privilege for adding data; the handler additionally requires
  // super admin.
  withConsoleUserRole("promo-code-campaigns", "create"),
  async (ctx) => commitViewpointImportHandler(ctx),
);

ViewpointRoutes.get(
  "/imports",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => listViewpointImportsHandler(ctx),
);

ViewpointRoutes.post(
  "/bookings",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => listViewpointBookingsHandler(ctx),
);

ViewpointRoutes.post(
  "/bookings/analytics",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => viewpointBookingAnalyticsHandler(ctx),
);

ViewpointRoutes.post(
  "/bookings/sync",
  withConsoleUserRole("promo-code-campaigns", "update"),
  async (ctx) => syncViewpointBookingsHandler(ctx),
);

/*
 * Console-only delete. `withConsoleUserRole(..., "delete")` is the feature
 * privilege; the handler additionally requires super admin, because removing
 * imported data affects what every user sees.
 */
ViewpointRoutes.post(
  "/bookings/count",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => countViewpointBookingsHandler(ctx),
);

/*
 * Reconciliation against core. `update` because it writes the match columns; no
 * super-admin gate, since it only establishes which bookings core already knows about
 * and overwrites nothing either system told us.
 */
/*
 * Read-only, and read by the campaigns dashboard rather than the Viewpoint page — so it
 * takes the same `read` privilege the rest of the promo pages use.
 */
ViewpointRoutes.get(
  "/bookings/by-promo-code",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => viewpointDirectByPromoCodeHandler(ctx),
);

ViewpointRoutes.post(
  "/bookings/sync-core",
  withConsoleUserRole("promo-code-campaigns", "update"),
  async (ctx) => syncViewpointFromCoreHandler(ctx),
);

ViewpointRoutes.post(
  "/imports/delete",
  withConsoleUserRole("promo-code-campaigns", "delete"),
  async (ctx) => deleteViewpointDataHandler(ctx),
);

ViewpointRoutes.post(
  "/member-contacts",
  withConsoleUserRole("promo-code-campaigns", "read"),
  async (ctx) => listViewpointMemberContactsHandler(ctx),
);
