"use client";

import { useEffect, useMemo, useState } from "react";
import {
  callAuthEndpoint,
  getAuthEndpointSpecs,
  getEndpointGroupOrder,
  safeStringify,
  type ApiCallResult,
  type EndpointSpec,
  type EndpointMethod,
} from "athena-auth-js";

import { authClient } from "../lib/auth-client";
import { SharedBackButton } from "./shared-back-button";
import { Badge } from "./ui/badge";
import { Button } from "./ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card";
import { Input } from "./ui/input";
import { Label } from "./ui/label";

type EndpointState = "not_run" | "ok" | "error" | "skipped";
type ContextMap = Record<string, string>;

type EndpointRunStatus = {
  state: EndpointState;
  status: number | null;
  message: string;
  updatedAt: string;
};

type HistoryRow = {
  id: string;
  endpointId: string;
  method: EndpointMethod;
  path: string;
  state: EndpointState;
  status: number | null;
  message: string;
  detail: string;
};

const ENDPOINT_SPECS = getAuthEndpointSpecs();
const GROUP_ORDER = getEndpointGroupOrder(ENDPOINT_SPECS);

const DEFAULT_CONTEXT: ContextMap = {
  callbackUrl: "/session",
  provider: "google",
  providerId: "google",
  oauthCode: "",
  oauthState: "",
  resetToken: "",
  token: "",
  email: "demo@example.com",
  username: "",
  password: "demo-pass-123",
  currentPassword: "demo-pass-123",
  newPassword: "demo-pass-456",
  name: "Demo User",
  imageUrl: "https://example.com/avatar.png",
  userId: "",
  role: "member",
  banReason: "manual test",
  sessionToken: "",
  code: "",
  backupCode: "",
  authenticatorAttachment: "platform",
  passkeyResponse: "{}",
  passkeyName: "Primary Passkey",
  passkeyId: "",
  organizationId: "",
  organizationName: "Demo Organization",
  organizationSlug: "demo-organization",
  invitationId: "",
  inviteEmail: "invitee@example.com",
  inviteRole: "member",
  memberId: "",
  memberIdOrEmail: "",
  permissionsJson: '{"organization":["update"]}',
  keyId: "",
  apiKeyName: "demo-api-key",
  apiKeyValue: "",
  apiKeyExpiresIn: "3600",
  apiKeyRemaining: "1000",
  apiKeyPermissions: "{}",
  athenaClientName: "demo-client",
  athenaClientBaseUrl: "http://localhost:3000",
  athenaClientApiKey: "demo-client-key",
  recipientEmail: "to@example.com",
  subject: "Demo Subject",
  fromAddress: "no-reply@example.com",
  emailProvider: "resend",
  emailId: "",
  emailFailureId: "",
  failureReason: "demo failure reason",
  templateKey: "welcome",
  subjectTemplate: "Welcome {{name}}",
  emailTemplateId: "",
  limit: "50",
  offset: "0",
};

const PREFERRED_CONTEXT_ORDER = [
  "email",
  "username",
  "password",
  "name",
  "currentPassword",
  "newPassword",
  "token",
  "callbackUrl",
  "provider",
  "providerId",
  "accountId",
  "userId",
  "sessionToken",
  "organizationId",
  "organizationName",
  "organizationSlug",
  "inviteEmail",
  "inviteRole",
  "invitationId",
  "memberId",
  "memberIdOrEmail",
  "passkeyId",
  "passkeyName",
  "passkeyResponse",
  "authenticatorAttachment",
  "permissionsJson",
] as const;

const TEXTAREA_HINTS = ["json", "response", "permissions", "template"];

function defaultContextValueFor(key: string): string {
  const lower = key.toLowerCase();
  if (TEXTAREA_HINTS.some((hint) => lower.includes(hint))) return "{}";
  if (key === "limit") return "50";
  if (key === "offset") return "0";
  if (key === "callbackUrl") return "/session";
  if (key === "provider" || key === "providerId") return "google";
  if (key === "inviteRole" || key === "role") return "member";
  return "";
}

function extractPlaceholders(template: string | undefined): string[] {
  if (!template) return [];
  const matches = template.match(/\{\{([a-zA-Z0-9_]+)\}\}/g);
  if (!matches) return [];
  return Array.from(
    new Set(matches.map((match) => match.replace(/\{\{|\}\}/g, ""))),
  );
}

function buildInitialContext(specs: EndpointSpec[]): ContextMap {
  const context: ContextMap = { ...DEFAULT_CONTEXT };

  for (const spec of specs) {
    for (const key of spec.requiredContext ?? []) {
      if (!(key in context)) context[key] = defaultContextValueFor(key);
    }

    for (const key of extractPlaceholders(spec.path)) {
      if (!(key in context)) context[key] = defaultContextValueFor(key);
    }

    for (const key of extractPlaceholders(spec.bodyTemplate)) {
      if (!(key in context)) context[key] = defaultContextValueFor(key);
    }
  }

  return context;
}

const INITIAL_CONTEXT = buildInitialContext(ENDPOINT_SPECS);

function applyTemplate(template: string, context: ContextMap): string {
  return template.replace(/\{\{([a-zA-Z0-9_]+)\}\}/g, (_match, key: string) => {
    const value = context[key];
    return typeof value === "string" ? value : "";
  });
}

function firstString(record: unknown, keys: string[]): string | null {
  if (!record || typeof record !== "object") return null;
  const objectRecord = record as Record<string, unknown>;
  for (const key of keys) {
    if (typeof objectRecord[key] === "string" && objectRecord[key]) {
      return objectRecord[key] as string;
    }
  }
  return null;
}

function isNonEmpty(value: string | undefined): boolean {
  return typeof value === "string" && value.trim().length > 0;
}

function formatContextLabel(key: string): string {
  return key
    .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
    .replace(/_/g, " ")
    .replace(/\b\w/g, (char) => char.toUpperCase());
}

function shouldUseTextarea(key: string): boolean {
  const lower = key.toLowerCase();
  return TEXTAREA_HINTS.some((hint) => lower.includes(hint));
}

function stateBadgeVariant(
  state: EndpointState,
): "default" | "secondary" | "success" | "warning" | "destructive" {
  if (state === "ok") return "success";
  if (state === "error") return "destructive";
  if (state === "skipped") return "secondary";
  return "warning";
}

function responseDetail(result: ApiCallResult<unknown>): string {
  return safeStringify({
    status: result.status,
    message: result.message,
    athenaTime: result.athenaTime,
    proxyTime: result.proxyTime,
    body: result.body,
  });
}

function sortContextKeys(keys: string[]): string[] {
  const preferred = new Map<string, number>(
    PREFERRED_CONTEXT_ORDER.map((key, index) => [key, index] as [string, number]),
  );
  return [...keys].sort((a, b) => {
    const aIndex = preferred.get(a);
    const bIndex = preferred.get(b);
    if (aIndex !== undefined && bIndex !== undefined) return aIndex - bIndex;
    if (aIndex !== undefined) return -1;
    if (bIndex !== undefined) return 1;
    return a.localeCompare(b);
  });
}

function normalizeTemplatePath(path: string): string {
  return path.startsWith("/") ? path : `/${path}`;
}

function extractContextPatch(spec: EndpointSpec, body: unknown): ContextMap {
  const patch: ContextMap = {};

  if (spec.id === "list-sessions" && Array.isArray(body) && body[0]) {
    const sessionToken = firstString(body[0], ["token"]);
    const userId = firstString(body[0], ["userId", "user_id"]);
    if (sessionToken) patch.sessionToken = sessionToken;
    if (userId) patch.userId = userId;
  }

  if (spec.id === "list-accounts" && Array.isArray(body) && body[0]) {
    const providerId = firstString(body[0], ["providerId", "provider"]);
    const accountId = firstString(body[0], ["accountId", "account_id"]);
    const userId = firstString(body[0], ["userId", "user_id"]);
    if (providerId) {
      patch.providerId = providerId;
      patch.provider = providerId;
    }
    if (accountId) patch.accountId = accountId;
    if (userId) patch.userId = userId;
  }

  if (spec.id === "organization-list" && Array.isArray(body) && body[0]) {
    const organizationId = firstString(body[0], ["id"]);
    const organizationName = firstString(body[0], ["name"]);
    const organizationSlug = firstString(body[0], ["slug"]);
    if (organizationId) patch.organizationId = organizationId;
    if (organizationName) patch.organizationName = organizationName;
    if (organizationSlug) patch.organizationSlug = organizationSlug;
  }

  if (spec.id === "passkey-list-user-passkeys" && Array.isArray(body) && body[0]) {
    const passkeyId = firstString(body[0], ["id"]);
    const passkeyName = firstString(body[0], ["name"]);
    if (passkeyId) patch.passkeyId = passkeyId;
    if (passkeyName) patch.passkeyName = passkeyName;
  }

  if (
    (spec.id === "organization-create" || spec.id === "organization-update") &&
    body &&
    typeof body === "object"
  ) {
    const organizationId = firstString(body, ["id", "organizationId"]);
    const organizationName = firstString(body, ["name"]);
    const organizationSlug = firstString(body, ["slug"]);
    if (organizationId) patch.organizationId = organizationId;
    if (organizationName) patch.organizationName = organizationName;
    if (organizationSlug) patch.organizationSlug = organizationSlug;
  }

  if (
    (spec.id === "organization-invite-member" ||
      spec.id === "organization-get-invitation") &&
    body &&
    typeof body === "object"
  ) {
    const invitationId = firstString(body, ["id", "invitationId"]);
    const inviteEmail = firstString(body, ["email"]);
    const inviteRole = firstString(body, ["role"]);
    if (invitationId) patch.invitationId = invitationId;
    if (inviteEmail) patch.inviteEmail = inviteEmail;
    if (inviteRole) patch.inviteRole = inviteRole;
  }

  return patch;
}

export function EndpointLab() {
  const [context, setContext] = useState<ContextMap>(() => ({ ...INITIAL_CONTEXT }));
  const [selectedEndpointId, setSelectedEndpointId] = useState<string>(
    ENDPOINT_SPECS[0]?.id ?? "",
  );
  const [method, setMethod] = useState<EndpointMethod>(
    ENDPOINT_SPECS[0]?.method ?? "GET",
  );
  const [path, setPath] = useState<string>(
    ENDPOINT_SPECS[0] ? normalizeTemplatePath(ENDPOINT_SPECS[0].path) : "",
  );
  const [body, setBody] = useState<string>(ENDPOINT_SPECS[0]?.bodyTemplate ?? "");
  const [loading, setLoading] = useState(false);
  const [suiteRunning, setSuiteRunning] = useState(false);
  const [autofillLoading, setAutofillLoading] = useState(false);
  const [includeDestructive, setIncludeDestructive] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [resultDetail, setResultDetail] = useState("");
  const [history, setHistory] = useState<HistoryRow[]>([]);
  const [statusByEndpoint, setStatusByEndpoint] = useState<
    Record<string, EndpointRunStatus>
  >({});

  const { data: sessionData } = authClient.useSession();

  const selectedSpec = useMemo(
    () => ENDPOINT_SPECS.find((entry) => entry.id === selectedEndpointId) ?? null,
    [selectedEndpointId],
  );

  const groupedSpecs = useMemo(
    () =>
      GROUP_ORDER.map((group) => ({
        group,
        specs: ENDPOINT_SPECS.filter((entry) => entry.group === group),
      })),
    [],
  );

  const contextKeys = useMemo(
    () => sortContextKeys(Object.keys(INITIAL_CONTEXT)),
    [],
  );

  const coverageSummary = useMemo(() => {
    const summary = {
      total: ENDPOINT_SPECS.length,
      ok: 0,
      error: 0,
      skipped: 0,
      notRun: 0,
    };

    for (const spec of ENDPOINT_SPECS) {
      const state = statusByEndpoint[spec.id]?.state ?? "not_run";
      if (state === "ok") summary.ok += 1;
      else if (state === "error") summary.error += 1;
      else if (state === "skipped") summary.skipped += 1;
      else summary.notRun += 1;
    }

    return summary;
  }, [statusByEndpoint]);

  const getMissingContext = (spec: EndpointSpec, source: ContextMap): string[] => {
    const required = spec.requiredContext ?? [];
    return required.filter((key) => !isNonEmpty(source[key]));
  };

  const setEndpointStatus = (
    spec: EndpointSpec,
    state: EndpointState,
    status: number | null,
    message: string,
    detail: string,
    resolvedPath: string,
  ) => {
    const updatedAt = new Date().toISOString();

    setStatusByEndpoint((previous) => ({
      ...previous,
      [spec.id]: { state, status, message, updatedAt },
    }));

    setHistory((previous) => [
      {
        id: crypto.randomUUID(),
        endpointId: spec.id,
        method: spec.method,
        path: resolvedPath,
        state,
        status,
        message,
        detail,
      },
      ...previous,
    ].slice(0, 100));
  };

  const loadTemplateFor = (spec: EndpointSpec, source: ContextMap) => {
    setMethod(spec.method);
    setPath(applyTemplate(normalizeTemplatePath(spec.path), source));
    setBody(spec.bodyTemplate ? applyTemplate(spec.bodyTemplate, source) : "");
  };

  const executeEndpoint = async (
    spec: EndpointSpec,
    source: ContextMap,
    options?: { pathOverride?: string; bodyOverride?: string; setSnapshot?: boolean },
  ): Promise<ApiCallResult<unknown> | null> => {
    const missing = getMissingContext(spec, source);
    const resolvedPath = options?.pathOverride ?? applyTemplate(spec.path, source);
    const resolvedBody = options?.bodyOverride ?? applyTemplate(spec.bodyTemplate ?? "", source);

    if (missing.length > 0) {
      const message = `Skipped: missing context (${missing.join(", ")})`;
      setEndpointStatus(spec, "skipped", null, message, message, resolvedPath);
      return null;
    }

    if (spec.destructive && !includeDestructive) {
      const message = "Skipped: destructive endpoint (enable destructive mode to run)";
      setEndpointStatus(spec, "skipped", null, message, message, resolvedPath);
      return null;
    }

    const init: RequestInit = { method: spec.method };
    if (spec.method === "POST") {
      init.body = resolvedBody || "{}";
    }

    const result = await callAuthEndpoint<unknown>(resolvedPath, init);
    const state: EndpointState = result.ok ? "ok" : "error";
    const detail = responseDetail(result);

    setEndpointStatus(spec, state, result.status, result.message, detail, resolvedPath);
    if (options?.setSnapshot !== false) {
      setResultDetail(detail);
    }

    const patch = extractContextPatch(spec, result.body);
    if (Object.keys(patch).length > 0) {
      Object.assign(source, patch);
      setContext((current) => ({ ...current, ...patch }));
    }

    return result;
  };

  const runSelectedEndpoint = async () => {
    if (!selectedSpec) return;
    setError(null);
    setLoading(true);

    try {
      const source = { ...context };
      const runtimeSpec: EndpointSpec = {
        ...selectedSpec,
        method,
      };

      await executeEndpoint(runtimeSpec, source, {
        pathOverride: path,
        bodyOverride: method === "POST" ? body : "",
        setSnapshot: true,
      });
    } catch (runError) {
      setError(runError instanceof Error ? runError.message : "Endpoint execution failed.");
    } finally {
      setLoading(false);
    }
  };

  const runSuite = async (targetGroup?: string) => {
    setError(null);
    setSuiteRunning(true);

    const source = { ...context };
    const specs = targetGroup
      ? ENDPOINT_SPECS.filter((spec) => spec.group === targetGroup)
      : ENDPOINT_SPECS;

    try {
      for (const spec of specs) {
        await executeEndpoint(spec, source, { setSnapshot: false });
      }
    } catch (suiteError) {
      setError(suiteError instanceof Error ? suiteError.message : "Suite failed.");
    } finally {
      setSuiteRunning(false);
    }
  };

  const clearCoverage = () => {
    setStatusByEndpoint({});
    setHistory([]);
    setResultDetail("");
    setError(null);
  };

  const autofillFromLive = async () => {
    setAutofillLoading(true);
    setError(null);

    try {
      const [sessionsResult, accountsResult, organizationsResult, passkeysResult] =
        await Promise.all([
          callAuthEndpoint<unknown[]>("/list-sessions", { method: "GET" }),
          callAuthEndpoint<unknown[]>("/list-accounts", { method: "GET" }),
          callAuthEndpoint<unknown[]>("/organization/list", { method: "GET" }),
          callAuthEndpoint<unknown[]>("/passkey/list-user-passkeys", { method: "GET" }),
        ]);

      setContext((current) => {
        const next = { ...current };
        const sessionPatch = extractContextPatch(
          { id: "list-sessions", group: "Session", path: "/list-sessions", method: "GET" },
          sessionsResult.body,
        );
        const accountPatch = extractContextPatch(
          { id: "list-accounts", group: "Social", path: "/list-accounts", method: "GET" },
          accountsResult.body,
        );
        const organizationPatch = extractContextPatch(
          {
            id: "organization-list",
            group: "Organization",
            path: "/organization/list",
            method: "GET",
          },
          organizationsResult.body,
        );
        const passkeyPatch = extractContextPatch(
          {
            id: "passkey-list-user-passkeys",
            group: "Passkey",
            path: "/passkey/list-user-passkeys",
            method: "GET",
          },
          passkeysResult.body,
        );

        return {
          ...next,
          ...sessionPatch,
          ...accountPatch,
          ...organizationPatch,
          ...passkeyPatch,
        };
      });
    } catch (autofillError) {
      setError(autofillError instanceof Error ? autofillError.message : "Autofill failed.");
    } finally {
      setAutofillLoading(false);
    }
  };

  useEffect(() => {
    if (!selectedSpec) return;
    loadTemplateFor(selectedSpec, context);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedSpec]);

  useEffect(() => {
    if (typeof window === "undefined") return;
    const callbackUrl = `${window.location.origin}/session`;
    setContext((current) =>
      current.callbackUrl === callbackUrl
        ? current
        : { ...current, callbackUrl },
    );
  }, []);

  useEffect(() => {
    const user = sessionData?.user;
    if (!user || typeof user !== "object") return;
    const userRecord = user as unknown as Record<string, unknown>;
    setContext((current) => ({
      ...current,
      userId:
        current.userId ||
        (typeof userRecord.id === "string" ? userRecord.id : ""),
      email:
        current.email ||
        (typeof userRecord.email === "string" ? userRecord.email : ""),
      name:
        current.name ||
        (typeof userRecord.name === "string" ? userRecord.name : ""),
    }));
  }, [sessionData?.user]);

  const updateContextField = (key: string, value: string) => {
    setContext((current) => ({ ...current, [key]: value }));
  };

  return (
    <main className="mx-auto w-full max-w-[1760px] px-4 py-6 md:px-6">
      <Card>
        <CardHeader className="space-y-4">
          <div className="flex flex-wrap items-center justify-between gap-2">
            <SharedBackButton fallbackHref="/login" />
            <Badge variant={loading || suiteRunning ? "warning" : "secondary"}>
              {loading || suiteRunning ? "running coverage..." : "coverage idle"}
            </Badge>
          </div>
          <div>
            <CardTitle className="text-2xl">Endpoint Lab</CardTitle>
            <CardDescription className="mt-1 max-w-5xl">
              Catalog-driven Athena auth endpoint coverage. Every SDK endpoint is
              represented with a runnable template and context-aware UI controls.
            </CardDescription>
          </div>
          <div className="flex flex-wrap items-center gap-2 text-xs">
            <Badge variant="secondary">Total: {coverageSummary.total}</Badge>
            <Badge variant="success">OK: {coverageSummary.ok}</Badge>
            <Badge variant="destructive">Errors: {coverageSummary.error}</Badge>
            <Badge variant="secondary">Skipped: {coverageSummary.skipped}</Badge>
            <Badge variant="warning">Not run: {coverageSummary.notRun}</Badge>
          </div>
        </CardHeader>

        <CardContent className="grid gap-5">
          {error ? (
            <p className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
              {error}
            </p>
          ) : null}

          <section className="grid gap-3 rounded-2xl border border-slate-200 bg-white p-5">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <h3 className="text-sm font-semibold">Coverage controls</h3>
              <div className="flex flex-wrap gap-2">
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  disabled={autofillLoading}
                  onClick={() => void autofillFromLive()}
                >
                  {autofillLoading ? "Autofilling..." : "Autofill from live data"}
                </Button>
                <Button
                  type="button"
                  size="sm"
                  disabled={loading || suiteRunning}
                  onClick={() => void runSuite()}
                >
                  {suiteRunning ? "Running suite..." : "Run full suite"}
                </Button>
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  disabled={loading || suiteRunning}
                  onClick={clearCoverage}
                >
                  Clear coverage
                </Button>
              </div>
            </div>
            <label className="flex items-center gap-2 text-sm">
              <input
                type="checkbox"
                checked={includeDestructive}
                onChange={(event) => setIncludeDestructive(event.target.checked)}
              />
              Include destructive endpoints (delete, revoke, remove, ban, unlink, leave)
            </label>
          </section>

          <section className="grid gap-3 rounded-2xl border border-slate-200 bg-white p-5">
            <h3 className="text-sm font-semibold">Runtime context</h3>
            <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
              {contextKeys.map((key) => {
                const multiline = shouldUseTextarea(key);
                const value = context[key] ?? "";
                return (
                  <div
                    key={key}
                    className={`grid gap-1 ${multiline ? "md:col-span-2 xl:col-span-2" : ""}`}
                  >
                    <Label>{formatContextLabel(key)}</Label>
                    {multiline ? (
                      <textarea
                        className="min-h-[92px] rounded-md border border-slate-200 p-2 font-mono text-xs"
                        value={value}
                        onChange={(event) => updateContextField(key, event.target.value)}
                      />
                    ) : (
                      <Input
                        value={value}
                        onChange={(event) => updateContextField(key, event.target.value)}
                      />
                    )}
                  </div>
                );
              })}
            </div>
          </section>

          <section className="grid gap-4 rounded-2xl border border-slate-200 bg-white p-5">
            <h3 className="text-sm font-semibold">Single endpoint runner</h3>
            <div className="grid gap-3 md:grid-cols-2">
              <div className="grid gap-1">
                <Label>Endpoint template</Label>
                <select
                  className="h-10 rounded-md border border-slate-200 bg-white px-3 text-sm"
                  value={selectedEndpointId}
                  onChange={(event) => setSelectedEndpointId(event.target.value)}
                >
                  {groupedSpecs.map((entry) => (
                    <optgroup key={entry.group} label={entry.group}>
                      {entry.specs.map((spec) => (
                        <option key={spec.id} value={spec.id}>
                          [{spec.method}] {spec.path}
                        </option>
                      ))}
                    </optgroup>
                  ))}
                </select>
              </div>
              <div className="grid gap-1">
                <Label>Method</Label>
                <Input
                  value={method}
                  onChange={(event) =>
                    setMethod(event.target.value.toUpperCase() as EndpointMethod)
                  }
                />
              </div>
            </div>
            <div className="grid gap-1">
              <Label>Path</Label>
              <Input value={path} onChange={(event) => setPath(event.target.value)} />
            </div>
            <div className="grid gap-1">
              <Label>Body (POST only)</Label>
              <textarea
                className="min-h-[160px] rounded-md border border-slate-200 p-2 font-mono text-xs"
                value={body}
                onChange={(event) => setBody(event.target.value)}
              />
            </div>
            {selectedSpec?.note ? (
              <p className="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900">
                {selectedSpec.note}
              </p>
            ) : null}
            <div className="flex flex-wrap gap-2">
              <Button
                type="button"
                disabled={loading || suiteRunning}
                onClick={() => void runSelectedEndpoint()}
              >
                {loading ? "Running..." : "Run endpoint"}
              </Button>
              <Button
                type="button"
                variant="secondary"
                onClick={() => {
                  if (selectedSpec) loadTemplateFor(selectedSpec, context);
                }}
              >
                Reload template values
              </Button>
            </div>
            <div className="grid gap-1">
              <Label>Latest response snapshot</Label>
              <pre className="max-h-[280px] overflow-auto rounded-md border border-slate-200 bg-slate-50 p-2 text-xs">
                {resultDetail || "Run an endpoint to capture a response snapshot."}
              </pre>
            </div>
          </section>

          <section className="grid gap-4 rounded-2xl border border-slate-200 bg-white p-5">
            <h3 className="text-sm font-semibold">Endpoint matrix</h3>
            {groupedSpecs.map((groupEntry) => (
              <div key={groupEntry.group} className="grid gap-2">
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <div className="text-sm font-medium">{groupEntry.group}</div>
                  <Button
                    type="button"
                    size="sm"
                    variant="secondary"
                    disabled={loading || suiteRunning}
                    onClick={() => void runSuite(groupEntry.group)}
                  >
                    Run {groupEntry.group}
                  </Button>
                </div>
                <div className="grid gap-2">
                  {groupEntry.specs.map((spec) => {
                    const status = statusByEndpoint[spec.id];
                    const state = status?.state ?? "not_run";
                    const missing = getMissingContext(spec, context);
                    const resolvedPath = applyTemplate(spec.path, context);
                    return (
                      <div
                        key={spec.id}
                        className="grid gap-2 rounded-lg border border-slate-200 p-3 md:grid-cols-[150px_1fr_210px]"
                      >
                        <div className="flex flex-wrap items-center gap-2">
                          <Badge variant={spec.method === "GET" ? "secondary" : "default"}>
                            {spec.method}
                          </Badge>
                          <Badge variant={stateBadgeVariant(state)}>
                            {state === "not_run" ? "not run" : state}
                          </Badge>
                          {spec.destructive ? <Badge variant="warning">destructive</Badge> : null}
                        </div>
                        <div className="grid gap-1">
                          <div className="font-mono text-xs">{resolvedPath}</div>
                          {spec.note ? (
                            <div className="text-xs text-slate-600">{spec.note}</div>
                          ) : null}
                          {missing.length > 0 ? (
                            <div className="text-xs text-amber-700">
                              Missing context: {missing.join(", ")}
                            </div>
                          ) : null}
                          {status ? (
                            <div className="text-xs text-slate-600">
                              {status.status !== null ? `HTTP ${status.status} · ` : ""}
                              {status.message}
                            </div>
                          ) : null}
                        </div>
                        <div className="flex flex-wrap gap-2 md:justify-end">
                          <Button
                            type="button"
                            size="sm"
                            variant="secondary"
                            onClick={() => {
                              setSelectedEndpointId(spec.id);
                              loadTemplateFor(spec, context);
                            }}
                          >
                            Load
                          </Button>
                          <Button
                            type="button"
                            size="sm"
                            disabled={loading || suiteRunning}
                            onClick={() => void executeEndpoint(spec, { ...context })}
                          >
                            Run
                          </Button>
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            ))}
          </section>

          <section className="grid gap-2 rounded-2xl border border-slate-200 bg-white p-5">
            <h3 className="text-sm font-semibold">Request history</h3>
            <div className="grid gap-2">
              {(history.length
                ? history
                : [
                    {
                      id: "empty",
                      endpointId: "-",
                      method: "GET" as const,
                      path: "-",
                      state: "not_run" as EndpointState,
                      status: null,
                      message: "No requests yet",
                      detail: "",
                    },
                  ]).map((row) => (
                <div
                  key={row.id}
                  className="grid gap-2 rounded-md border border-slate-200 p-2 md:grid-cols-[220px_170px_1fr]"
                >
                  <div className="text-xs">
                    <div className="font-medium">{row.endpointId}</div>
                    <div className="text-slate-500">{row.method}</div>
                    <div className="text-slate-500">
                      {row.status !== null ? `HTTP ${row.status}` : "-"} · {row.state}
                    </div>
                  </div>
                  <div className="font-mono text-xs">{row.path}</div>
                  <div className="font-mono text-xs break-all">
                    {row.detail || row.message}
                  </div>
                </div>
              ))}
            </div>
          </section>
        </CardContent>
      </Card>
    </main>
  );
}
