"use client";

import clsx from "clsx";
import { useState, type FormEvent, type ReactNode } from "react";
import { Check, Copy, KeyRound, RefreshCw, Star, Unplug } from "lucide-react";
import { Badge, Button, ConfirmDialog, Field, Input, Panel, Select, Skeleton, Textarea } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { api, ApiError } from "@/lib/api";
import { formatDateTime } from "@/lib/format";
import { useApi } from "@/lib/use-api";
import type { ApiLog, WaMessage, WebhookEvent, WhatsAppAccount, WhatsAppConfig } from "@/lib/types";

const STATUS: Record<WhatsAppAccount["status"], { label: string; tone: "teal" | "brick" | "amber" | "neutral" }> = {
  connected: { label: "Connected", tone: "teal" },
  token_invalid: { label: "Token rejected", tone: "brick" },
  error: { label: "Needs attention", tone: "amber" },
  disconnected: { label: "Disconnected", tone: "neutral" },
};

const QUALITY: Record<string, { label: string; dot: string }> = {
  GREEN: { label: "High quality", dot: "bg-teal" },
  YELLOW: { label: "Medium quality", dot: "bg-amber" },
  RED: { label: "Low quality", dot: "bg-brick" },
};

function CopyField({ label, value, hint }: { label: string; value: string; hint?: ReactNode }) {
  const [copied, setCopied] = useState(false);
  return (
    <Field label={label} hint={hint}>
      <div className="flex gap-2">
        <code className="flex h-10 min-w-0 flex-1 items-center overflow-x-auto whitespace-nowrap rounded-md border border-line bg-paper px-3 text-[13px]">{value}</code>
        <Button
          type="button"
          aria-label={`Copy ${label.toLowerCase()}`}
          icon={copied ? <Check className="size-4 text-teal" /> : <Copy className="size-4" />}
          onClick={async () => {
            await navigator.clipboard.writeText(value);
            setCopied(true);
            setTimeout(() => setCopied(false), 1500);
          }}
        >
          {copied ? "Copied" : "Copy"}
        </Button>
      </div>
    </Field>
  );
}

function WebhookTab({ account }: { account: WhatsAppAccount }) {
  const w = account.webhook;
  return (
    <div className="space-y-5">
      <p className="max-w-2xl text-sm text-muted">
        In your Meta app, open <span className="font-medium text-text">WhatsApp › Configuration</span>, choose <span className="font-medium text-text">Edit</span> under Webhook, paste these two values, then subscribe to the{" "}
        <code className="text-teal">messages</code> field. Meta calls this address to deliver incoming messages and delivery updates.
      </p>
      <CopyField label="Callback URL" value={w.callback_url} hint="Must be public HTTPS in production. Meta does not accept self-signed certificates." />
      {w.verify_token && <CopyField label="Verify token" value={w.verify_token} />}
      <dl className="grid gap-3 text-sm sm:grid-cols-3">
        <div>
          <dt className="text-muted">Meta verified this URL</dt>
          <dd className="mt-0.5 font-medium">{w.verified_at ? formatDateTime(w.verified_at) : <span className="text-amber">Not yet</span>}</dd>
        </div>
        <div>
          <dt className="text-muted">Last notification</dt>
          <dd className="mt-0.5 font-medium">{w.last_event_at ? formatDateTime(w.last_event_at) : "None yet"}</dd>
        </div>
        <div>
          <dt className="text-muted">App subscribed to this account</dt>
          <dd className={clsx("mt-0.5 font-medium", !account.app_subscribed && "text-amber")}>{account.app_subscribed ? "Yes" : "No, reconnect to retry"}</dd>
        </div>
      </dl>
    </div>
  );
}

function TestTab({ account, config, onSent }: { account: WhatsAppAccount; config: WhatsAppConfig | null; onSent: () => void }) {
  const toast = useToast();
  const [kind, setKind] = useState<"template" | "text">("template");
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [sending, setSending] = useState(false);
  const [simErrors, setSimErrors] = useState<Record<string, string>>({});
  const [simulating, setSimulating] = useState(false);

  async function send(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const body = { kind, ...Object.fromEntries(new FormData(e.currentTarget)) };
    setSending(true);
    setErrors({});
    try {
      await api.post(`/whatsapp/accounts/${account.id}/test-message`, body);
      toast("success", "Test message sent to Meta");
      onSent();
    } catch (err) {
      if (err instanceof ApiError && Object.keys(err.fields).length) setErrors(err.fields);
      else toast("error", (err as Error).message);
    } finally {
      setSending(false);
    }
  }

  async function simulate(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = e.currentTarget;
    setSimulating(true);
    setSimErrors({});
    try {
      await api.post(`/whatsapp/accounts/${account.id}/simulate`, { kind: "message", ...Object.fromEntries(new FormData(form)) });
      toast("success", "Simulated message received");
      form.reset();
      onSent();
    } catch (err) {
      if (err instanceof ApiError && Object.keys(err.fields).length) setSimErrors(err.fields);
      else toast("error", (err as Error).message);
    } finally {
      setSimulating(false);
    }
  }

  return (
    <div className="grid gap-8 lg:grid-cols-2">
      <form onSubmit={send} noValidate className="space-y-4">
        <div>
          <h3 className="font-semibold">Send a test message</h3>
          <p className="mt-0.5 text-sm text-muted">Outside a 24-hour conversation, WhatsApp only delivers approved templates. New accounts include the hello_world template.</p>
        </div>
        <Field label="To" htmlFor="t-to" error={errors.to} hint="Country code and number, e.g. 919812345670">
          <Input id="t-to" name="to" inputMode="tel" className="tabular" invalid={!!errors.to} />
        </Field>
        <Field label="Message" htmlFor="t-kind">
          <Select id="t-kind" value={kind} onChange={(e) => setKind(e.target.value as "template" | "text")}>
            <option value="template">Template: hello_world (en_US)</option>
            <option value="text">Free text (only within 24 hours of their last message)</option>
          </Select>
        </Field>
        {kind === "text" && (
          <Field label="Text" htmlFor="t-text" error={errors.text}>
            <Textarea id="t-text" name="text" rows={3} invalid={!!errors.text} />
          </Field>
        )}
        <Button variant="primary" type="submit" loading={sending} disabled={account.status === "disconnected"}>
          Send test message
        </Button>
      </form>

      {config?.mode === "simulation" && (
        <form onSubmit={simulate} noValidate className="space-y-4 rounded-lg border border-dashed border-amber/40 bg-amber-soft/40 p-4">
          <div>
            <h3 className="font-semibold">Simulate an incoming message</h3>
            <p className="mt-0.5 text-sm text-muted">Sends a realistic Meta notification through the same processing as real webhooks. Only available in simulation mode.</p>
          </div>
          <div className="grid gap-4 sm:grid-cols-2">
            <Field label="From" htmlFor="s-from" error={simErrors.from}>
              <Input id="s-from" name="from" inputMode="tel" className="tabular" placeholder="447700900123" invalid={!!simErrors.from} />
            </Field>
            <Field label="Profile name" htmlFor="s-name" optional>
              <Input id="s-name" name="name" placeholder="Piper Reeves" />
            </Field>
          </div>
          <Field label="Message" htmlFor="s-text" error={simErrors.text} hint='Try "STOP" to see automatic opt-out.'>
            <Input id="s-text" name="text" invalid={!!simErrors.text} />
          </Field>
          <Button type="submit" loading={simulating}>
            Receive message
          </Button>
        </form>
      )}
    </div>
  );
}

const MSG_LABEL: Record<string, string> = { accepted: "Sent to Meta", sent: "Sent", delivered: "Delivered", read: "Read", failed: "Failed", received: "Received" };
const MSG_TONE: Record<string, "teal" | "brick" | "neutral" | "amber"> = { read: "teal", delivered: "teal", sent: "neutral", accepted: "neutral", received: "amber", failed: "brick" };

function MessagesTab({ account, config, version, onChanged }: { account: WhatsAppAccount; config: WhatsAppConfig | null; version: number; onChanged: () => void }) {
  const toast = useToast();
  const { data } = useApi<{ data: WaMessage[] }>(`/whatsapp/accounts/${account.id}/messages?v=${version}`);
  async function simulateStatus(id: number, status: string) {
    try {
      await api.post(`/whatsapp/accounts/${account.id}/simulate`, { kind: "status", message_id: id, status });
      onChanged();
    } catch (e) {
      toast("error", (e as Error).message);
    }
  }
  if (!data) return <Skeleton className="h-24 w-full" />;
  if (!data.data.length) return <p className="py-6 text-center text-sm text-muted">No messages yet. Send a test message or wait for someone to message this number.</p>;
  return (
    <div className="relative overflow-x-auto">
      <table className="w-full min-w-[640px] text-sm">
        <thead>
          <tr className="border-b border-line text-left text-[13px] text-muted">
            <th className="py-2 pr-3 font-medium">When</th>
            <th className="py-2 pr-3 font-medium">Contact</th>
            <th className="py-2 pr-3 font-medium">Message</th>
            <th className="py-2 pr-3 font-medium">Status</th>
          </tr>
        </thead>
        <tbody>
          {data.data.map((m) => (
            <tr key={m.id} className="border-b border-line last:border-0 align-top">
              <td className="whitespace-nowrap py-2.5 pr-3 text-muted">{formatDateTime(m.created_at)}</td>
              <td className="py-2.5 pr-3">
                <div className="font-medium">{m.contact_name}</div>
                <div className="tabular text-xs text-muted">+{m.phone}</div>
              </td>
              <td className="max-w-xs py-2.5 pr-3">
                <span className="mr-1.5 text-xs text-muted">{m.direction === "in" ? "In" : "Out"}</span>
                <span className="break-words">{m.body}</span>
                {m.error_message && <div className="mt-0.5 text-xs text-brick">{m.error_message}</div>}
              </td>
              <td className="py-2.5 pr-3">
                <Badge tone={MSG_TONE[m.status] ?? "neutral"}>{MSG_LABEL[m.status] ?? m.status}</Badge>
                {config?.mode === "simulation" && m.direction === "out" && !["read", "failed"].includes(m.status) && (
                  <div className="mt-1.5 flex gap-1">
                    {["delivered", "read", "failed"].map((s) => (
                      <button key={s} onClick={() => simulateStatus(m.id, s)} className="rounded border border-line px-1.5 text-[11px] text-muted hover:border-teal hover:text-teal">
                        {s}
                      </button>
                    ))}
                  </div>
                )}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function ActivityTab({ account, version }: { account: WhatsAppAccount; version: number }) {
  const logs = useApi<{ data: ApiLog[] }>(`/whatsapp/accounts/${account.id}/logs?v=${version}`);
  const events = useApi<{ data: WebhookEvent[] }>(`/whatsapp/accounts/${account.id}/events?v=${version}`);
  return (
    <div className="grid gap-8 xl:grid-cols-2">
      <section>
        <h3 className="mb-1 font-semibold">Calls to Meta</h3>
        <p className="mb-3 text-sm text-muted">The last 50 requests this workspace made for this number. Share the trace ID with Meta support if a call fails.</p>
        {!logs.data ? (
          <Skeleton className="h-24 w-full" />
        ) : (
          <ul className="divide-y divide-line rounded-lg border border-line text-sm">
            {logs.data.data.map((l) => (
              <li key={l.id} className="flex flex-wrap items-start gap-x-3 gap-y-1 px-3 py-2">
                <Badge tone={l.ok ? "teal" : "brick"}>{l.ok ? "OK" : `Error ${l.error_code ?? l.http_status ?? ""}`}</Badge>
                <div className="min-w-0 flex-1">
                  <code className="break-all text-[12.5px]">
                    {l.method} {l.path}
                  </code>
                  {l.error_message && <div className="text-xs text-brick">{l.error_message}</div>}
                  {l.fbtrace_id && <div className="text-xs text-muted">Trace ID {l.fbtrace_id}</div>}
                </div>
                <span className="whitespace-nowrap text-xs text-muted">
                  {formatDateTime(l.created_at)}
                  {l.duration_ms !== null && `, ${l.duration_ms} ms`}
                </span>
              </li>
            ))}
            {logs.data.data.length === 0 && <li className="px-3 py-4 text-center text-muted">No calls yet</li>}
          </ul>
        )}
      </section>
      <section>
        <h3 className="mb-1 font-semibold">Notifications from Meta</h3>
        <p className="mb-3 text-sm text-muted">Repeated deliveries of the same event are counted once.</p>
        {!events.data ? (
          <Skeleton className="h-24 w-full" />
        ) : (
          <ul className="divide-y divide-line rounded-lg border border-line text-sm">
            {events.data.data.map((ev) => (
              <li key={ev.id} className="flex items-start gap-3 px-3 py-2">
                <Badge tone={ev.result === "processed" ? "teal" : ev.result === "failed" ? "brick" : "neutral"}>{ev.result}</Badge>
                <span className="flex-1">{ev.summary}</span>
                <span className="whitespace-nowrap text-xs text-muted">{formatDateTime(ev.received_at)}</span>
              </li>
            ))}
            {events.data.data.length === 0 && <li className="px-3 py-4 text-center text-muted">No notifications received yet</li>}
          </ul>
        )}
      </section>
    </div>
  );
}

const TABS = [
  { id: "webhook", label: "Webhook" },
  { id: "test", label: "Test" },
  { id: "messages", label: "Messages" },
  { id: "activity", label: "Activity" },
] as const;

export function NumberPanel({
  account,
  config,
  canManage,
  showDefaultControls,
  onChanged,
  onRotate,
}: {
  account: WhatsAppAccount;
  config: WhatsAppConfig | null;
  canManage: boolean;
  showDefaultControls: boolean;
  onChanged: () => void;
  onRotate: () => void;
}) {
  const toast = useToast();
  const [tab, setTab] = useState<(typeof TABS)[number]["id"]>(account.webhook.verified_at ? "messages" : "webhook");
  const [busy, setBusy] = useState<string | null>(null);
  const [confirmDisconnect, setConfirmDisconnect] = useState(false);
  const [version, setVersion] = useState(0);
  const refresh = () => {
    setVersion((v) => v + 1);
    onChanged();
  };
  const st = STATUS[account.status];
  const q = account.quality_rating ? QUALITY[account.quality_rating] : null;

  async function run(name: string, fn: () => Promise<unknown>, message: string) {
    setBusy(name);
    try {
      await fn();
      toast("success", message);
      refresh();
    } catch (e) {
      toast("error", (e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  const tabs = canManage ? TABS : TABS.filter((t) => t.id === "messages");
  const activeTab = tabs.some((t) => t.id === tab) ? tab : tabs[0].id;

  return (
    <Panel>
      <div className="flex flex-wrap items-start gap-4 p-5">
        <div className="min-w-0 flex-1">
          <div className="flex flex-wrap items-center gap-2">
            <h2 className="tabular text-xl font-semibold text-ink">{account.display_phone_number ?? account.phone_number_id}</h2>
            <Badge tone={st.tone}>{st.label}</Badge>
            {account.is_default && showDefaultControls && <Badge tone="teal">Default</Badge>}
          </div>
          <dl className="mt-2 flex flex-wrap gap-x-6 gap-y-1 text-sm">
            <div className="flex gap-1.5">
              <dt className="text-muted">Display name</dt>
              <dd>{account.verified_name ?? "—"}</dd>
            </div>
            {q && (
              <div className="flex items-center gap-1.5">
                <dt className="sr-only">Quality</dt>
                <span className={clsx("size-2 rounded-full", q.dot)} />
                <dd>{q.label}</dd>
              </div>
            )}
            <div className="flex gap-1.5">
              <dt className="text-muted">Token</dt>
              <dd className="tabular">{account.access_token_hint ?? "—"}</dd>
            </div>
            <div className="flex gap-1.5">
              <dt className="text-muted">Last checked</dt>
              <dd>{formatDateTime(account.last_health_check_at)}</dd>
            </div>
          </dl>
          {account.last_error && <p className="mt-3 rounded-md bg-brick-soft px-3 py-2 text-sm text-brick">{account.last_error}</p>}
        </div>
        {canManage && (
          <div className="flex flex-wrap gap-2">
            <Button size="sm" icon={<RefreshCw className="size-3.5" />} loading={busy === "check"} onClick={() => run("check", () => api.post(`/whatsapp/accounts/${account.id}/health-check`), "Connection checked")}>
              Check connection
            </Button>
            <Button size="sm" icon={<KeyRound className="size-3.5" />} onClick={onRotate}>
              Update credentials
            </Button>
            {showDefaultControls && !account.is_default && (
              <Button size="sm" icon={<Star className="size-3.5" />} loading={busy === "default"} onClick={() => run("default", () => api.post(`/whatsapp/accounts/${account.id}/default`), "Default number changed")}>
                Make default
              </Button>
            )}
            <Button size="sm" variant="ghost" className="hover:bg-brick-soft hover:text-brick" icon={<Unplug className="size-3.5" />} onClick={() => setConfirmDisconnect(true)}>
              Disconnect
            </Button>
          </div>
        )}
      </div>

      <div role="tablist" aria-label="Number details" className="flex gap-1 overflow-x-auto border-y border-line px-3">
        {tabs.map((t) => (
          <button
            key={t.id}
            role="tab"
            aria-selected={activeTab === t.id}
            onClick={() => setTab(t.id)}
            className={clsx("-mb-px whitespace-nowrap border-b-2 px-3 py-2.5 text-sm font-medium", activeTab === t.id ? "border-teal text-teal" : "border-transparent text-muted hover:text-text")}
          >
            {t.label}
          </button>
        ))}
      </div>
      <div className="p-5" role="tabpanel">
        {activeTab === "webhook" && <WebhookTab account={account} />}
        {activeTab === "test" && <TestTab account={account} config={config} onSent={refresh} />}
        {activeTab === "messages" && <MessagesTab account={account} config={config} version={version} onChanged={refresh} />}
        {activeTab === "activity" && <ActivityTab account={account} version={version} />}
      </div>

      <ConfirmDialog
        open={confirmDisconnect}
        title={`Disconnect ${account.display_phone_number ?? "this number"}?`}
        message="We stop receiving messages for it and delete the stored token and app secret. Contacts and message history stay. You can reconnect later with new credentials."
        confirmLabel="Disconnect number"
        loading={busy === "disconnect"}
        onConfirm={() =>
          run("disconnect", () => api.delete(`/whatsapp/accounts/${account.id}`), "Number disconnected").then(() => setConfirmDisconnect(false))
        }
        onClose={() => setConfirmDisconnect(false)}
      />
    </Panel>
  );
}
