import React, { useEffect, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";
import { useForm } from "@tanstack/react-form";
import {
  QueryClient,
  QueryClientProvider,
  useMutation,
  useQuery,
  useQueryClient,
} from "@tanstack/react-query";
import {
  ActivityIcon,
  AlertTriangleIcon,
  BarChart3Icon,
  ChevronDownIcon,
  ChevronUpIcon,
  Clock3Icon,
  FileTextIcon,
  GaugeIcon,
  KeyRoundIcon,
  LogOutIcon,
  MailIcon,
  PowerIcon,
  RefreshCwIcon,
  RepeatIcon,
  SendIcon,
  ShieldCheckIcon,
  SlidersHorizontalIcon,
  UserPlusIcon,
  UsersIcon,
  type LucideIcon,
} from "lucide-react";
import {
  api,
  ApiClient,
  type AppLog,
  type AuthSession,
  type DashboardAnalytics,
  type DashboardScope,
  type DashboardUser,
  type EmailEvent,
  type ProvidersConfigInput,
  type ProviderStatus,
  type UsageEvent,
} from "./api";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Field,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Textarea } from "@/components/ui/textarea";
import "./styles.css";

const sessionKey = "rinci-hub-token";
const numberFormatter = new Intl.NumberFormat("en");
const percentFormatter = new Intl.NumberFormat("en", {
  maximumFractionDigits: 1,
  style: "percent",
});
const queryClient = new QueryClient();

type DashboardPage =
  | "overview"
  | "analytics"
  | "users"
  | "emails"
  | "usage"
  | "logs"
  | "settings";

const dashboardPages: Array<{
  id: DashboardPage;
  label: string;
  icon: LucideIcon;
  managerOnly?: boolean;
}> = [
  { id: "overview", label: "Overview", icon: GaugeIcon },
  { id: "analytics", label: "Analytics", icon: BarChart3Icon },
  { id: "users", label: "Users", icon: UsersIcon, managerOnly: true },
  { id: "emails", label: "Email events", icon: MailIcon },
  { id: "usage", label: "API usage", icon: ActivityIcon },
  { id: "logs", label: "Logs", icon: FileTextIcon },
  { id: "settings", label: "Settings", icon: SlidersHorizontalIcon },
];

function formatDate(value: string | null) {
  if (!value) return "Never";
  return new Intl.DateTimeFormat("en", {
    month: "short",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  }).format(new Date(value));
}

function formatCount(value: number) {
  return numberFormatter.format(value);
}

function formatPercent(value: number) {
  return percentFormatter.format(value);
}

function canManage(session: AuthSession) {
  return (
    session.scopes.includes("*") ||
    session.user.role === "service" ||
    session.user.role === "admin" ||
    session.user.role === "manager"
  );
}

function statusVariant(
  value: "good" | "warn" | "neutral" | "bad",
): React.ComponentProps<typeof Badge>["variant"] {
  if (value === "bad") return "destructive";
  if (value === "neutral") return "secondary";
  return "outline";
}

function StatusBadge({
  tone,
  children,
}: {
  tone: "good" | "warn" | "neutral" | "bad";
  children: React.ReactNode;
}) {
  return (
    <Badge className="shrink-0 uppercase" variant={statusVariant(tone)}>
      {children}
    </Badge>
  );
}

function emailStatusTone(
  status: EmailEvent["status"],
): "good" | "warn" | "neutral" | "bad" {
  if (status === "failed") return "bad";
  if (status === "processing") return "warn";
  if (status === "queued") return "neutral";
  return "good";
}

function LoginPanel({ onLogin }: { onLogin: (session: AuthSession) => void }) {
  const [error, setError] = useState<string | null>(null);
  const form = useForm({
    defaultValues: { token: "" },
    onSubmit: async ({ value }) => {
      const token = value.token.trim();
      setError(null);
      try {
        const client = api.withToken(token);
        const result = await client.login(token);
        sessionStorage.setItem(sessionKey, token);
        onLogin({
          token,
          user: result.user,
          scopes: result.auth.scopes,
        });
      } catch (err) {
        setError(err instanceof Error ? err.message : "Login failed");
      }
    },
  });

  return (
    <main className="flex min-h-[100dvh] items-center justify-center bg-muted/40 p-4">
      <Card className="w-full max-w-md">
        <CardHeader className="gap-4">
          <Avatar className="size-11 rounded-lg">
            <AvatarFallback className="rounded-lg bg-primary text-primary-foreground">
              RH
            </AvatarFallback>
          </Avatar>
          <div>
            <CardTitle className="text-3xl">Rinci Hub</CardTitle>
            <CardDescription>
              Sign in with a service key or generated Hub API key.
            </CardDescription>
          </div>
        </CardHeader>
        <CardContent>
          <form
            onSubmit={(event) => {
              event.preventDefault();
              event.stopPropagation();
              void form.handleSubmit();
            }}
          >
            <FieldGroup>
              <form.Field
                name="token"
                validators={{
                  onChange: ({ value }) =>
                    value.trim().length >= 16 ? undefined : "Enter a valid token.",
                }}
              >
                {(field) => (
                  <Field data-invalid={field.state.meta.errors.length > 0}>
                    <FieldLabel htmlFor={field.name}>API token</FieldLabel>
                    <Input
                      id={field.name}
                      type="password"
                      value={field.state.value}
                      onBlur={field.handleBlur}
                      onChange={(event) => field.handleChange(event.target.value)}
                      placeholder="hub_... or service key"
                      autoComplete="current-password"
                      aria-invalid={field.state.meta.errors.length > 0}
                    />
                    <FieldError errors={field.state.meta.errors} />
                  </Field>
                )}
              </form.Field>
            {error ? (
              <Alert variant="destructive">
                <AlertDescription>{error}</AlertDescription>
              </Alert>
            ) : null}
              <form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting, state.values.token]}>
                {([canSubmit, isSubmitting, token]) => {
                  const tokenValue = String(token);
                  return (
                    <Button
                      type="submit"
                      disabled={!canSubmit || Boolean(isSubmitting) || tokenValue.trim().length < 16}
                    >
                      <KeyRoundIcon data-icon="inline-start" />
                      {isSubmitting ? "Checking..." : "Open dashboard"}
                    </Button>
                  );
                }}
              </form.Subscribe>
            </FieldGroup>
          </form>
        </CardContent>
      </Card>
    </main>
  );
}

function MetricCard({
  label,
  value,
  hint,
  icon: Icon,
}: {
  label: string;
  value: string | number;
  hint: string;
  icon: LucideIcon;
}) {
  return (
    <Card size="sm">
      <CardHeader className="grid-cols-[1fr_auto]">
        <div className="min-w-0">
          <CardDescription>{label}</CardDescription>
          <CardTitle className="mt-1 text-3xl tabular-nums">{value}</CardTitle>
        </div>
        <div className="flex size-9 items-center justify-center rounded-lg border bg-muted">
          <Icon data-icon="inline-start" />
        </div>
      </CardHeader>
      <CardContent>
        <p className="text-sm text-muted-foreground">{hint}</p>
      </CardContent>
    </Card>
  );
}

function BucketList({
  title,
  items,
}: {
  title: string;
  items: Array<{ name: string; count: number }>;
}) {
  const max = Math.max(...items.map((item) => item.count), 1);

  return (
    <Card>
      <CardHeader>
        <CardTitle>{title}</CardTitle>
      </CardHeader>
      <CardContent className="flex flex-col gap-3">
        {items.map((item) => (
          <div className="grid gap-2" key={item.name}>
            <div className="flex items-center justify-between gap-3 text-sm">
              <span className="truncate font-medium">{item.name}</span>
              <span className="tabular-nums text-muted-foreground">
                {formatCount(item.count)}
              </span>
            </div>
            <div className="h-2 overflow-hidden rounded-full bg-muted">
              <div
                className="h-full rounded-full bg-primary"
                style={{ width: `${Math.max(6, (item.count / max) * 100)}%` }}
              />
            </div>
          </div>
        ))}
        {items.length === 0 ? (
          <p className="text-sm text-muted-foreground">No records in this range.</p>
        ) : null}
      </CardContent>
    </Card>
  );
}

function AnalyticsPanel({ analytics }: { analytics: DashboardAnalytics }) {
  return (
    <div className="grid gap-4">
      <section className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <MetricCard
          label="24h requests"
          value={formatCount(analytics.totals.requests)}
          hint={`${formatCount(analytics.totals.errors)} errors recorded`}
          icon={ActivityIcon}
        />
        <MetricCard
          label="Failure rate"
          value={formatPercent(analytics.totals.failureRate)}
          hint="HTTP 4xx/5xx over total requests"
          icon={AlertTriangleIcon}
        />
        <MetricCard
          label="Average latency"
          value={`${formatCount(analytics.totals.averageDurationMs)}ms`}
          hint="Mean protected route duration"
          icon={Clock3Icon}
        />
        <MetricCard
          label="Active users"
          value={formatCount(analytics.totals.activeUsers)}
          hint="Distinct users with API traffic"
          icon={UsersIcon}
        />
      </section>

      <section className="grid gap-4 xl:grid-cols-3">
        <BucketList title="Requests by status" items={analytics.requestsByStatus} />
        <BucketList title="Emails by status" items={analytics.emailsByStatus} />
        <BucketList title="Emails by provider" items={analytics.emailsByProvider} />
      </section>

      <Card>
        <CardHeader>
          <CardTitle>Top routes</CardTitle>
          <CardDescription>Highest traffic protected routes in the last 24 hours</CardDescription>
        </CardHeader>
        <CardContent>
          <div className="overflow-x-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Route</TableHead>
                  <TableHead>Requests</TableHead>
                  <TableHead>Errors</TableHead>
                  <TableHead>Avg duration</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {analytics.topRoutes.map((route) => (
                  <TableRow key={`${route.method}:${route.path}`}>
                    <TableCell>
                      <div className="min-w-56">
                        <p className="font-medium">{route.method}</p>
                        <p className="truncate text-sm text-muted-foreground">
                          {route.path}
                        </p>
                      </div>
                    </TableCell>
                    <TableCell>{formatCount(route.requests)}</TableCell>
                    <TableCell>{formatCount(route.errors)}</TableCell>
                    <TableCell>{formatCount(route.averageDurationMs)}ms</TableCell>
                  </TableRow>
                ))}
                {analytics.topRoutes.length === 0 ? (
                  <TableRow>
                    <TableCell className="text-muted-foreground" colSpan={4}>
                      No route activity in this range.
                    </TableCell>
                  </TableRow>
                ) : null}
              </TableBody>
            </Table>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

function ScopeSwitch({
  scope,
  disabled,
  onChange,
}: {
  scope: DashboardScope;
  disabled: boolean;
  onChange: (scope: DashboardScope) => void;
}) {
  return (
    <div className="grid grid-cols-2 rounded-lg border bg-muted p-1">
      {(["mine", "all"] as const).map((item) => (
        <Button
          key={item}
          disabled={disabled && item === "all"}
          size="sm"
          variant={scope === item ? "secondary" : "ghost"}
          onClick={() => onChange(item)}
        >
          {item === "mine" ? "My data" : "All data"}
        </Button>
      ))}
    </div>
  );
}

function ProviderRail({
  providers,
  manager,
  pending,
  onUpdate,
}: {
  providers: ProviderStatus[];
  manager: boolean;
  pending: boolean;
  onUpdate: (config: ProvidersConfigInput) => void;
}) {
  // Render in routing order; disabled providers sort last.
  const ordered = [...providers].sort((a, b) => a.order - b.order);
  const enabledNames = ordered
    .filter((provider) => provider.role !== "disabled")
    .map((provider) => provider.name);

  function toggle(provider: ProviderStatus) {
    const enabled = provider.role === "disabled";
    onUpdate({ enabled: { [provider.name]: enabled } });
  }

  function move(provider: ProviderStatus, direction: -1 | 1) {
    const index = enabledNames.indexOf(provider.name);
    const target = index + direction;
    if (index < 0 || target < 0 || target >= enabledNames.length) return;
    const next = [...enabledNames];
    [next[index], next[target]] = [next[target], next[index]];
    onUpdate({ order: next });
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle>Providers</CardTitle>
        <CardDescription>
          {manager
            ? "Toggle providers and set routing order"
            : "Routing order and readiness"}
        </CardDescription>
      </CardHeader>
      <CardContent className="flex flex-col gap-3">
        {ordered.map((provider) => {
          const isEnabled = provider.role !== "disabled";
          const enabledIndex = enabledNames.indexOf(provider.name);
          return (
            <div
              className="flex items-center justify-between gap-3 rounded-lg border p-3"
              key={provider.name}
            >
              <div className="min-w-0">
                <p className="font-semibold uppercase">{provider.name}</p>
                <p className="truncate text-sm text-muted-foreground">
                  {provider.host ?? provider.endpoint ?? "Not configured"}
                </p>
              </div>
              <div className="flex items-center gap-2">
                <StatusBadge
                  tone={
                    !isEnabled ? "neutral" : provider.configured ? "good" : "warn"
                  }
                >
                  {provider.role}
                </StatusBadge>
                {manager ? (
                  <>
                    {isEnabled ? (
                      <div className="flex flex-col">
                        <Button
                          size="icon"
                          variant="ghost"
                          className="h-5 w-6"
                          aria-label={`Move ${provider.name} up`}
                          disabled={pending || enabledIndex <= 0}
                          onClick={() => move(provider, -1)}
                        >
                          <ChevronUpIcon className="h-4 w-4" />
                        </Button>
                        <Button
                          size="icon"
                          variant="ghost"
                          className="h-5 w-6"
                          aria-label={`Move ${provider.name} down`}
                          disabled={
                            pending || enabledIndex >= enabledNames.length - 1
                          }
                          onClick={() => move(provider, 1)}
                        >
                          <ChevronDownIcon className="h-4 w-4" />
                        </Button>
                      </div>
                    ) : null}
                    <Button
                      size="icon"
                      variant={isEnabled ? "secondary" : "ghost"}
                      aria-label={`${isEnabled ? "Disable" : "Enable"} ${provider.name}`}
                      title={isEnabled ? "Disable provider" : "Enable provider"}
                      disabled={pending}
                      onClick={() => toggle(provider)}
                    >
                      <PowerIcon className="h-4 w-4" />
                    </Button>
                  </>
                ) : null}
              </div>
            </div>
          );
        })}
      </CardContent>
    </Card>
  );
}

function RegisterUserPanel({
  client,
  disabled,
  onRegistered,
}: {
  client: ApiClient;
  disabled: boolean;
  onRegistered: () => Promise<void>;
}) {
  const [result, setResult] = useState<string | null>(null);
  const form = useForm({
    defaultValues: {
      email: "",
      name: "",
      sendScope: true,
      taskScope: false,
    },
    onSubmit: async ({ value, formApi }) => {
      setResult(null);
      const scopes = ["user"];
      if (value.sendScope) scopes.push("emails:send");
      if (value.taskScope) scopes.push("tasks:enqueue");
      const response = await client.registerUser({
        email: value.email.trim(),
        name: value.name.trim() || undefined,
        scopes,
      });
      setResult(`Created ${response.user.email}. API key: ${response.apiKey.token}`);
      formApi.reset();
      await onRegistered();
    },
  });

  return (
    <Card>
      <CardHeader>
        <CardTitle>Register user</CardTitle>
        <CardDescription>Service-key and manager-only API issuance</CardDescription>
      </CardHeader>
      <CardContent>
        <form
          onSubmit={(event) => {
            event.preventDefault();
            event.stopPropagation();
            void form.handleSubmit().catch((err) => {
              setResult(err instanceof Error ? err.message : "Registration failed");
            });
          }}
        >
          <FieldGroup>
            <div className="grid gap-3 sm:grid-cols-2">
              <form.Field
                name="email"
                validators={{
                  onChange: ({ value }) =>
                    /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
                      ? undefined
                      : "Use a valid email address.",
                }}
              >
                {(field) => (
                  <Field data-invalid={field.state.meta.errors.length > 0}>
                    <FieldLabel htmlFor={field.name}>Email</FieldLabel>
                    <Input
                      id={field.name}
                      disabled={disabled}
                      value={field.state.value}
                      onBlur={field.handleBlur}
                      onChange={(event) => field.handleChange(event.target.value)}
                      placeholder="name@example.com"
                      aria-invalid={field.state.meta.errors.length > 0}
                    />
                    <FieldError errors={field.state.meta.errors} />
                  </Field>
                )}
              </form.Field>
              <form.Field name="name">
                {(field) => (
                  <Field>
                    <FieldLabel htmlFor={field.name}>Name</FieldLabel>
                    <Input
                      id={field.name}
                      disabled={disabled}
                      value={field.state.value}
                      onBlur={field.handleBlur}
                      onChange={(event) => field.handleChange(event.target.value)}
                      placeholder="Optional"
                    />
                  </Field>
                )}
              </form.Field>
            </div>
            <FieldSet>
              <FieldLegend variant="label">Scopes</FieldLegend>
              <div className="grid gap-3 sm:grid-cols-2">
                <form.Field name="sendScope">
                  {(field) => (
                    <Field orientation="horizontal">
                      <Checkbox
                        checked={field.state.value}
                        disabled={disabled}
                        onCheckedChange={(checked) => field.handleChange(checked === true)}
                      />
                      <div>
                        <FieldLabel>Email sending</FieldLabel>
                        <FieldDescription>Allow POST /api/emails.</FieldDescription>
                      </div>
                    </Field>
                  )}
                </form.Field>
                <form.Field name="taskScope">
                  {(field) => (
                    <Field orientation="horizontal">
                      <Checkbox
                        checked={field.state.value}
                        disabled={disabled}
                        onCheckedChange={(checked) => field.handleChange(checked === true)}
                      />
                      <div>
                        <FieldLabel>Task enqueue</FieldLabel>
                        <FieldDescription>Allow scheduled task creation.</FieldDescription>
                      </div>
                    </Field>
                  )}
                </form.Field>
              </div>
            </FieldSet>
            <form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting, state.values.email]}>
              {([canSubmit, isSubmitting, email]) => {
                const emailValue = String(email);
                return (
                  <Button
                    type="submit"
                    disabled={disabled || !canSubmit || Boolean(isSubmitting) || !emailValue.trim()}
                    className="w-full sm:w-fit"
                  >
                    <UserPlusIcon data-icon="inline-start" />
                    {isSubmitting ? "Creating..." : "Create user and key"}
                  </Button>
                );
              }}
            </form.Subscribe>
          {result ? (
            <Alert>
              <AlertDescription className="break-all">{result}</AlertDescription>
            </Alert>
          ) : null}
          </FieldGroup>
        </form>
      </CardContent>
    </Card>
  );
}

function SendEmailPanel({
  client,
  onSent,
}: {
  client: ApiClient;
  onSent: () => Promise<void>;
}) {
  const [status, setStatus] = useState<string | null>(null);
  const form = useForm({
    defaultValues: {
      to: "",
      subject: "Rinci Hub email API test",
      body: "Sent from the Rinci Hub dashboard.",
      html: false,
    },
    onSubmit: async ({ value }) => {
      setStatus(null);
      const result = await client.sendEmail({
        from: "Rinci Hub <hello@mail.rin.ci>",
        to: value.to,
        subject: value.subject,
        ...(value.html ? { html: value.body } : { text: value.body }),
      });
      setStatus(`Queued ${result.id}`);
      await onSent();
    },
  });

  return (
    <Card>
      <CardHeader>
        <CardTitle>Send email</CardTitle>
        <CardDescription>Resend-compatible POST /api/emails</CardDescription>
      </CardHeader>
      <CardContent>
        <form
          onSubmit={(event) => {
            event.preventDefault();
            event.stopPropagation();
            void form.handleSubmit().catch((err) => {
              setStatus(err instanceof Error ? err.message : "Send failed");
            });
          }}
        >
          <FieldGroup>
            <div className="grid gap-3 sm:grid-cols-2">
              <form.Field
                name="to"
                validators={{
                  onChange: ({ value }) =>
                    /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
                      ? undefined
                      : "Use a valid recipient email.",
                }}
              >
                {(field) => (
                  <Field data-invalid={field.state.meta.errors.length > 0}>
                    <FieldLabel htmlFor={field.name}>Recipient</FieldLabel>
                    <Input
                      id={field.name}
                      value={field.state.value}
                      onBlur={field.handleBlur}
                      onChange={(event) => field.handleChange(event.target.value)}
                      placeholder="name@example.com"
                      aria-invalid={field.state.meta.errors.length > 0}
                    />
                    <FieldError errors={field.state.meta.errors} />
                  </Field>
                )}
              </form.Field>
              <form.Field
                name="subject"
                validators={{
                  onChange: ({ value }) =>
                    value.trim() ? undefined : "Subject is required.",
                }}
              >
                {(field) => (
                  <Field data-invalid={field.state.meta.errors.length > 0}>
                    <FieldLabel htmlFor={field.name}>Subject</FieldLabel>
                    <Input
                      id={field.name}
                      value={field.state.value}
                      onBlur={field.handleBlur}
                      onChange={(event) => field.handleChange(event.target.value)}
                      aria-invalid={field.state.meta.errors.length > 0}
                    />
                    <FieldError errors={field.state.meta.errors} />
                  </Field>
                )}
              </form.Field>
            </div>
            <form.Field
              name="body"
              validators={{
                onChange: ({ value }) =>
                  value.trim() ? undefined : "Body is required.",
              }}
            >
              {(field) => (
                <Field data-invalid={field.state.meta.errors.length > 0}>
                  <FieldLabel htmlFor={field.name}>Body</FieldLabel>
                  <Textarea
                    id={field.name}
                    value={field.state.value}
                    onBlur={field.handleBlur}
                    onChange={(event) => field.handleChange(event.target.value)}
                    rows={6}
                    aria-invalid={field.state.meta.errors.length > 0}
                  />
                  <FieldError errors={field.state.meta.errors} />
                </Field>
              )}
            </form.Field>
            <form.Field name="html">
              {(field) => (
                <Field orientation="horizontal">
                  <Checkbox
                    checked={field.state.value}
                    onCheckedChange={(checked) => field.handleChange(checked === true)}
                  />
                  <FieldLabel>Send body as HTML</FieldLabel>
                </Field>
              )}
            </form.Field>
            <form.Subscribe
              selector={(state) => [
                state.canSubmit,
                state.isSubmitting,
                state.values.to,
                state.values.subject,
                state.values.body,
              ]}
            >
              {([canSubmit, isSubmitting, to, subject, body]) => {
                const toValue = String(to);
                const subjectValue = String(subject);
                const bodyValue = String(body);
                return (
                  <Button
                    type="submit"
                    disabled={
                      !canSubmit ||
                      Boolean(isSubmitting) ||
                      !toValue.trim() ||
                      !subjectValue.trim() ||
                      !bodyValue.trim()
                    }
                  >
                    <SendIcon data-icon="inline-start" />
                    {isSubmitting ? "Queueing..." : "Send test"}
                  </Button>
                );
              }}
            </form.Subscribe>
          {status ? (
            <Alert>
              <AlertDescription>{status}</AlertDescription>
            </Alert>
          ) : null}
          </FieldGroup>
        </form>
      </CardContent>
    </Card>
  );
}

function UsersTable({ users }: { users: DashboardUser[] }) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Users</CardTitle>
        <CardDescription>Accounts, keys, and recorded activity</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>User</TableHead>
                <TableHead>Role</TableHead>
                <TableHead>Keys</TableHead>
                <TableHead>Requests</TableHead>
                <TableHead>Emails</TableHead>
                <TableHead>Last seen</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {users.map((user) => (
                <TableRow key={user.id}>
                  <TableCell>
                    <div className="min-w-48">
                      <p className="font-medium">{user.email}</p>
                      <p className="text-sm text-muted-foreground">
                        {user.name ?? "Unnamed"}
                      </p>
                    </div>
                  </TableCell>
                  <TableCell>
                    <StatusBadge tone={user.status === "active" ? "good" : "bad"}>
                      {user.role}
                    </StatusBadge>
                  </TableCell>
                  <TableCell>{formatCount(user.apiKeyCount)}</TableCell>
                  <TableCell>{formatCount(user.requestCount)}</TableCell>
                  <TableCell>{formatCount(user.emailCount)}</TableCell>
                  <TableCell>{formatDate(user.lastSeenAt)}</TableCell>
                </TableRow>
              ))}
              {users.length === 0 ? (
                <TableRow>
                  <TableCell className="text-muted-foreground" colSpan={6}>
                    No users recorded.
                  </TableCell>
                </TableRow>
              ) : null}
            </TableBody>
          </Table>
        </div>
      </CardContent>
    </Card>
  );
}

function UsageTable({ usage }: { usage: UsageEvent[] }) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>API usage</CardTitle>
        <CardDescription>Real request records from protected routes</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Route</TableHead>
                <TableHead>Status</TableHead>
                <TableHead>Duration</TableHead>
                <TableHead>Auth</TableHead>
                <TableHead>Created</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {usage.map((event) => (
                <TableRow key={event.id}>
                  <TableCell>
                    <div className="min-w-56">
                      <p className="font-medium">{event.method}</p>
                      <p className="truncate text-sm text-muted-foreground">{event.path}</p>
                    </div>
                  </TableCell>
                  <TableCell>
                    <StatusBadge tone={event.statusCode >= 400 ? "bad" : "good"}>
                      {event.statusCode}
                    </StatusBadge>
                  </TableCell>
                  <TableCell>{event.durationMs}ms</TableCell>
                  <TableCell>{event.authMethod ?? "unknown"}</TableCell>
                  <TableCell>{formatDate(event.createdAt)}</TableCell>
                </TableRow>
              ))}
              {usage.length === 0 ? (
                <TableRow>
                  <TableCell className="text-muted-foreground" colSpan={5}>
                    No usage events yet.
                  </TableCell>
                </TableRow>
              ) : null}
            </TableBody>
          </Table>
        </div>
      </CardContent>
    </Card>
  );
}

function ActivityTable({
  emailEvents,
  onResend,
  resendingId,
}: {
  emailEvents: EmailEvent[];
  onResend: (event: EmailEvent) => void;
  resendingId?: string;
}) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Email events</CardTitle>
        <CardDescription>Recent queue and delivery records</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Recipient</TableHead>
                <TableHead>Subject</TableHead>
                <TableHead>Status</TableHead>
                <TableHead>Provider</TableHead>
                <TableHead>Created</TableHead>
                <TableHead className="text-right">Control</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {emailEvents.map((event) => (
                <TableRow key={event.id}>
                  <TableCell className="min-w-48">{event.to}</TableCell>
                  <TableCell className="min-w-56">{event.subject}</TableCell>
                  <TableCell>
                    <StatusBadge tone={emailStatusTone(event.status)}>
                      {event.status}
                    </StatusBadge>
                  </TableCell>
                  <TableCell>{event.provider ?? "pending"}</TableCell>
                  <TableCell>{formatDate(event.createdAt)}</TableCell>
                  <TableCell className="text-right">
                    <Button
                      size="sm"
                      variant="outline"
                      disabled={event.status !== "failed" || resendingId === event.id}
                      onClick={() => onResend(event)}
                    >
                      <RepeatIcon data-icon="inline-start" />
                      {resendingId === event.id ? "Retrying..." : "Resend"}
                    </Button>
                  </TableCell>
                </TableRow>
              ))}
              {emailEvents.length === 0 ? (
                <TableRow>
                  <TableCell className="text-muted-foreground" colSpan={6}>
                    No email events yet.
                  </TableCell>
                </TableRow>
              ) : null}
            </TableBody>
          </Table>
        </div>
      </CardContent>
    </Card>
  );
}

function LogsPanel({ logs }: { logs: AppLog[] }) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>System logs</CardTitle>
        <CardDescription>Recent operational signals</CardDescription>
      </CardHeader>
      <CardContent className="flex flex-col gap-3">
        {logs.map((log) => (
          <div
            className="grid gap-2 rounded-lg border p-3 sm:grid-cols-[auto_1fr_auto] sm:items-center"
            key={log.id}
          >
            <StatusBadge
              tone={
                log.level === "error"
                  ? "bad"
                  : log.level === "warn"
                    ? "warn"
                    : "neutral"
              }
            >
              {log.level}
            </StatusBadge>
            <span className="min-w-0 truncate">{log.message}</span>
            <span className="text-sm text-muted-foreground">
              {formatDate(log.createdAt)}
            </span>
          </div>
        ))}
        {logs.length === 0 ? (
          <p className="text-sm text-muted-foreground">No logs recorded.</p>
        ) : null}
      </CardContent>
    </Card>
  );
}

function LoadingDashboard() {
  return (
    <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
      <Skeleton className="h-32" />
      <Skeleton className="h-32" />
      <Skeleton className="h-32" />
      <Skeleton className="h-32" />
    </div>
  );
}

function Dashboard({
  session,
  onLogout,
}: {
  session: AuthSession;
  onLogout: () => void;
}) {
  const client = useMemo(() => api.withToken(session.token), [session.token]);
  const queryClient = useQueryClient();
  const manager = canManage(session);
  const [scope, setScope] = useState<DashboardScope>(manager ? "all" : "mine");
  const [activePage, setActivePage] = useState<DashboardPage>("overview");
  const dashboardQuery = useQuery({
    queryKey: ["dashboard", session.token, scope, manager],
    queryFn: async () => {
      const [dashboard, analytics, providerData, usageData, eventData, logData, userData] =
        await Promise.all([
          client.dashboard(scope),
          client.analytics(scope),
          client.providers(),
          client.usage(scope),
          client.emailEvents(scope),
          client.logs(scope),
          manager ? client.users() : Promise.resolve({ users: [] }),
        ]);
      return {
        summary: dashboard,
        analytics,
        providers: providerData.providers,
        usage: usageData.usage,
        emailEvents: eventData.emailEvents,
        logs: logData.logs,
        users: userData.users,
      };
    },
  });
  const resendMutation = useMutation({
    mutationFn: (event: EmailEvent) => client.resendEmailEvent(event.id),
    onSuccess: async () => {
      await queryClient.invalidateQueries({ queryKey: ["dashboard", session.token] });
    },
  });
  const providersMutation = useMutation({
    mutationFn: (config: ProvidersConfigInput) => client.updateProviders(config),
    onSuccess: async () => {
      await queryClient.invalidateQueries({ queryKey: ["dashboard", session.token] });
    },
  });

  const summary = dashboardQuery.data?.summary ?? null;
  const analytics = dashboardQuery.data?.analytics ?? null;
  const providers = dashboardQuery.data?.providers ?? [];
  const usage = dashboardQuery.data?.usage ?? [];
  const emailEvents = dashboardQuery.data?.emailEvents ?? [];
  const logs = dashboardQuery.data?.logs ?? [];
  const users = dashboardQuery.data?.users ?? [];
  const error =
    dashboardQuery.error instanceof Error
      ? dashboardQuery.error.message
      : resendMutation.error instanceof Error
        ? resendMutation.error.message
        : providersMutation.error instanceof Error
          ? providersMutation.error.message
          : null;

  function updateScope(nextScope: DashboardScope) {
    if (nextScope === "all" && !manager) return;
    setScope(nextScope);
  }

  async function refresh() {
    await queryClient.invalidateQueries({ queryKey: ["dashboard", session.token] });
  }

  function renderPage() {
    if (!summary || !analytics) return null;

    if (activePage === "overview") {
      return (
        <>
          <section className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
            <MetricCard
              label="Requests"
              value={formatCount(summary.totals.requests)}
              hint={`${scope === "all" ? "All users" : "Your account"} all time`}
              icon={ActivityIcon}
            />
            <MetricCard
              label="24h requests"
              value={formatCount(summary.totals.requests24h)}
              hint="Recent protected API traffic"
              icon={Clock3Icon}
            />
            <MetricCard
              label="Emails"
              value={formatCount(summary.totals.emails)}
              hint={`${formatCount(summary.totals.emails24h)} created in 24h`}
              icon={MailIcon}
            />
            <MetricCard
              label="24h failures"
              value={formatCount(summary.totals.errors24h + summary.totals.failedEmails24h)}
              hint="API errors and failed emails"
              icon={AlertTriangleIcon}
            />
          </section>
          <AnalyticsPanel analytics={analytics} />
        </>
      );
    }

    if (activePage === "analytics") return <AnalyticsPanel analytics={analytics} />;
    if (activePage === "users") return manager ? <UsersTable users={users} /> : null;
    if (activePage === "emails") {
      return (
        <ActivityTable
          emailEvents={emailEvents}
          onResend={(event) => resendMutation.mutate(event)}
          resendingId={resendMutation.variables?.id}
        />
      );
    }
    if (activePage === "usage") return <UsageTable usage={usage} />;
    if (activePage === "logs") return <LogsPanel logs={logs} />;

    return (
      <section className="grid gap-4 xl:grid-cols-[minmax(0,1.25fr)_minmax(320px,0.75fr)]">
        <div className="grid gap-4">
          {manager ? (
            <RegisterUserPanel
              client={client}
              disabled={!manager}
              onRegistered={refresh}
            />
          ) : null}
          <SendEmailPanel client={client} onSent={refresh} />
        </div>
        <div className="grid gap-4">
          <ProviderRail
            providers={providers}
            manager={manager}
            pending={providersMutation.isPending}
            onUpdate={(config) => providersMutation.mutate(config)}
          />
          <Card>
            <CardHeader>
              <CardTitle>Access</CardTitle>
              <CardDescription>Current authentication context</CardDescription>
            </CardHeader>
            <CardContent className="grid gap-3 text-sm">
              <div className="flex items-center justify-between gap-3">
                <span className="text-muted-foreground">Manager access</span>
                <StatusBadge tone={manager ? "good" : "neutral"}>
                  {manager ? "enabled" : "limited"}
                </StatusBadge>
              </div>
              <div className="flex items-center justify-between gap-3">
                <span className="text-muted-foreground">Scopes</span>
                <span className="text-right font-medium">
                  {session.scopes.join(", ")}
                </span>
              </div>
              <div className="flex items-center gap-2 text-muted-foreground">
                <ShieldCheckIcon data-icon="inline-start" />
                <span>Tokens remain in session storage only.</span>
              </div>
            </CardContent>
          </Card>
        </div>
      </section>
    );
  }

  return (
    <main className="min-h-[100dvh] bg-muted/40">
      <div className="mx-auto grid w-full max-w-7xl gap-5 p-4 sm:p-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:p-8">
        <aside className="hidden lg:block">
          <div className="sticky top-8 grid gap-4 rounded-xl border bg-card p-3 shadow-sm">
            <div className="flex items-center gap-3 p-2">
              <Avatar className="size-10 rounded-lg">
                <AvatarFallback className="rounded-lg bg-primary text-primary-foreground">
                  RH
                </AvatarFallback>
              </Avatar>
              <div className="min-w-0">
                <p className="truncate text-sm text-muted-foreground">mail.rin.ci</p>
                <p className="truncate font-semibold">Rinci Hub</p>
              </div>
            </div>
            <Separator />
            <nav className="grid gap-1">
              {dashboardPages
                .filter((page) => !page.managerOnly || manager)
                .map((page) => {
                  const Icon = page.icon;
                  return (
                    <Button
                      className="justify-start"
                      key={page.id}
                      onClick={() => setActivePage(page.id)}
                      variant={activePage === page.id ? "secondary" : "ghost"}
                    >
                      <Icon data-icon="inline-start" />
                      {page.label}
                    </Button>
                  );
                })}
            </nav>
          </div>
        </aside>

        <section className="flex min-w-0 flex-col gap-5">
          <header className="rounded-xl border bg-card p-4 shadow-sm">
            <div className="flex flex-col gap-4 xl:flex-row xl:items-center xl:justify-between">
              <div className="flex min-w-0 items-center gap-3">
                <Avatar className="size-11 rounded-lg lg:hidden">
                  <AvatarFallback className="rounded-lg bg-primary text-primary-foreground">
                    RH
                  </AvatarFallback>
                </Avatar>
                <div className="min-w-0">
                  <p className="text-sm text-muted-foreground">Dashboard</p>
                  <h1 className="truncate text-2xl font-semibold tracking-tight">
                    {dashboardPages.find((page) => page.id === activePage)?.label}
                  </h1>
                </div>
              </div>
              <div className="flex flex-col gap-3 lg:flex-row lg:items-center">
                <nav className="flex gap-1 overflow-x-auto lg:hidden">
                  {dashboardPages
                    .filter((page) => !page.managerOnly || manager)
                    .map((page) => {
                      const Icon = page.icon;
                      return (
                        <Button
                          key={page.id}
                          onClick={() => setActivePage(page.id)}
                          size="sm"
                          variant={activePage === page.id ? "secondary" : "ghost"}
                        >
                          <Icon data-icon="inline-start" />
                          {page.label}
                        </Button>
                      );
                    })}
                </nav>
                <Separator className="hidden h-8 xl:block" orientation="vertical" />
                <div className="flex flex-wrap items-center gap-3">
                  <ScopeSwitch scope={scope} disabled={!manager} onChange={updateScope} />
                  <div className="flex min-w-0 items-center gap-3">
                    <Avatar className="size-9">
                      <AvatarFallback>
                        {session.user.email.slice(0, 2).toUpperCase()}
                      </AvatarFallback>
                    </Avatar>
                    <div className="min-w-0">
                      <p className="truncate text-sm font-medium">{session.user.email}</p>
                      <StatusBadge tone={manager ? "good" : "neutral"}>
                        {session.user.role}
                      </StatusBadge>
                    </div>
                  </div>
                  <Button
                    aria-label="Refresh dashboard"
                    disabled={dashboardQuery.isFetching}
                    onClick={() => void refresh()}
                    size="icon"
                    variant="outline"
                  >
                    <RefreshCwIcon />
                  </Button>
                  <Button aria-label="Sign out" onClick={onLogout} size="icon" variant="ghost">
                    <LogOutIcon />
                  </Button>
                </div>
              </div>
            </div>
          </header>

          {error ? (
            <Alert variant="destructive">
              <AlertDescription>{error}</AlertDescription>
            </Alert>
          ) : null}

          {dashboardQuery.isLoading ? <LoadingDashboard /> : null}

          {renderPage()}
        </section>
      </div>
    </main>
  );
}

function App() {
  const [session, setSession] = useState<AuthSession | null>(null);
  const [booting, setBooting] = useState(true);

  useEffect(() => {
    const token = sessionStorage.getItem(sessionKey);
    if (!token) {
      setBooting(false);
      return;
    }
    const client = api.withToken(token);
    client
      .me()
      .then((result) => {
        setSession({
          token,
          user: result.user,
          scopes: result.auth.scopes,
        });
      })
      .catch(() => sessionStorage.removeItem(sessionKey))
      .finally(() => setBooting(false));
  }, []);

  if (booting) {
    return (
      <main className="flex min-h-[100dvh] items-center justify-center bg-muted/40 p-6">
        <Card className="w-full max-w-md">
          <CardHeader>
            <CardTitle>Starting Rinci Hub</CardTitle>
            <CardDescription>Loading your saved session.</CardDescription>
          </CardHeader>
          <CardContent>
            <Skeleton className="h-10" />
          </CardContent>
        </Card>
      </main>
    );
  }

  if (!session) return <LoginPanel onLogin={setSession} />;

  return (
    <Dashboard
      session={session}
      onLogout={() => {
        sessionStorage.removeItem(sessionKey);
        setSession(null);
      }}
    />
  );
}

createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </React.StrictMode>,
);
