import type { AdminActionRunResponse } from "@xtablo/shared-types";
import { Hono } from "hono";
import { recordAdminAuditLog } from "../helpers/adminAudit.js";
import { getAdminActionDefinition, listAdminActions } from "../helpers/adminRegistry.js";
import type { BaseEnv } from "../types/app.types.js";

type ActionInput = {
  reason?: string;
  tabloId?: string;
  userId?: string;
};

function getActionInput(body: unknown): ActionInput {
  if (!body || typeof body !== "object") {
    return {};
  }

  const input = body as Record<string, unknown>;

  return {
    reason: typeof input.reason === "string" ? input.reason : undefined,
    tabloId: typeof input.tabloId === "string" ? input.tabloId : undefined,
    userId: typeof input.userId === "string" ? input.userId : undefined,
  };
}

export const getAdminActionsRouter = () => {
  const adminActionsRouter = new Hono<BaseEnv>();

  adminActionsRouter.get("/", async (c) => {
    return c.json({ actions: listAdminActions() }, 200);
  });

  adminActionsRouter.post("/:actionId/run", async (c) => {
    const supabase = c.get("supabase");
    const adminSession = c.get("adminSession");
    const actionId = c.req.param("actionId");
    const definition = getAdminActionDefinition(actionId);

    if (!definition) {
      return c.json({ error: `Admin action '${actionId}' is not registered` }, 404);
    }

    const { reason, tabloId, userId } = getActionInput(await c.req.json().catch(() => null));

    if (!tabloId || !userId || !reason) {
      return c.json({ error: "tabloId, userId, and reason are required" }, 400);
    }

    const { data: before, error: beforeError } = await supabase
      .from("tablo_access")
      .select("id,tablo_id,user_id,is_active,is_admin")
      .eq("tablo_id", tabloId)
      .eq("user_id", userId)
      .maybeSingle();

    if (beforeError) {
      return c.json({ error: `Failed to load tablo access for action '${actionId}'` }, 500);
    }

    if (!before) {
      return c.json({ error: "Target tablo access row was not found" }, 404);
    }

    const changes =
      actionId === "grant_tablo_admin" ? { is_active: true, is_admin: true } : { is_active: false };

    const { data: after, error: updateError } = await supabase
      .from("tablo_access")
      .update(changes)
      .eq("id", before.id)
      .select("id,tablo_id,user_id,is_active,is_admin")
      .single();

    if (updateError || !after) {
      return c.json({ error: `Failed to run admin action '${actionId}'` }, 500);
    }

    await recordAdminAuditLog({
      action: `${actionId}:${reason}`,
      after,
      before,
      operatorEmail: adminSession.operatorEmail,
      operatorId: adminSession.operatorId,
      role: adminSession.role,
      supabase,
      targetId: `${tabloId}:${userId}`,
      targetType: "tablo_access",
    });

    return c.json(
      {
        message:
          actionId === "grant_tablo_admin"
            ? "Tablo admin access granted and logged."
            : "Tablo access deactivated and logged.",
        success: true,
      } satisfies AdminActionRunResponse,
      200
    );
  });

  return adminActionsRouter;
};
