"use client";

import React, { Suspense, useCallback, useEffect, useRef, useState } from "react";
import { useAuth } from "@/hooks/useAuth";
import { useRouter, useSearchParams } from "next/navigation";
import { apiFetch, API_BASE, resolveToApiOrigin } from "@/lib/api";
import { useSiteSettings } from "@/contexts/SiteSettingsContext";
import { useDismissingState } from "@/hooks/useDismissingState";
import { Building2, Palette, Bell, Mail, Scale, MessageCircle, type LucideIcon } from "lucide-react";

type TabId = "organisation" | "branding" | "notifications" | "email" | "legal" | "whatsapp";

const TABS: { id: TabId; label: string; icon: LucideIcon }[] = [
  { id: "organisation",  label: "Organisation",  icon: Building2 },
  { id: "branding",      label: "Branding",      icon: Palette },
  { id: "notifications", label: "Notifications", icon: Bell },
  { id: "email",         label: "Email",         icon: Mail },
  { id: "legal",         label: "Legal",         icon: Scale },
  { id: "whatsapp",      label: "WhatsApp",      icon: MessageCircle },
];

const inputCls =
  "w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-400";

function Field({
  label, hint, required, children,
}: {
  label: string; hint?: string; required?: boolean; children: React.ReactNode;
}) {
  return (
    <div>
      <label className="block text-sm font-medium text-gray-700 mb-1">
        {label} {required && <span className="text-red-500">*</span>}
      </label>
      {children}
      {hint && <p className="text-xs text-gray-400 mt-1">{hint}</p>}
    </div>
  );
}

function SaveBar({
  saving, onSave, result,
}: {
  saving: boolean;
  onSave: () => void;
  result: { ok: boolean; message: string } | null;
}) {
  return (
    <div className="flex items-center justify-between pt-4 border-t mt-6 flex-wrap gap-3">
      {result ? (
        <span className={`text-sm flex items-center gap-1.5 ${result.ok ? "text-green-600" : "text-red-600"}`}>
          {result.ok ? "✓" : "✗"} {result.message}
        </span>
      ) : (
        <span />
      )}
      <button
        type="button"
        disabled={saving}
        onClick={onSave}
        className="px-6 py-2 bg-brand-600 hover:bg-brand-700 disabled:opacity-50 text-white rounded-lg text-sm font-medium"
      >
        {saving ? "Saving…" : "Save"}
      </button>
    </div>
  );
}

export default function SiteSettingsPage() {
  return (
    <Suspense fallback={<div className="p-6 text-sm text-gray-500">Loading settings…</div>}>
      <SiteSettingsPageInner />
    </Suspense>
  );
}

function SiteSettingsPageInner() {
  const { token } = useAuth();
  const router = useRouter();
  const searchParams = useSearchParams();
  const { reload: reloadSettings } = useSiteSettings();

  const initialTab = TABS.some(t => t.id === searchParams.get("tab")) ? (searchParams.get("tab") as TabId) : "organisation";
  const [activeTab, setActiveTab] = useState<TabId>(initialTab);
  const [loadingInitial, setLoadingInitial] = useState(true);

  // Per-tab save state
  const [saving, setSaving] = useState(false);
  const [result, setResult] = useDismissingState<{ ok: boolean; message: string } | null>(null);

  // ── Organisation ──
  const [orgName, setOrgName] = useState("");
  const [orgTagline, setOrgTagline] = useState("");
  const [orgEmail, setOrgEmail] = useState("");
  const [orgPhone, setOrgPhone] = useState("");
  const [orgAddress, setOrgAddress] = useState("");
  const [appBaseUrl, setAppBaseUrl] = useState("");

  // ── Branding ──
  const [accentColor, setAccentColor] = useState("#2563eb");
  const [logoUrl, setLogoUrl] = useState("");
  const [logoFile, setLogoFile] = useState<File | null>(null);
  const [logoPreview, setLogoPreview] = useState<string | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  // ── Notifications ──
  const [notifEmails, setNotifEmails] = useState("");

  // ── SMTP ──
  const [smtpHost, setSmtpHost] = useState("");
  const [smtpPort, setSmtpPort] = useState("587");
  const [smtpSecure, setSmtpSecure] = useState(false);
  const [smtpFrom, setSmtpFrom] = useState("");
  const [smtpUser, setSmtpUser] = useState("");
  const [smtpPass, setSmtpPass] = useState("");
  const [smtpPassSet, setSmtpPassSet] = useState(false);
  const [smtpTesting, setSmtpTesting] = useState(false);
  const [smtpTestResult, setSmtpTestResult] = useDismissingState<{ ok: boolean; message: string; raw?: string } | null>(null);

  // ── Legal ──
  const [legalOperatorName, setLegalOperatorName] = useState("");
  const [legalIoName, setLegalIoName] = useState("");
  const [legalIoEmail, setLegalIoEmail] = useState("");
  const [legalWebsiteUrl, setLegalWebsiteUrl] = useState("");
  const [legalEffectiveDate, setLegalEffectiveDate] = useState("");

  // ── Load all settings once ────────────────────────────────────────────────
  useEffect(() => {
    if (!token) return;
    apiFetch<Record<string, string>>("/api/settings/all", { authToken: token })
      .then((s) => {
        setOrgName(s.org_name || "");
        setOrgTagline(s.org_tagline || "");
        setOrgEmail(s.org_email || "");
        setOrgPhone(s.org_phone || "");
        setOrgAddress(s.org_address || "");
        setAppBaseUrl(s.app_base_url || "");
        setAccentColor(s.accent_color || "#2563eb");
        setLogoUrl(s.logo_url || "");
        setNotifEmails(s.reg_notification_emails || "");
        setSmtpHost(s.smtp_host || "");
        setSmtpPort(s.smtp_port || "587");
        setSmtpSecure((s.smtp_secure || "").toLowerCase() === "true");
        setSmtpFrom(s.smtp_from || "");
        setSmtpUser(s.smtp_user || "");
        setSmtpPassSet(!!s.smtp_pass && s.smtp_pass !== "");
        setSmtpPass("");
        setLegalOperatorName(s.legal_operator_name || "");
        setLegalIoName(s.legal_io_name || "");
        setLegalIoEmail(s.legal_io_email || "");
        setLegalWebsiteUrl(s.legal_website_url || "");
        setLegalEffectiveDate(s.legal_effective_date || "");
      })
      .catch((e: any) => setResult({ ok: false, message: e?.message || "Failed to load settings" }))
      .finally(() => setLoadingInitial(false));
  }, [token]);

  // Clear result when switching tabs
  const switchTab = (id: TabId) => { setActiveTab(id); setResult(null); };

  // ── Save helpers ──────────────────────────────────────────────────────────
  const save = async (updates: Record<string, string>) => {
    if (!token) return;
    setSaving(true);
    setResult(null);
    try {
      await apiFetch("/api/settings", { method: "PUT", authToken: token, body: updates });
      setResult({ ok: true, message: "Saved." });
      reloadSettings();
    } catch (e: any) {
      setResult({ ok: false, message: e?.message || "Failed to save" });
    } finally {
      setSaving(false);
    }
  };

  const saveOrganisation = () => save({
    org_name:     orgName.trim(),
    org_tagline:  orgTagline.trim(),
    org_email:    orgEmail.trim(),
    org_phone:    orgPhone.trim(),
    org_address:  orgAddress.trim(),
    app_base_url: appBaseUrl.trim(),
  });

  const saveBranding = async () => {
    if (!token) return;
    setSaving(true);
    setResult(null);
    try {
      let finalLogoUrl = logoUrl;
      if (logoFile) {
        const fd = new FormData();
        fd.append("image", logoFile);
        const res = await fetch(`${API_BASE}/api/uploads/logo`, {
          method: "POST",
          headers: { Authorization: `Bearer ${token}` },
          body: fd,
        });
        if (!res.ok) throw new Error("Logo upload failed");
        const data = await res.json();
        finalLogoUrl = data.url || logoUrl;
      }
      await apiFetch("/api/settings", {
        method: "PUT", authToken: token,
        body: { accent_color: accentColor, logo_url: finalLogoUrl },
      });
      setLogoUrl(finalLogoUrl);
      setLogoFile(null);
      setLogoPreview(null);
      setResult({ ok: true, message: "Saved." });
      reloadSettings();
    } catch (e: any) {
      setResult({ ok: false, message: e?.message || "Failed to save" });
    } finally {
      setSaving(false);
    }
  };

  const saveNotifications = () => save({ reg_notification_emails: notifEmails.trim() });

  const saveSmtp = async () => {
    if (!token) return;
    setSaving(true);
    setResult(null);
    try {
      const updates: Record<string, string> = {
        smtp_host:   smtpHost.trim(),
        smtp_port:   smtpPort.trim(),
        smtp_secure: smtpSecure ? "true" : "false",
        smtp_from:   smtpFrom.trim(),
        smtp_user:   smtpUser.trim(),
      };
      if (smtpPass.trim() !== "") updates.smtp_pass = smtpPass.trim();
      await apiFetch("/api/settings", { method: "PUT", authToken: token, body: updates });
      if (smtpPass.trim() !== "") { setSmtpPassSet(true); setSmtpPass(""); }
      setResult({ ok: true, message: "Saved." });
      reloadSettings();
    } catch (e: any) {
      setResult({ ok: false, message: e?.message || "Failed to save" });
    } finally {
      setSaving(false);
    }
  };

  const saveLegal = () => save({
    legal_operator_name:  legalOperatorName.trim(),
    legal_io_name:        legalIoName.trim(),
    legal_io_email:       legalIoEmail.trim(),
    legal_website_url:    legalWebsiteUrl.trim(),
    legal_effective_date: legalEffectiveDate.trim(),
  });

  const handleTestSmtp = async () => {
    if (!token) return;
    setSmtpTesting(true);
    setSmtpTestResult(null);
    try {
      await apiFetch("/api/settings/test-smtp", {
        method: "POST",
        authToken: token,
        body: {
          host:   smtpHost.trim(),
          port:   smtpPort.trim(),
          secure: smtpSecure,
          from:   smtpFrom.trim(),
          user:   smtpUser.trim(),
          pass:   smtpPass.trim() !== "" ? smtpPass.trim() : "••••••••",
        },
      });
      setSmtpTestResult({ ok: true, message: "Connection successful — check your inbox for a test email." });
    } catch (e: any) {
      setSmtpTestResult({ ok: false, message: e?.message || "SMTP test failed", raw: e?.data?.raw });
    } finally {
      setSmtpTesting(false);
    }
  };

  if (loadingInitial) return <div className="p-6 text-sm text-gray-500">Loading settings…</div>;

  const currentLogoSrc = logoPreview || (logoUrl ? resolveToApiOrigin(logoUrl) : null);

  return (
    <div className="max-w-3xl mx-auto w-full">
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div>
          <h1 className="text-2xl font-semibold text-gray-900">Site Settings</h1>
          <p className="text-sm text-gray-500 mt-1">Configure your organisation, branding, email, and legal pages.</p>
        </div>
        <button
          className="px-3 py-1.5 text-sm rounded-lg bg-gray-100 hover:bg-gray-200"
          onClick={() => router.push("/dashboard/admin")}
        >
          Back
        </button>
      </div>

      {/* Tab bar */}
      <div className="flex items-center gap-2 flex-wrap mb-4">
        {TABS.map((tab) => {
          const Icon = tab.icon;
          return (
            <button
              key={tab.id}
              type="button"
              onClick={() => switchTab(tab.id)}
              className={`flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg border transition-colors ${
                activeTab === tab.id
                  ? "bg-brand-600 text-white border-brand-600"
                  : "bg-white text-gray-700 border-gray-200 hover:bg-gray-50"
              }`}
            >
              <Icon className="w-4 h-4" />
              {tab.label}
            </button>
          );
        })}
      </div>

      <div className="border rounded-xl p-5 bg-white shadow-sm">
        {/* ── Organisation ─────────────────────────────────────────────────── */}
        {activeTab === "organisation" && (
          <div className="space-y-4">
            <h2 className="text-lg font-semibold text-gray-900">Organisation details</h2>
            <Field label="Organisation name" required>
              <input className={inputCls} placeholder="Hope Family Church"
                value={orgName} onChange={e => setOrgName(e.target.value)} />
            </Field>
            <Field label="Tagline">
              <input className={inputCls} placeholder="Connecting community through events"
                value={orgTagline} onChange={e => setOrgTagline(e.target.value)} />
            </Field>
            <div className="grid sm:grid-cols-2 gap-4">
              <Field label="Contact email">
                <input type="email" className={inputCls} placeholder="admin@yourchurch.org"
                  value={orgEmail} onChange={e => setOrgEmail(e.target.value)} />
              </Field>
              <Field label="Phone">
                <input className={inputCls} placeholder="+27 12 345 6789"
                  value={orgPhone} onChange={e => setOrgPhone(e.target.value)} />
              </Field>
            </div>
            <Field label="Address">
              <input className={inputCls} placeholder="123 Church St, City"
                value={orgAddress} onChange={e => setOrgAddress(e.target.value)} />
            </Field>
            <Field label="Site URL" hint="The public URL of this site — used in email links (e.g. password reset, ticket delivery). e.g. https://events.yourchurch.org">
              <input className={inputCls} placeholder="https://events.yourchurch.org"
                value={appBaseUrl} onChange={e => setAppBaseUrl(e.target.value)} />
            </Field>
            <SaveBar saving={saving} onSave={saveOrganisation} result={result} />
          </div>
        )}

        {/* ── Branding ─────────────────────────────────────────────────────── */}
        {activeTab === "branding" && (
          <div className="space-y-5">
            <h2 className="text-lg font-semibold text-gray-900">Branding</h2>
            <Field label="Accent / brand colour" hint="Only recolors the organisation name next to the logo in the top navigation bar — every other button, link, and highlight across the site uses a fixed color scheme.">
              <div className="flex items-center gap-3">
                <input type="color" className="h-10 w-20 border rounded cursor-pointer"
                  value={accentColor} onChange={e => setAccentColor(e.target.value)} />
                <input className={`${inputCls} font-mono`} placeholder="#2563eb"
                  value={accentColor} onChange={e => setAccentColor(e.target.value)} />
              </div>
              <div className="mt-2 h-6 rounded-lg transition-colors" style={{ background: accentColor }} />
            </Field>

            <Field label="Site logo" hint="PNG, JPG, SVG or WebP, max 2 MB. Displayed in the navigation bar.">
              {currentLogoSrc && (
                <div className="mb-3 flex items-center gap-3">
                  {/* eslint-disable-next-line @next/next/no-img-element */}
                  <img src={currentLogoSrc} alt="Current logo" className="h-16 object-contain border rounded p-1 bg-gray-50" />
                  <button
                    type="button"
                    className="text-xs text-red-500 hover:text-red-700"
                    onClick={() => { setLogoUrl(""); setLogoFile(null); setLogoPreview(null); if (fileRef.current) fileRef.current.value = ""; }}
                  >
                    Remove
                  </button>
                </div>
              )}
              <input ref={fileRef} type="file" accept="image/*" onChange={e => {
                const file = e.target.files?.[0];
                if (!file) return;
                setLogoFile(file);
                setLogoPreview(URL.createObjectURL(file));
              }} className="text-sm" />
            </Field>

            <SaveBar saving={saving} onSave={saveBranding} result={result} />
          </div>
        )}

        {/* ── Notifications ─────────────────────────────────────────────────── */}
        {activeTab === "notifications" && (
          <div className="space-y-4">
            <h2 className="text-lg font-semibold text-gray-900">Notifications</h2>
            <Field
              label="Registration notification emails"
              hint="Who gets notified when someone registers for an event. Separate multiple addresses with commas."
            >
              <input className={inputCls} placeholder="registrations@yourchurch.org, admin@yourchurch.org"
                value={notifEmails} onChange={e => setNotifEmails(e.target.value)} />
            </Field>
            <SaveBar saving={saving} onSave={saveNotifications} result={result} />
          </div>
        )}

        {/* ── Email / SMTP ──────────────────────────────────────────────────── */}
        {activeTab === "email" && (
          <div className="space-y-4">
            <h2 className="text-lg font-semibold text-gray-900">Email</h2>
            <p className="text-sm text-gray-500">
              Outgoing email for tickets, payment confirmations, and account notifications.
              Leave blank to use server environment variables. The password is stored encrypted.
            </p>

            <div className="grid sm:grid-cols-2 gap-4">
              <Field label="SMTP host">
                <input className={inputCls} placeholder="smtp.yourprovider.com"
                  value={smtpHost} onChange={e => setSmtpHost(e.target.value)} />
              </Field>
              <Field label="Port">
                <input type="number" className={inputCls} placeholder="587"
                  value={smtpPort} onChange={e => setSmtpPort(e.target.value)} />
              </Field>
            </div>

            <div className="flex items-center gap-2">
              <input type="checkbox" id="smtpSecure" checked={smtpSecure}
                onChange={e => setSmtpSecure(e.target.checked)} className="rounded" />
              <label htmlFor="smtpSecure" className="text-sm text-gray-700">Use TLS/SSL (port 465)</label>
            </div>

            <Field label="From address" hint="The address emails appear to come from.">
              <input type="email" className={inputCls} placeholder="no-reply@yourchurch.org"
                value={smtpFrom} onChange={e => setSmtpFrom(e.target.value)} />
            </Field>

            <div className="grid sm:grid-cols-2 gap-4">
              <Field label="SMTP username">
                <input type="email" className={inputCls} placeholder="mail@yourchurch.org"
                  value={smtpUser} onChange={e => setSmtpUser(e.target.value)} autoComplete="username" />
              </Field>
              <Field
                label="SMTP password"
                hint={smtpPassSet ? "Password is saved. Leave blank to keep it." : undefined}
              >
                <div className="relative">
                  <input type="password" className={inputCls}
                    placeholder={smtpPassSet ? "Leave blank to keep current" : "Enter password"}
                    value={smtpPass} onChange={e => setSmtpPass(e.target.value)} autoComplete="new-password" />
                  {smtpPassSet && smtpPass === "" && (
                    <span className="absolute right-3 top-1/2 -translate-y-1/2 text-xs text-green-600 pointer-events-none">● saved</span>
                  )}
                </div>
              </Field>
            </div>

            {/* Test connection */}
            <div className="pt-1 space-y-2">
              <div className="flex items-center gap-3 flex-wrap">
                <button
                  type="button"
                  disabled={smtpTesting || !smtpHost.trim()}
                  onClick={handleTestSmtp}
                  className="px-4 py-2 text-sm rounded-lg bg-gray-100 hover:bg-gray-200 disabled:opacity-50 border"
                >
                  {smtpTesting ? "Testing…" : "Test connection"}
                </button>
                {smtpTestResult && (
                  <span className={`text-sm ${smtpTestResult.ok ? "text-green-600" : "text-red-600"}`}>
                    {smtpTestResult.ok ? "✓" : "✗"} {smtpTestResult.message}
                  </span>
                )}
              </div>
              {smtpTestResult && !smtpTestResult.ok && smtpTestResult.raw && (
                <details className="text-xs text-gray-500">
                  <summary className="cursor-pointer select-none hover:text-gray-700">Show technical details</summary>
                  <pre className="mt-1 p-2 bg-gray-100 rounded text-xs overflow-x-auto whitespace-pre-wrap break-all">{smtpTestResult.raw}</pre>
                </details>
              )}
            </div>

            <SaveBar saving={saving} onSave={saveSmtp} result={result} />
          </div>
        )}

        {/* ── Legal ─────────────────────────────────────────────────────────── */}
        {activeTab === "legal" && (
          <div className="space-y-4">
            <h2 className="text-lg font-semibold text-gray-900">Legal</h2>
            <p className="text-sm text-gray-500">
              These values populate the Terms of Use and Privacy Policy pages automatically.
            </p>

            <Field label="Operator / responsible party"
              hint='Shown in the "Owned and operated by" line of the Terms of Use.'>
              <input className={inputCls} placeholder="Jane Smith on behalf of Example Church, City, South Africa"
                value={legalOperatorName} onChange={e => setLegalOperatorName(e.target.value)} />
            </Field>
            <Field label="Website URL (without https://)">
              <input className={inputCls} placeholder="events.yourchurch.org"
                value={legalWebsiteUrl} onChange={e => setLegalWebsiteUrl(e.target.value)} />
            </Field>
            <Field label="Effective date">
              <input className={inputCls} placeholder="April 2026"
                value={legalEffectiveDate} onChange={e => setLegalEffectiveDate(e.target.value)} />
            </Field>

            <div className="border-t pt-4">
              <p className="text-sm font-medium text-gray-700 mb-3">Information Officer (POPIA)</p>
              <div className="grid sm:grid-cols-2 gap-4">
                <Field label="Full name">
                  <input className={inputCls} placeholder="Jane Smith"
                    value={legalIoName} onChange={e => setLegalIoName(e.target.value)} />
                </Field>
                <Field label="Email">
                  <input type="email" className={inputCls} placeholder="io@yourchurch.org"
                    value={legalIoEmail} onChange={e => setLegalIoEmail(e.target.value)} />
                </Field>
              </div>
            </div>

            <SaveBar saving={saving} onSave={saveLegal} result={result} />
          </div>
        )}

        {/* ── WhatsApp ──────────────────────────────────────────────────────── */}
        {activeTab === "whatsapp" && <WhatsAppTab active={activeTab === "whatsapp"} />}
      </div>
    </div>
  );
}

// ─── WhatsApp tab (migrated from the old standalone /dashboard/admin/whatsapp page) ───

type WAStatus =
  | "WORKING"
  | "CONNECTED"
  | "SCAN_QR_CODE"
  | "STARTING"
  | "FAILED"
  | "STOPPED"
  | string;

interface ConfigResponse {
  tokenMasked: string;
  instanceId:  string;
  hasToken:    boolean;
  hasInstance: boolean;
  configured:  boolean;
}

interface StatusResponse {
  status:   WAStatus;
  message?: string;
}

const STATUS_COLORS: Record<string, string> = {
  WORKING:      "bg-green-100 text-green-800 border-green-300",
  CONNECTED:    "bg-green-100 text-green-800 border-green-300",
  SCAN_QR_CODE: "bg-yellow-100 text-yellow-800 border-yellow-300",
  STARTING:     "bg-blue-100 text-blue-800 border-blue-300",
  FAILED:       "bg-red-100 text-red-800 border-red-300",
  STOPPED:      "bg-gray-100 text-gray-700 border-gray-300",
};

const STATUS_ICONS: Record<string, string> = {
  WORKING:      "🟢",
  CONNECTED:    "🟢",
  SCAN_QR_CODE: "📷",
  STARTING:     "🔄",
  FAILED:       "🔴",
  STOPPED:      "⚫",
};

const ACTIVE_STATUSES = new Set(["WORKING", "CONNECTED"]);
const POLLING_STATUSES = new Set(["STARTING", "SCAN_QR_CODE", "FAILED", "STOPPED"]);

function Spinner() {
  return (
    <svg className="animate-spin h-4 w-4 text-brand-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
    </svg>
  );
}

function WAAlert({ type, children }: { type: "ok" | "err" | "info"; children: React.ReactNode }) {
  const cls =
    type === "ok" ? "bg-green-50 text-green-800 border-green-200"
    : type === "err" ? "bg-red-50 text-red-800 border-red-200"
    : "bg-blue-50 text-blue-800 border-blue-200";
  return <div className={`p-3 rounded-lg text-sm border ${cls}`}>{children}</div>;
}

function StepIndicator({ step }: { step: number }) {
  const steps = [
    { n: 1, label: "Access Token" },
    { n: 2, label: "Session Instance" },
    { n: 3, label: "Connected" },
  ];
  return (
    <div className="flex items-center gap-0">
      {steps.map((s, i) => {
        const done    = step > s.n;
        const current = step === s.n;
        return (
          <React.Fragment key={s.n}>
            <div className="flex flex-col items-center">
              <div className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-bold border-2 transition-colors ${
                done ? "bg-green-500 border-green-500 text-white"
                : current ? "bg-brand-600 border-brand-600 text-white"
                : "bg-white border-gray-300 text-gray-400"
              }`}>
                {done ? "✓" : s.n}
              </div>
              <span className={`text-xs mt-1 font-medium ${done || current ? "text-gray-700" : "text-gray-400"}`}>{s.label}</span>
            </div>
            {i < steps.length - 1 && (
              <div className={`flex-1 h-0.5 mb-5 mx-1 transition-colors ${done ? "bg-green-400" : "bg-gray-200"}`} />
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
}

type ButtonColor = "green" | "amber" | "blue" | "red-outline";

function ActionButton({
  label, busyLabel, isBusy, disabled, color, onClick,
}: {
  label: string; busyLabel: string; isBusy: boolean; disabled: boolean; color: ButtonColor; onClick: () => void;
}) {
  const base = "flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium disabled:opacity-50 transition-colors";
  const colors: Record<ButtonColor, string> = {
    green:       "bg-green-600 text-white hover:bg-green-700",
    amber:       "bg-amber-500 text-white hover:bg-amber-600",
    blue:        "bg-blue-600 text-white hover:bg-blue-700",
    "red-outline": "border border-red-600 text-red-600 hover:bg-red-50",
  };
  return (
    <button onClick={onClick} disabled={disabled} className={`${base} ${colors[color]}`}>
      {isBusy && <Spinner />}
      {isBusy ? busyLabel : label}
    </button>
  );
}

/** `active` gates all polling — only run status/QR polling while this tab is actually visible. */
function WhatsAppTab({ active }: { active: boolean }) {
  const { token } = useAuth();

  const [cfg, setCfg] = useState<ConfigResponse | null>(null);
  const [cfgLoading, setCfgLoading] = useState(true);

  const step = !cfg ? 0 : !cfg.hasToken ? 1 : !cfg.hasInstance ? 2 : 3;

  const [inputToken, setInputToken] = useState("");
  const [savingToken, setSavingToken] = useState(false);

  const [instanceMode, setInstanceMode] = useState<"enter" | "create">("create");
  const [inputInstanceId, setInputInstanceId] = useState("");
  const [savingInstance, setSavingInstance] = useState(false);

  const [status, setStatus]       = useState<WAStatus | null>(null);
  const [statusMsg, setStatusMsg] = useState<string | null>(null);
  const [qrSrc, setQrSrc]         = useState<string | null>(null);
  const [pairingPhone, setPairingPhone] = useState("");

  const [actionMsg, setActionMsg] = useDismissingState<{ type: "ok" | "err"; text: string } | null>(null);
  const [busy, setBusy]           = useState<string | null>(null);

  const fetchConfig = useCallback(async () => {
    if (!token) return;
    try {
      const res = await apiFetch<ConfigResponse>("/api/whatsapp/config", { authToken: token });
      setCfg(res);
    } catch {
      // network error — leave cfg null, tab shows loading state
    } finally {
      setCfgLoading(false);
    }
  }, [token]);

  useEffect(() => { if (active) fetchConfig(); }, [fetchConfig, active]);

  const fetchStatus = useCallback(async () => {
    if (!token || step !== 3) return;
    try {
      const res = await apiFetch<StatusResponse>("/api/whatsapp/status", { authToken: token });
      setStatus(res.status ?? null);
      setStatusMsg(res.message ?? null);
    } catch (e: any) {
      await fetchConfig();
      setStatus("FAILED");
      setStatusMsg(null);
    }
  }, [token, step, fetchConfig]);

  useEffect(() => { if (active && step === 3) fetchStatus(); }, [step, fetchStatus, active]);

  // Auto-poll status when not stable — only while this tab is active.
  useEffect(() => {
    if (!active || step !== 3 || status === null) return;
    if (ACTIVE_STATUSES.has(status)) return;
    const id = setInterval(fetchStatus, 5_000);
    return () => clearInterval(id);
  }, [active, step, status, fetchStatus]);

  const fetchQr = useCallback(async () => {
    if (!token) return;
    try {
      const res = await apiFetch<{ qr?: string }>("/api/whatsapp/qr", { authToken: token });
      if (res.qr) setQrSrc(`data:image/png;base64,${res.qr}`);
    } catch {
      setQrSrc(null);
    }
  }, [token]);

  useEffect(() => {
    if (active && status === "SCAN_QR_CODE") { fetchQr(); }
    else { setQrSrc(null); }
  }, [status, fetchQr, active]);

  // Auto-refresh QR every 20s while waiting — only while this tab is active.
  useEffect(() => {
    if (!active || status !== "SCAN_QR_CODE") return;
    const id = setInterval(fetchQr, 20_000);
    return () => clearInterval(id);
  }, [active, status, fetchQr]);

  const doAction = async (action: string, body?: object) => {
    if (!token) return;
    setBusy(action);
    setActionMsg(null);
    try {
      const res = await apiFetch<any>(`/api/whatsapp/${action}`, { method: "POST", authToken: token, body });
      setActionMsg({ type: "ok", text: res?.message || `${action} successful.` });
      await fetchStatus();
      await fetchConfig();
    } catch (e: any) {
      let msg = e?.message || `${action} failed.`;
      try { msg = JSON.parse(msg)?.message || msg; } catch {}
      await fetchConfig();
      if (!msg.includes("SESSION_NOT_FOUND")) {
        setActionMsg({ type: "err", text: msg });
      }
      await fetchStatus();
    } finally {
      setBusy(null);
    }
  };

  const saveToken = async () => {
    if (!inputToken.trim()) {
      setActionMsg({ type: "err", text: "Please enter your WAWP access token." });
      return;
    }
    setSavingToken(true);
    setActionMsg(null);
    try {
      await apiFetch("/api/whatsapp/config", { method: "POST", authToken: token!, body: { token: inputToken.trim(), instanceId: "" } });
      setInputToken("");
      await fetchConfig();
    } catch (e: any) {
      setActionMsg({ type: "err", text: e?.message || "Failed to save token." });
    } finally {
      setSavingToken(false);
    }
  };

  const saveInstanceId = async () => {
    if (!inputInstanceId.trim()) {
      setActionMsg({ type: "err", text: "Please enter the Instance ID." });
      return;
    }
    setSavingInstance(true);
    setActionMsg(null);
    try {
      await apiFetch("/api/whatsapp/config", { method: "POST", authToken: token!, body: { token: "", instanceId: inputInstanceId.trim() } });
      setInputInstanceId("");
      await fetchConfig();
    } catch (e: any) {
      setActionMsg({ type: "err", text: e?.message || "Failed to save Instance ID." });
    } finally {
      setSavingInstance(false);
    }
  };

  const createInstance = async () => {
    setSavingInstance(true);
    setActionMsg(null);
    try {
      const res = await apiFetch<any>("/api/whatsapp/create-instance", { method: "POST", authToken: token! });
      setActionMsg({ type: "ok", text: res?.message || "Instance created." });
      await fetchConfig();
    } catch (e: any) {
      setActionMsg({ type: "err", text: e?.message || "Failed to create instance." });
    } finally {
      setSavingInstance(false);
    }
  };

  const requestPairingCode = async () => {
    if (!pairingPhone.trim()) {
      setActionMsg({ type: "err", text: "Enter your phone number first." });
      return;
    }
    await doAction("request-code", { phoneNumber: pairingPhone.trim() });
  };

  const resetToken = async () => {
    if (!confirm("This will clear your saved access token. You will need to re-enter it. Continue?")) return;
    try {
      await apiFetch("/api/whatsapp/config", { method: "POST", authToken: token!, body: { token: "_clear_", instanceId: "" } });
    } catch {}
    setCfg(prev => prev ? { ...prev, hasToken: false, hasInstance: false, configured: false, tokenMasked: "", instanceId: "" } : null);
  };

  if (cfgLoading) {
    return (
      <div className="flex items-center gap-2 text-sm text-gray-500">
        <Spinner /> Loading…
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div>
        <h2 className="text-lg font-semibold text-gray-900">WhatsApp integration</h2>
        <p className="text-sm text-gray-500">Powered by WAWP — used to send tickets and notifications via WhatsApp.</p>
      </div>

      <StepIndicator step={step} />

      {actionMsg && <WAAlert type={actionMsg.type}>{actionMsg.text}</WAAlert>}

      {step === 1 && (
        <section className="border rounded-xl p-5 bg-gray-50 space-y-4">
          <h3 className="text-base font-semibold">Step 1 — Enter your WAWP Access Token</h3>
          <p className="text-sm text-gray-600">
            Your access token is found in your WAWP account dashboard at{" "}
            <a href="https://app.wawp.net" target="_blank" rel="noopener noreferrer" className="text-brand-600 hover:underline">app.wawp.net</a>.
          </p>
          <div className="space-y-2">
            <label className="block text-xs font-medium text-gray-700">Access Token</label>
            <input
              type="password"
              value={inputToken}
              onChange={e => setInputToken(e.target.value)}
              onKeyDown={e => e.key === "Enter" && saveToken()}
              placeholder="Paste your WAWP access token"
              className="w-full border rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-brand-500"
            />
          </div>
          <button onClick={saveToken} disabled={savingToken} className="flex items-center gap-2 px-5 py-2.5 rounded-lg bg-brand-600 text-white text-sm font-medium hover:bg-brand-700 disabled:opacity-50">
            {savingToken && <Spinner />}
            {savingToken ? "Saving…" : "Save Token & Continue"}
          </button>
        </section>
      )}

      {step === 2 && (
        <section className="border rounded-xl p-5 bg-gray-50 space-y-5">
          <div className="flex items-center justify-between">
            <h3 className="text-base font-semibold">Step 2 — Set Up Session Instance</h3>
            <span className="text-xs text-gray-400 font-mono bg-gray-100 px-2 py-0.5 rounded">Token: {cfg?.tokenMasked}</span>
          </div>
          <p className="text-sm text-gray-600">You need a WAWP session instance. Either create a brand-new one, or enter an existing Instance ID.</p>

          <div className="flex rounded-lg border overflow-hidden text-sm font-medium">
            <button onClick={() => setInstanceMode("create")} className={`flex-1 px-4 py-2.5 transition-colors ${instanceMode === "create" ? "bg-brand-600 text-white" : "bg-white text-gray-600 hover:bg-gray-50"}`}>
              Create new instance
            </button>
            <button onClick={() => setInstanceMode("enter")} className={`flex-1 px-4 py-2.5 border-l transition-colors ${instanceMode === "enter" ? "bg-brand-600 text-white" : "bg-white text-gray-600 hover:bg-gray-50"}`}>
              Enter existing ID
            </button>
          </div>

          {instanceMode === "create" && (
            <div className="space-y-3">
              <p className="text-sm text-gray-600">Click below to create a new WAWP session. The Instance ID will be saved automatically.</p>
              <button onClick={createInstance} disabled={savingInstance} className="flex items-center gap-2 px-5 py-2.5 rounded-lg bg-brand-600 text-white text-sm font-medium hover:bg-brand-700 disabled:opacity-50">
                {savingInstance && <Spinner />}
                {savingInstance ? "Creating…" : "Create Instance"}
              </button>
            </div>
          )}

          {instanceMode === "enter" && (
            <div className="space-y-3">
              <div>
                <label className="block text-xs font-medium text-gray-700 mb-1">Instance ID</label>
                <input
                  type="text"
                  value={inputInstanceId}
                  onChange={e => setInputInstanceId(e.target.value)}
                  onKeyDown={e => e.key === "Enter" && saveInstanceId()}
                  placeholder="e.g. BF14B761C364"
                  className="w-full border rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-brand-500"
                />
              </div>
              <button onClick={saveInstanceId} disabled={savingInstance} className="flex items-center gap-2 px-5 py-2.5 rounded-lg bg-brand-600 text-white text-sm font-medium hover:bg-brand-700 disabled:opacity-50">
                {savingInstance && <Spinner />}
                {savingInstance ? "Saving…" : "Save & Continue"}
              </button>
            </div>
          )}

          <button onClick={resetToken} className="text-xs text-gray-400 hover:text-red-500 hover:underline">← Change access token</button>
        </section>
      )}

      {step === 3 && (
        <>
          <section className="border rounded-xl p-5 bg-gray-50 space-y-3">
            <div className="flex items-center justify-between">
              <h3 className="text-base font-semibold">Session Status</h3>
              <button onClick={fetchStatus} className="text-xs text-brand-600 hover:underline">Refresh</button>
            </div>

            {status === null ? (
              <div className="flex items-center gap-2 text-sm text-gray-500"><Spinner /> Fetching status…</div>
            ) : (
              <div className="flex items-center gap-2">
                <span className="text-lg">{STATUS_ICONS[status] ?? "⚪"}</span>
                <span className={`inline-flex items-center px-3 py-1 rounded-full border text-sm font-semibold ${STATUS_COLORS[status] ?? "bg-gray-100 text-gray-700 border-gray-300"}`}>{status}</span>
              </div>
            )}

            {statusMsg && <p className="text-xs text-gray-500">{statusMsg}</p>}

            {status === "FAILED" && (
              <WAAlert type="err">The session has failed. The system will attempt to auto-restart. You can also restart manually below.</WAAlert>
            )}

            {status && POLLING_STATUSES.has(status) && (
              <p className="text-xs text-gray-400 flex items-center gap-1"><Spinner /> Auto-refreshing every 5 seconds…</p>
            )}

            <div className="flex flex-wrap gap-3 pt-2 border-t text-xs text-gray-500">
              <span>Token: <span className="font-mono">{cfg?.tokenMasked || "—"}</span></span>
              <span>Instance: <span className="font-mono">{cfg?.instanceId || "—"}</span></span>
            </div>
          </section>

          {status === "SCAN_QR_CODE" && (
            <section className="border rounded-xl p-5 bg-gray-50 space-y-4">
              <div className="flex items-center justify-between">
                <h3 className="text-base font-semibold">Scan QR Code</h3>
                <button onClick={fetchQr} className="text-xs text-brand-600 hover:underline">Refresh QR</button>
              </div>
              <p className="text-sm text-gray-600">Open WhatsApp → Linked Devices → Link a Device, then scan the code below.</p>
              {qrSrc ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={qrSrc} alt="WhatsApp QR Code" className="w-56 h-56 border rounded-lg" />
              ) : (
                <div className="flex items-center gap-2 text-sm text-gray-400"><Spinner /> Loading QR…</div>
              )}
              <p className="text-xs text-gray-400">QR codes expire after ~20 seconds — click Refresh QR if it stops working.</p>
            </section>
          )}

          {status === "SCAN_QR_CODE" && (
            <section className="border rounded-xl p-5 bg-gray-50 space-y-4">
              <h3 className="text-base font-semibold">Link by Phone Number Instead</h3>
              <p className="text-sm text-gray-600">Enter your WhatsApp number (SA format, e.g. 082 123 4567) to receive a pairing code on your phone.</p>
              <div className="flex gap-2">
                <input
                  type="tel"
                  value={pairingPhone}
                  onChange={e => setPairingPhone(e.target.value)}
                  placeholder="082 123 4567"
                  className="flex-1 border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
                />
                <button onClick={requestPairingCode} disabled={busy === "request-code"} className="flex items-center gap-1.5 px-4 py-2 rounded-lg bg-brand-600 text-white text-sm font-medium hover:bg-brand-700 disabled:opacity-50">
                  {busy === "request-code" && <Spinner />}
                  {busy === "request-code" ? "Sending…" : "Send code"}
                </button>
              </div>
            </section>
          )}

          <section className="border rounded-xl p-5 bg-gray-50 space-y-4">
            <h3 className="text-base font-semibold">Session Controls</h3>
            <div className="flex flex-wrap gap-3">
              <ActionButton label="Start" busyLabel="Starting…" isBusy={busy === "start"} disabled={!!busy} color="green" onClick={() => doAction("start")} />
              <ActionButton label="Restart" busyLabel="Restarting…" isBusy={busy === "restart"} disabled={!!busy} color="amber" onClick={() => doAction("restart")} />
              <ActionButton label="Logout" busyLabel="Logging out…" isBusy={busy === "logout"} disabled={!!busy} color="red-outline" onClick={() => {
                if (!confirm("This will log out the linked WhatsApp account. Are you sure?")) return;
                doAction("logout");
              }} />
            </div>
          </section>

          <section className="border rounded-xl p-5 bg-gray-50 space-y-4">
            <h3 className="text-base font-semibold">Instance Management</h3>
            <p className="text-sm text-gray-600">Create a brand-new instance or permanently delete the current one. Deleting will require you to set up a new instance.</p>
            <div className="flex flex-wrap gap-3">
              <ActionButton label="Create New Instance" busyLabel="Creating…" isBusy={busy === "create-instance"} disabled={!!busy} color="blue" onClick={() => doAction("create-instance")} />
              <ActionButton label="Delete Instance" busyLabel="Deleting…" isBusy={busy === "delete-instance"} disabled={!!busy} color="red-outline" onClick={() => {
                if (!confirm("This will PERMANENTLY delete the instance. You'll need to create a new one. Are you sure?")) return;
                doAction("delete-instance");
              }} />
            </div>
          </section>

          <details className="border rounded-xl bg-gray-50">
            <summary className="p-5 cursor-pointer text-sm font-semibold text-gray-700 select-none list-none flex items-center justify-between">
              <span>Update Credentials</span>
              <span className="text-gray-400 text-xs">expand ▾</span>
            </summary>
            <div className="px-5 pb-5 space-y-3 border-t pt-4">
              <p className="text-sm text-gray-600">Change your WAWP access token or Instance ID. Leave a field blank to keep the current value.</p>
              <div>
                <label className="block text-xs font-medium text-gray-700 mb-1">New Access Token</label>
                <input type="password" value={inputToken} onChange={e => setInputToken(e.target.value)} placeholder="Leave blank to keep current token" className="w-full border rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-brand-500" />
              </div>
              <div>
                <label className="block text-xs font-medium text-gray-700 mb-1">New Instance ID</label>
                <input type="text" value={inputInstanceId} onChange={e => setInputInstanceId(e.target.value)} placeholder="Leave blank to keep current instance" className="w-full border rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-brand-500" />
              </div>
              <button
                onClick={async () => {
                  if (!inputToken.trim() && !inputInstanceId.trim()) {
                    setActionMsg({ type: "err", text: "Enter at least one field to update." });
                    return;
                  }
                  setSavingToken(true);
                  setActionMsg(null);
                  try {
                    await apiFetch("/api/whatsapp/config", {
                      method: "POST",
                      authToken: token!,
                      body: { token: inputToken.trim() || undefined, instanceId: inputInstanceId.trim() || undefined },
                    });
                    setActionMsg({ type: "ok", text: "Credentials updated." });
                    setInputToken("");
                    setInputInstanceId("");
                    await fetchConfig();
                  } catch (e: any) {
                    setActionMsg({ type: "err", text: e?.message || "Failed to update." });
                  } finally {
                    setSavingToken(false);
                  }
                }}
                disabled={savingToken}
                className="flex items-center gap-2 px-4 py-2 rounded-lg bg-brand-600 text-white text-sm font-medium hover:bg-brand-700 disabled:opacity-50"
              >
                {savingToken && <Spinner />}
                {savingToken ? "Saving…" : "Save Changes"}
              </button>
            </div>
          </details>
        </>
      )}

      <p className="text-xs text-gray-400 text-center">
        WhatsApp notifications powered by{" "}
        <a href="https://wawp.net" target="_blank" rel="noopener noreferrer" className="hover:underline">WAWP</a>
        . Session auto-recovers on failure; admin alert sent if recovery fails.
      </p>
    </div>
  );
}
