"use client";

import clsx from "clsx";
import type { ReactNode } from "react";
import { PageHeader, Panel, Skeleton } from "@/components/ui/kit";
import { CopyField, DevTabs, METHOD_TONE } from "@/components/developers/common";
import { useApi } from "@/lib/use-api";

type Endpoint = { method: string; path: string; scope: string; summary: string };

function Section({ title, children }: { title: string; children: ReactNode }) {
  return (
    <Panel className="mb-6 p-5">
      <h2 className="mb-3 text-lg font-semibold">{title}</h2>
      <div className="space-y-3 text-sm leading-relaxed [&_p_code]:break-all">{children}</div>
    </Panel>
  );
}
const Code = ({ children }: { children: string }) => <pre className="overflow-x-auto rounded-lg bg-ink p-3 font-mono text-[12.5px] leading-relaxed text-white">{children}</pre>;

const VERIFY = `// Node.js (no library needed). Use the raw request body, exactly as received.
import crypto from "node:crypto";

function verify(secret, headers, rawBody) {
  const id = headers["webhook-id"];
  const ts = Number(headers["webhook-timestamp"]);
  if (!id || Math.abs(Date.now() / 1000 - ts) > 300) return false; // replay window
  const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
  const expected = "v1," + crypto.createHmac("sha256", key).update(\`\${id}.\${ts}.\${rawBody}\`).digest("base64");
  return headers["webhook-signature"].split(" ").some((sig) =>
    sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)));
}
// Then answer 2xx within 10 seconds, and ignore a webhook-id you have already processed.`;

export default function ApiReferencePage() {
  const { data } = useApi<{ data: Endpoint[]; meta: { base_url: string } }>("/developers/api-keys/reference");
  const scopes = useApi<{ data: { scope: string; description: string }[] }>("/developers/api-keys/scopes");
  const events = useApi<{ data: { type: string; description: string }[] }>("/developers/webhooks/event-types");
  const base = data?.meta.base_url ?? "";
  return (
    <>
      <PageHeader title="Developers" description="Connect your own systems to Devwebs with the REST API and signed webhooks." />
      <DevTabs />
      {!data ? (
        <Skeleton className="h-96" />
      ) : (
        <>
          <Section title="Authentication">
            <p>Every request needs an API key from the API keys tab, sent as a bearer token. Keys belong to this workspace; requests only ever see its data.</p>
            <CopyField value={base} label="Base URL" />
            <Code>{`curl ${base}/contacts?per_page=10 \\\n  -H "Authorization: Bearer dwk_live_…"`}</Code>
            <p>
              JSON in and out. Errors look like <code className="font-mono">{'{"error":{"code":"…","message":"…","fields":{…}}}'}</code>: <b>401</b> invalid key, <b>402</b> your plan doesn&apos;t include API access or the wallet is too low, <b>403</b> the key lacks a permission, <b>404</b> not found, <b>422</b> invalid input, <b>429</b> rate limit.
            </p>
          </Section>
          <Section title="Permissions (scopes)">
            <ul className="divide-y divide-line rounded-lg border border-line">
              {scopes.data?.data.map((s) => (
                <li key={s.scope} className="flex flex-wrap gap-x-3 px-3 py-2">
                  <code className="w-40 font-mono text-[13px]">{s.scope}</code>
                  <span className="text-muted">{s.description}</span>
                </li>
              ))}
            </ul>
          </Section>
          <Section title="Endpoints">
            <ul className="divide-y divide-line rounded-lg border border-line">
              {data.data.map((e) => (
                <li key={`${e.method} ${e.path}`} className="flex flex-wrap items-center gap-x-3 gap-y-1 px-3 py-2">
                  <span className={clsx("w-16 rounded px-1.5 py-0.5 text-center font-mono text-[12px] font-semibold", METHOD_TONE[e.method])}>{e.method}</span>
                  <code className="min-w-0 flex-1 break-all font-mono text-[13px]">{e.path.replace("/api/v1", "")}</code>
                  <span className="text-[13px] text-muted">{e.summary}</span>
                  <code className="rounded bg-paper px-1.5 font-mono text-[12px]">{e.scope}</code>
                </li>
              ))}
            </ul>
            <p>
              Requests and responses use the same fields as the app (for example a contact has <code className="font-mono">first_name</code>, <code className="font-mono">phone</code> with country code, <code className="font-mono">opt_in_status</code>, <code className="font-mono">group_ids</code>, <code className="font-mono">custom_fields</code>). Lists take <code className="font-mono">page</code> and <code className="font-mono">per_page</code>.
            </p>
          </Section>
          <Section title="Sending messages">
            <p>
              Templates can be sent any time; free text only within 24 hours of the customer&apos;s last message (WhatsApp&apos;s rule). The contact and chat are created if needed, the message is charged to your wallet when WhatsApp confirms delivery, and opted-out contacts never get marketing templates.
            </p>
            <Code>{`curl ${base}/messages \\
  -H "Authorization: Bearer dwk_live_…" -H "Content-Type: application/json" \\
  -H "Idempotency-Key: order-1001-shipped" \\
  -d '{"to":"+919812345670","type":"template",
       "template":{"name":"order_update","language":"en_US"},
       "bindings":{"body":{"1":{"source":"text","value":"#1001"}}}}'`}</Code>
            <p>
              Then follow the status with <code className="font-mono">GET /messages/:id</code> or the <code className="font-mono">message.status</code> webhook.
            </p>
          </Section>
          <Section title="Retries, idempotency and limits">
            <p>
              Send an <code className="font-mono">Idempotency-Key</code> header (8–120 characters) on writes. Repeating a request with the same key within 24 hours returns the first response (with <code className="font-mono">Idempotent-Replayed: true</code>) instead of acting twice; the same key with a different body is refused.
            </p>
            <p>
              Each key has its own per-minute limit (set on the key, up to 600). Responses carry <code className="font-mono">RateLimit</code> headers; over the limit you get 429 and should wait for the reset.
            </p>
          </Section>
          <Section title="Webhooks">
            <p>
              Each delivery is a POST with the event as JSON: <code className="font-mono">{'{"id","type","created_at","organization_id","data"}'}</code>. Headers follow the Standard Webhooks specification: <code className="font-mono">webhook-id</code> (same on every retry; use it to ignore duplicates), <code className="font-mono">webhook-timestamp</code> and <code className="font-mono">webhook-signature</code> (<code className="font-mono">v1,&lt;base64 HMAC-SHA256&gt;</code>; two signatures while a secret is being rotated). Retries: 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h. An endpoint answering 410, or failing 50 times in a row, is switched off and you get a notification.
            </p>
            <Code>{VERIFY}</Code>
            <ul className="divide-y divide-line rounded-lg border border-line">
              {events.data?.data.map((e) => (
                <li key={e.type} className="flex flex-wrap gap-x-3 px-3 py-2">
                  <code className="w-52 font-mono text-[13px]">{e.type}</code>
                  <span className="text-muted">{e.description}</span>
                </li>
              ))}
            </ul>
          </Section>
        </>
      )}
    </>
  );
}
