import {
  applyAccountDeletionHandler,
  getDeletionConfigHandler,
  listDeletionRecordsHandler,
  listRetiredAccountsHandler,
  listDeletionStatusesHandler,
  putDeletionConfigHandler,
  reactivateAccountHandler,
  sendRecordMailNowHandler,
  sendTestMailHandler,
  searchAccountsHandler,
} from "@/controllers/admin/account-deletion/account-deletion.controller";
import { withConsoleUserRole } from "@/middlewares/console-role";
import { withConsoleUserSession } from "@/middlewares/withConsoleUserSession";
import { Hono } from "hono";

/**
 * Retiring a member account from the console.
 *
 * Two layers, the same split the Viewpoint routes use:
 *
 *   `withConsoleUserRole("members", …)` — the module the data belongs to, so
 *   reaching these endpoints follows the privilege that already governs member data.
 *
 *   the super-admin check inside every handler — the action itself. It lives in the
 *   controller because it needs the session the middleware above resolves, and it
 *   applies to the search too: who was looked up is as sensitive as what was done.
 *
 * Both reads are POST. The search carries an account number or an email, neither of
 * which belongs in a URL that is logged, cached and pasted into tickets — and the
 * activity-log middleware skips GETs, so a GET search would leave no trail.
 */
export const AccountDeletionRoutes = new Hono();

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

AccountDeletionRoutes.post(
  "/search",
  withConsoleUserRole("members", "read"),
  async (ctx) => searchAccountsHandler(ctx),
);

AccountDeletionRoutes.post(
  "/statuses",
  withConsoleUserRole("members", "read"),
  async (ctx) => listDeletionStatusesHandler(ctx),
);

AccountDeletionRoutes.post(
  "/apply",
  withConsoleUserRole("members", "delete"),
  async (ctx) => applyAccountDeletionHandler(ctx),
);

// The history of what has been retired, with each mail's outcome. Read-only.
AccountDeletionRoutes.post(
  "/records",
  withConsoleUserRole("members", "read"),
  async (ctx) => listDeletionRecordsHandler(ctx),
);

// Undoing a deletion. Same privilege as applying one — it is the same write to the
// same system of record, in the other direction.
AccountDeletionRoutes.post(
  "/reactivate",
  withConsoleUserRole("members", "delete"),
  async (ctx) => reactivateAccountHandler(ctx),
);

// The configured default templates, so the picker can name them.
AccountDeletionRoutes.post(
  "/config",
  withConsoleUserRole("members", "read"),
  async (ctx) => getDeletionConfigHandler(ctx),
);

/*
 * Sending on demand, and proving the path works.
 *
 * Both behind "delete" rather than "read": they put mail in front of a member (or
 * spend a send against SendGrid), which is not something a reader should be able to
 * do. Each handler additionally requires super admin.
 */
AccountDeletionRoutes.post(
  "/send-now",
  withConsoleUserRole("members", "delete"),
  async (ctx) => sendRecordMailNowHandler(ctx),
);

AccountDeletionRoutes.post(
  "/test-send",
  withConsoleUserRole("members", "delete"),
  async (ctx) => sendTestMailHandler(ctx),
);

// The follow-up window. Read is on /config above; this is the write.
AccountDeletionRoutes.put(
  "/config",
  withConsoleUserRole("members", "delete"),
  async (ctx) => putDeletionConfigHandler(ctx),
);

// Every account currently in a deletion status, however it got there.
AccountDeletionRoutes.post(
  "/retired",
  withConsoleUserRole("members", "read"),
  async (ctx) => listRetiredAccountsHandler(ctx),
);
