import { redirect } from "next/navigation";
import { inArray } from "drizzle-orm";
import { db } from "@db/client";
import { users } from "@db/schema";
import { getCurrentRole } from "@/lib/auth";
import { format } from "date-fns";
import { ScrollText } from "lucide-react";
import { getAuditLog, getAuditLogByAction } from "@db/queries/audit";
import { PageHeader, TableShell, EmptyState } from "@/components/ui";

export const metadata = { title: "Audit log · Admin" };

const ACTION_LABELS: Record<string, string> = {
  "organizer.status_change": "Changed organizer status",
  "organizer.password_reset_link": "Sent organizer a password reset link",
  "organizer.password_set": "Set organizer password",
  "organizer.view_as": "Started viewing as organizer",
  "settings.payout_rates": "Changed payout deduction rates",
  "event.change_notified": "Organizer notified ticket holders of a change",
  "organizer.view_as_ended": "Stopped viewing as organizer",
  "order.tickets_resent": "Resent order tickets",
  "order.tickets_whatsapp_opened": "Opened WhatsApp to send order tickets",
  "order.payment_checked": "Checked order payment with M-Pesa",
  "order.payment_confirmed_mpesa": "Confirmed order payment via M-Pesa",
  "order.payment_confirmed_manually": "Marked order paid manually",
  "payout_account.verify": "Verified payout account",
  "payout_account.unverify": "Un-verified payout account",
  "event.feature": "Featured event",
  "event.unfeature": "Un-featured event",
  "event.status_change": "Changed event status",
  "payout.run": "Ran M-Pesa payout",
  "payout.bank_paid": "Recorded bank payout",
  "refund.request": "Requested refund",
  "refund.approve": "Issued refund",
  "refund.reject": "Rejected refund",
  "event.submitted_for_review": "Organizer submitted event for approval",
  "event.approved": "Approved event",
  "event.rejected": "Rejected event",
  "ticket.cancel_for_upgrade": "Cancelled ticket for upgrade",
  "order.payment_confirmed_paystack": "Confirmed card payment via Paystack",
  "merch.shop_opened": "Opened a merch shop",
  "merch.shop_closed": "Closed a merch shop",
};

const SCAN_REASON: Record<string, string> = {
  not_a_ticket_code: "Not a VibePass QR",
  unknown_code: "No ticket with this code",
  bad_signature: "QR signature mismatch",
  wrong_account: "Scanned from an account that doesn't own the event",
  already_used: "Already checked in",
  void: "Ticket cancelled / refunded",
};

function describeDetail(detail: Record<string, unknown> | null): string {
  if (!detail) return "";
  if (typeof detail.from === "string" && typeof detail.to === "string") {
    return `${detail.from} → ${detail.to}`;
  }
  return "";
}

export default async function AdminAuditPage() {
  const { isAdmin } = await getCurrentRole();
  if (!isAdmin) redirect("/dashboard");

  const [entries, scans] = await Promise.all([
    getAuditLog(100, { excludeAction: "checkin.failed" }),
    getAuditLogByAction("checkin.failed", 50),
  ]);

  const actorIds = [...new Set([...entries, ...scans].map((e) => e.actor_id).filter(Boolean))] as string[];
  const profiles = actorIds.length ? await db.select({ id: users.id, name: users.name }).from(users).where(inArray(users.id, actorIds)) : [];
  const nameById = new Map(profiles.map((p) => [p.id, p.name]));

  return (
    <div className="space-y-6">
      <PageHeader icon={ScrollText} title="Audit log" description="Recent administrative actions." />

      <section className="space-y-2">
        <h2 className="text-lg font-medium text-be-text">Rejected scans</h2>
        <p className="text-sm text-be-muted">
          Every ticket the gate scanner turned away, with the reason and exactly what the camera read.
        </p>
        {scans.length === 0 ? (
          <p className="text-sm text-be-muted">No rejected scans yet.</p>
        ) : (
          <TableShell>
            <thead>
              <tr>
                <th>When</th>
                <th>Scanned by</th>
                <th>Reason</th>
                <th>Gate</th>
                <th>What was read</th>
              </tr>
            </thead>
            <tbody>
              {scans.map((s) => {
                const d = (s.detail ?? {}) as Record<string, string>;
                return (
                  <tr key={s.id}>
                    <td className="whitespace-nowrap text-be-muted">{format(new Date(s.created_at), "PP p")}</td>
                    <td className="text-be-text">{(s.actor_id && nameById.get(s.actor_id)) || "—"}</td>
                    <td className="text-be-text">
                      {SCAN_REASON[d.reason] ?? d.reason}
                      {d.eventTitle ? <span className="text-be-muted"> · {d.eventTitle}</span> : null}
                    </td>
                    <td className="text-be-muted">{d.gate ?? "—"}</td>
                    <td className="max-w-xs break-all font-mono text-xs text-be-muted">{d.scanned ?? ""}</td>
                  </tr>
                );
              })}
            </tbody>
          </TableShell>
        )}
      </section>

      <h2 className="text-lg font-medium text-be-text">Admin actions</h2>

      {entries.length === 0 ? (
        <EmptyState icon={ScrollText} title="No actions recorded yet" body="Admin actions are logged here." />
      ) : (
        <TableShell>
          <thead>
            <tr>
              <th>When</th>
              <th>Admin</th>
              <th>Action</th>
              <th>Detail</th>
            </tr>
          </thead>
          <tbody>
            {entries.map((e) => (
              <tr key={e.id}>
                <td className="whitespace-nowrap text-be-muted">
                  {format(new Date(e.created_at), "PP p")}
                </td>
                <td className="text-be-text">
                  {(e.actor_id && nameById.get(e.actor_id)) || (
                    <span className="text-be-muted opacity-70">System</span>
                  )}
                </td>
                <td className="text-be-text">{ACTION_LABELS[e.action] ?? e.action}</td>
                <td className="text-be-muted">{describeDetail(e.detail)}</td>
              </tr>
            ))}
          </tbody>
        </TableShell>
      )}
    </div>
  );
}
