import { redirect } from "next/navigation";
import { inArray } from "drizzle-orm";
import { db } from "@db/client";
import { users, payoutAccounts } from "@db/schema";
import { getCurrentRole } from "@/lib/auth";
import { formatPrice } from "@/lib/format";
import { format } from "date-fns";
import { getPlatformEarnings, getAllPayouts, owedCents } from "@db/queries/payouts";
import { Banknote, Users as UsersIcon, Coins, Smartphone, Landmark } from "lucide-react";
import type { PayoutAccountType, PayoutStatus } from "@/lib/types";
import PayoutActions from "./payout-actions";
import { PageHeader, StatCard, TableShell, StatusPill, EmptyState, type Tone } from "@/components/ui";

export const metadata = { title: "Payouts · Admin" };

const STATUS_TONE: Record<PayoutStatus, Tone> = {
  pending: "muted",
  processing: "warn",
  paid: "ok",
  failed: "danger",
};

export default async function AdminPayoutsPage() {
  const { isAdmin } = await getCurrentRole();
  if (!isAdmin) redirect("/dashboard");

  const [earnings, payouts] = await Promise.all([getPlatformEarnings(), getAllPayouts()]);

  const ids = earnings.map((e) => e.organizer_id);
  const [profiles, accounts] = ids.length
    ? await Promise.all([
        db.select({ id: users.id, name: users.name, email: users.email }).from(users).where(inArray(users.id, ids)),
        db
          .select({
            organizerId: payoutAccounts.organizerId,
            type: payoutAccounts.type,
            verified: payoutAccounts.verified,
            withdrawalRequestedAt: payoutAccounts.withdrawalRequestedAt,
          })
          .from(payoutAccounts)
          .where(inArray(payoutAccounts.organizerId, ids)),
      ])
    : [[], []];

  const nameById = new Map(profiles.map((p) => [p.id, p.name?.trim() || p.email]));
  const acctById = new Map(
    accounts.map((a) => [
      a.organizerId,
      a as { type: PayoutAccountType; verified: boolean; withdrawalRequestedAt: Date | null },
    ])
  );
  const payoutsByOrganizer = new Map<string, typeof payouts>();
  for (const p of payouts) {
    const list = payoutsByOrganizer.get(p.organizer_id) ?? [];
    list.push(p);
    payoutsByOrganizer.set(p.organizer_id, list);
  }

  const rows = earnings
    .map((e) => {
      const orgPayouts = payoutsByOrganizer.get(e.organizer_id) ?? [];
      const owed = owedCents(e.net_cents, orgPayouts);
      const inFlight = orgPayouts.some((p) =>
        (["pending", "processing"] as string[]).includes(p.status)
      );
      const acct = acctById.get(e.organizer_id) ?? null;
      const currency = e.currency ?? "kes";
      const requested = !!acct?.withdrawalRequestedAt;
      return { e, owed, inFlight, acct, currency, requested };
    })
    .sort((a, b) => (a.requested === b.requested ? b.owed - a.owed : a.requested ? -1 : 1));

  const totalOwed = rows.reduce((sum, r) => sum + Math.max(r.owed, 0), 0);
  const totalCurrency = rows[0]?.currency ?? "kes";

  return (
    <div className="space-y-8">
      <PageHeader
        icon={Banknote}
        title="Payouts"
        description="Disburse what organizers are owed. M-Pesa runs automatically; bank transfers are recorded manually."
      />

      <section className="grid grid-cols-2 sm:grid-cols-3 gap-3">
        <StatCard icon={UsersIcon} label="Organizers" value={rows.length.toString()} />
        <StatCard icon={Coins} label="Outstanding owed" value={formatPrice(totalOwed, totalCurrency)} accent="gold" />
        <StatCard icon={Banknote} label="Payouts run" value={payouts.length.toString()} />
      </section>

      <section className="space-y-3">
        <h2 className="text-lg font-medium text-be-text">Owed balances</h2>
        {rows.length === 0 ? (
          <EmptyState icon={Coins} title="No earnings yet" body="Owed balances appear once organizers make sales." />
        ) : (
          <TableShell>
            <thead>
              <tr>
                <th>Organizer</th>
                <th>Payout</th>
                <th className="text-right">Net</th>
                <th className="text-right">Owed</th>
                <th className="text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {rows.map(({ e, owed, inFlight, acct, currency, requested }) => (
                <tr key={e.organizer_id}>
                  <td className="font-medium text-be-text">
                    <span className="inline-flex items-center gap-2">
                      {nameById.get(e.organizer_id) || (
                        <span className="text-be-muted opacity-70">Unnamed</span>
                      )}
                      {requested && <StatusPill tone="warn">Requested</StatusPill>}
                    </span>
                  </td>
                  <td>
                    {acct ? (
                      <span className="inline-flex items-center gap-2 text-be-text">
                        <span className="inline-flex items-center gap-1">
                          {acct.type === "mpesa" ? (
                            <Smartphone className="h-3.5 w-3.5 text-be-muted" />
                          ) : (
                            <Landmark className="h-3.5 w-3.5 text-be-muted" />
                          )}
                          {acct.type === "mpesa" ? "M-Pesa" : "Bank"}
                        </span>
                        <StatusPill tone={acct.verified ? "ok" : "warn"}>
                          {acct.verified ? "Verified" : "Pending"}
                        </StatusPill>
                      </span>
                    ) : (
                      <span className="text-xs text-be-muted opacity-70">Not set up</span>
                    )}
                  </td>
                  <td className="text-right tabular-nums text-be-text">
                    {formatPrice(e.net_cents, currency)}
                    {(e.merch_orders ?? 0) > 0 && (
                      <span className="block text-xs text-be-muted">
                        incl. {formatPrice(e.merch_net_cents ?? 0, currency)} merch
                      </span>
                    )}
                  </td>
                  <td className="text-right font-medium tabular-nums text-be-text">
                    {formatPrice(Math.max(owed, 0), currency)}
                  </td>
                  <td className="text-right">
                    <PayoutActions
                      organizerId={e.organizer_id}
                      method={acct?.type ?? null}
                      verified={acct?.verified ?? false}
                      owedCents={owed}
                      currency={currency}
                      inFlight={inFlight}
                    />
                  </td>
                </tr>
              ))}
            </tbody>
          </TableShell>
        )}
      </section>

      <section className="space-y-3">
        <h2 className="text-lg font-medium text-be-text">Recent payouts</h2>
        {payouts.length === 0 ? (
          <EmptyState icon={Banknote} title="No payouts yet" body="Disbursements you run will be listed here." />
        ) : (
          <TableShell>
            <thead>
              <tr>
                <th>When</th>
                <th>Organizer</th>
                <th>Method</th>
                <th className="text-right">Amount</th>
                <th>Status</th>
                <th>Reference</th>
              </tr>
            </thead>
            <tbody>
              {payouts.slice(0, 25).map((p) => (
                <tr key={p.id}>
                  <td className="whitespace-nowrap text-be-muted">
                    {format(new Date(p.created_at), "PP")}
                  </td>
                  <td className="text-be-text">
                    {nameById.get(p.organizer_id) || (
                      <span className="text-be-muted opacity-70">Unnamed</span>
                    )}
                  </td>
                  <td className="text-be-text">{p.method === "mpesa" ? "M-Pesa" : "Bank"}</td>
                  <td className="text-right tabular-nums text-be-text">
                    {formatPrice(p.amount_cents, p.currency)}
                  </td>
                  <td>
                    <StatusPill tone={STATUS_TONE[p.status] ?? "muted"}>{p.status}</StatusPill>
                    {p.status === "failed" && p.failure_reason && (
                      <span className="ml-2 text-xs text-be-muted">{p.failure_reason}</span>
                    )}
                  </td>
                  <td className="text-xs text-be-muted">
                    {p.b2c_transaction_id || p.notes || "—"}
                  </td>
                </tr>
              ))}
            </tbody>
          </TableShell>
        )}
      </section>
    </div>
  );
}
