'use client'

/**
 * Integrations tab of the Form Schema drawer. Manages signed outbound webhooks
 * (Zapier Catch Hook, Make, custom CRM endpoints) and guides editors through
 * the default Zapier → Webhooks by Zapier → Catch Hook setup.
 */
import { Toggle } from '../ui/Toggle.js'
import { ExternalLink, Loader2, Plus, Trash2, Zap } from 'lucide-react'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import {
  createFormWebhook,
  deleteFormWebhook,
  fetchFormWebhooks,
  testFormWebhook,
  updateFormWebhook,
  type FormWebhookConfig,
} from '../../lib/forms-service.js'
import { ConfirmDialog } from '../ui/ConfirmDialog.js'
import { FormsErrorState, FormsLoading, btnPrimary, btnSecondary } from './primitives.js'

const ZAPIER_CATCH_HOOK_DOCS = 'https://zapier.com/apps/webhook/integrations'
const FORMS_INTEGRATIONS_DOCS = 'https://actuatecms.dev/docs/forms-and-integrations'

const inputCls =
  'border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none'

export function WebhooksPanel({ formId, formSlug }: { formId: string; formSlug: string }) {
  const [webhooks, setWebhooks] = useState<FormWebhookConfig[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [url, setUrl] = useState('')
  const [creating, setCreating] = useState(false)
  const [createdSecret, setCreatedSecret] = useState<string | null>(null)
  const [pendingDelete, setPendingDelete] = useState<FormWebhookConfig | null>(null)
  const [testingId, setTestingId] = useState<string | null>(null)

  async function reload(): Promise<void> {
    setLoading(true)
    setError(null)
    try {
      setWebhooks(await fetchFormWebhooks(formId))
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : 'Failed to load webhooks')
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    let active = true
    setLoading(true)
    setError(null)
    fetchFormWebhooks(formId)
      .then((rows) => {
        if (active) setWebhooks(rows)
      })
      .catch((e: unknown) => {
        if (active) setError(e instanceof Error ? e.message : 'Failed to load webhooks')
      })
      .finally(() => {
        if (active) setLoading(false)
      })
    return () => {
      active = false
    }
  }, [formId])

  async function handleCreate(e: React.FormEvent): Promise<void> {
    e.preventDefault()
    const trimmed = url.trim()
    if (!trimmed) {
      toast.error('Paste your Catch Hook URL first.')
      return
    }
    setCreating(true)
    const res = await createFormWebhook(formId, {
      url: trimmed,
      events: ['form.submitted'],
      enabled: true,
    })
    setCreating(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    if (res.data?.secret) setCreatedSecret(res.data.secret)
    setUrl('')
    toast.success('Webhook connected.')
    await reload()
  }

  async function toggleEnabled(webhook: FormWebhookConfig, enabled: boolean): Promise<void> {
    const res = await updateFormWebhook(formId, webhook.id, { enabled })
    if (res.error) {
      toast.error(res.error)
      return
    }
    setWebhooks((rows) => rows.map((row) => (row.id === webhook.id ? { ...row, enabled } : row)))
  }

  async function handleTest(webhookId: string): Promise<void> {
    setTestingId(webhookId)
    const res = await testFormWebhook(formId, webhookId)
    setTestingId(null)
    if (res.error) {
      toast.error(res.error)
      return
    }
    if (res.data?.ok) {
      toast.success(`Test delivery succeeded (HTTP ${res.data.status}).`)
    } else {
      toast.error(res.data?.error || `Test failed (HTTP ${res.data?.status ?? 'unknown'}).`)
    }
    await reload()
  }

  async function confirmDelete(): Promise<void> {
    if (!pendingDelete) return
    const res = await deleteFormWebhook(formId, pendingDelete.id)
    setPendingDelete(null)
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success('Webhook removed.')
    await reload()
  }

  if (loading) return <FormsLoading label="Loading integrations…" />
  if (error) return <FormsErrorState message={error} onRetry={() => void reload()} />

  return (
    <div className="space-y-5">
      <section
        className="border-border bg-muted/40 space-y-3 rounded-lg border p-4"
        aria-labelledby="zapier-helper-title"
      >
        <div className="flex items-start gap-3">
          <span className="bg-primary/10 text-primary flex h-9 w-9 shrink-0 items-center justify-center rounded-md">
            <Zap size={18} aria-hidden />
          </span>
          <div className="min-w-0 space-y-2">
            <h3 id="zapier-helper-title" className="text-foreground text-sm font-medium">
              Connect to Zapier (recommended)
            </h3>
            <ol className="text-muted-foreground list-decimal space-y-1 pl-4 text-sm">
              <li>
                In Zapier, create a Zap with trigger{' '}
                <span className="text-foreground font-medium">Webhooks by Zapier → Catch Hook</span>
                .
              </li>
              <li>Copy the hook URL Zapier gives you and paste it below.</li>
              <li>
                Map fields in your action step — submission values arrive under{' '}
                <span className="font-mono text-xs">data.email</span>,{' '}
                <span className="font-mono text-xs">data.name</span>, etc.
              </li>
              <li>
                Use event <span className="font-mono text-xs">form.submitted</span> only (spam hits
                emit <span className="font-mono text-xs">form.spam_detected</span> separately).
              </li>
            </ol>
            <p className="text-muted-foreground text-xs">
              HubSpot, Salesforce, Slack, and Google Sheets work through Zapier actions — no native
              Actuate app required for v1.
            </p>
            <div className="flex flex-wrap gap-3 pt-1">
              <a
                href={ZAPIER_CATCH_HOOK_DOCS}
                target="_blank"
                rel="noopener noreferrer"
                className="text-primary inline-flex items-center gap-1 text-sm font-medium hover:underline"
              >
                Open Zapier Webhooks
                <ExternalLink size={14} aria-hidden />
              </a>
              <a
                href={FORMS_INTEGRATIONS_DOCS}
                target="_blank"
                rel="noopener noreferrer"
                className="text-primary inline-flex items-center gap-1 text-sm font-medium hover:underline"
              >
                Full integration guide
                <ExternalLink size={14} aria-hidden />
              </a>
            </div>
          </div>
        </div>
      </section>

      <form onSubmit={handleCreate} className="space-y-3">
        <label className="block">
          <span className="text-foreground mb-1 block text-sm font-medium">Webhook URL</span>
          <input
            type="url"
            value={url}
            onChange={(e) => setUrl(e.target.value)}
            placeholder="https://hooks.zapier.com/hooks/catch/…"
            className={inputCls}
            autoComplete="off"
          />
          <span className="text-muted-foreground mt-1 block text-xs">
            Paste your Catch Hook URL for form <span className="font-mono">{formSlug}</span>.
            Payloads are HMAC-signed via <span className="font-mono">X-Actuate-Signature</span>.
          </span>
        </label>
        <button
          type="submit"
          className={`${btnPrimary} inline-flex items-center`}
          disabled={creating}
        >
          {creating ? (
            <>
              <Loader2 className="mr-2 inline h-4 w-4 animate-spin" aria-hidden />
              Connecting…
            </>
          ) : (
            <>
              <Plus className="mr-1 inline h-4 w-4" aria-hidden />
              Add webhook
            </>
          )}
        </button>
      </form>

      {createdSecret && (
        <div
          className="border-success/30 bg-success/10 text-foreground space-y-2 rounded-md border px-3 py-3 text-sm"
          role="status"
        >
          <p className="font-medium">Signing secret (shown once)</p>
          <p className="text-muted-foreground text-xs">
            Store this if your CRM verifies HMAC signatures. You cannot retrieve it again after
            closing this panel.
          </p>
          <pre className="border-border bg-background overflow-x-auto rounded border px-2 py-1.5 font-mono text-xs">
            {createdSecret}
          </pre>
          <button type="button" className={btnSecondary} onClick={() => setCreatedSecret(null)}>
            Dismiss
          </button>
        </div>
      )}

      {webhooks.length === 0 ? (
        <p className="text-muted-foreground text-sm">
          No webhooks yet. Add a Catch Hook URL to send each submission to your CRM.
        </p>
      ) : (
        <ul className="space-y-3" aria-label="Configured webhooks">
          {webhooks.map((webhook) => (
            <li
              key={webhook.id}
              className="border-border flex flex-col gap-3 rounded-lg border p-3 sm:flex-row sm:items-center sm:justify-between"
            >
              <div className="min-w-0">
                <p className="text-foreground truncate font-mono text-xs">{webhook.url}</p>
                <p className="text-muted-foreground mt-1 text-xs">
                  Events: {webhook.events.join(', ') || 'form.submitted'}
                  {webhook.lastDeliveryAt
                    ? ` · Last delivery: ${webhook.lastDeliveryStatus ?? 'unknown'}`
                    : ''}
                </p>
              </div>
              <div className="flex shrink-0 flex-wrap items-center gap-2">
                <Toggle
                  checked={webhook.enabled}
                  onCheckedChange={(v) => void toggleEnabled(webhook, v)}
                  aria-label={`Enable webhook ${webhook.url}`}
                  variant="enabled"
                />
                <button
                  type="button"
                  className={btnSecondary}
                  disabled={testingId === webhook.id}
                  onClick={() => void handleTest(webhook.id)}
                >
                  {testingId === webhook.id ? 'Testing…' : 'Send test'}
                </button>
                <button
                  type="button"
                  className="text-destructive hover:bg-destructive/10 focus-visible:ring-ring inline-flex items-center gap-1 rounded-md px-2 py-1.5 text-sm font-medium focus-visible:ring-2 focus-visible:outline-none"
                  aria-label="Remove webhook"
                  onClick={() => setPendingDelete(webhook)}
                >
                  <Trash2 size={16} aria-hidden />
                  Remove
                </button>
              </div>
            </li>
          ))}
        </ul>
      )}

      <ConfirmDialog
        open={!!pendingDelete}
        onClose={() => setPendingDelete(null)}
        onConfirm={() => void confirmDelete()}
        title="Remove webhook?"
        description="New submissions will no longer be sent to this URL. Existing Zapier Zaps are not deleted — disable them in Zapier if needed."
        confirmLabel="Remove"
        cancelLabel="Keep webhook"
        destructive
      />
    </div>
  )
}
