import { useState, useEffect } from 'react';
import { Plus, Trash2, Copy, Send, Pencil, History, Key, RefreshCw, AlertCircle, Webhook, X, ChevronDown, ChevronUp } from 'lucide-react';
import api from '../lib/api';
import { toast } from './Toast';
import { ConfirmDialog } from './ConfirmDialog';

interface OutgoingWebhook {
  id: number;
  name: string;
  url: string;
  events: string[];
  include_sensitive: boolean;
  active: boolean;
  secret?: string;
  last_status_code: number | null;
  last_error: string | null;
  last_triggered_at: string | null;
  consecutive_failures: number;
}

interface Delivery {
  id: number;
  event: string;
  status: 'pending' | 'processing' | 'success' | 'failed';
  attempts: number;
  response_code: number | null;
  response_body: string | null;
  error: string | null;
  next_attempt_at: string | null;
  delivered_at: string | null;
  created_at: string;
  payload?: unknown;
}

interface FormState {
  name: string;
  url: string;
  events: string[];
  include_sensitive: boolean;
  active: boolean;
}

const emptyForm: FormState = { name: '', url: '', events: [], include_sensitive: false, active: true };

const statusLabels: Record<Delivery['status'], { label: string; className: string }> = {
  pending: { label: 'Aguardando', className: 'bg-yellow-100 text-yellow-800' },
  processing: { label: 'Enviando', className: 'bg-blue-100 text-blue-800' },
  success: { label: 'Entregue', className: 'bg-green-100 text-green-800' },
  failed: { label: 'Falhou', className: 'bg-red-100 text-red-800' },
};

const inputClass = 'w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent';

const formatDate = (value: string | null) => (value ? new Date(value).toLocaleString('pt-BR') : '-');

const errorMessage = (error: any, fallback: string) =>
  error?.response?.data?.message || fallback;

export function WebhooksTab() {
  const [webhooks, setWebhooks] = useState<OutgoingWebhook[]>([]);
  const [events, setEvents] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(true);

  const [showForm, setShowForm] = useState(false);
  const [editingId, setEditingId] = useState<number | null>(null);
  const [form, setForm] = useState<FormState>(emptyForm);
  const [saving, setSaving] = useState(false);

  const [secretModal, setSecretModal] = useState<OutgoingWebhook | null>(null);
  const [testingId, setTestingId] = useState<number | null>(null);
  const [deleteId, setDeleteId] = useState<number | null>(null);

  const [historyFor, setHistoryFor] = useState<OutgoingWebhook | null>(null);
  const [deliveries, setDeliveries] = useState<Delivery[]>([]);
  const [loadingDeliveries, setLoadingDeliveries] = useState(false);
  const [expandedDelivery, setExpandedDelivery] = useState<number | null>(null);
  const [retryingId, setRetryingId] = useState<number | null>(null);

  useEffect(() => {
    loadWebhooks();
  }, []);

  const loadWebhooks = async () => {
    try {
      setLoading(true);
      const { data } = await api.get('/outgoing-webhooks');
      setWebhooks(data.webhooks || []);
      setEvents(data.events || {});
    } catch (error) {
      console.error('Erro ao carregar webhooks:', error);
      toast.error('Erro ao carregar webhooks');
    } finally {
      setLoading(false);
    }
  };

  const openCreate = () => {
    setEditingId(null);
    setForm(emptyForm);
    setShowForm(true);
  };

  const openEdit = (webhook: OutgoingWebhook) => {
    setEditingId(webhook.id);
    setForm({
      name: webhook.name,
      url: webhook.url,
      events: webhook.events || [],
      include_sensitive: webhook.include_sensitive,
      active: webhook.active,
    });
    setShowForm(true);
  };

  const toggleEvent = (event: string) => {
    setForm((prev) => ({
      ...prev,
      events: prev.events.includes(event) ? prev.events.filter((e) => e !== event) : [...prev.events, event],
    }));
  };

  const handleSave = async (e: React.FormEvent) => {
    e.preventDefault();

    if (form.events.length === 0) {
      toast.error('Selecione pelo menos um evento');
      return;
    }

    setSaving(true);
    try {
      if (editingId) {
        await api.put(`/outgoing-webhooks/${editingId}`, form);
        toast.success('Webhook atualizado');
      } else {
        const { data } = await api.post('/outgoing-webhooks', form);
        toast.success('Webhook criado');
        setSecretModal(data.webhook);
      }
      setShowForm(false);
      await loadWebhooks();
    } catch (error: any) {
      console.error('Erro ao salvar webhook:', error);
      toast.error(errorMessage(error, 'Erro ao salvar webhook'));
    } finally {
      setSaving(false);
    }
  };

  const handleToggleActive = async (webhook: OutgoingWebhook) => {
    try {
      await api.put(`/outgoing-webhooks/${webhook.id}`, { active: !webhook.active });
      toast.success(webhook.active ? 'Webhook desativado' : 'Webhook ativado');
      await loadWebhooks();
    } catch (error: any) {
      toast.error(errorMessage(error, 'Erro ao alterar webhook'));
    }
  };

  const handleTest = async (webhook: OutgoingWebhook) => {
    setTestingId(webhook.id);
    try {
      const { data } = await api.post(`/outgoing-webhooks/${webhook.id}/test`);
      toast.success(data.message || 'Teste enviado');
    } catch (error: any) {
      toast.error(errorMessage(error, 'Falha no teste'));
    } finally {
      setTestingId(null);
      await loadWebhooks();
    }
  };

  const handleDelete = async () => {
    if (!deleteId) return;
    try {
      await api.delete(`/outgoing-webhooks/${deleteId}`);
      toast.success('Webhook removido');
      await loadWebhooks();
    } catch (error: any) {
      toast.error(errorMessage(error, 'Erro ao remover webhook'));
    } finally {
      setDeleteId(null);
    }
  };

  const showSecret = async (webhook: OutgoingWebhook) => {
    try {
      const { data } = await api.get(`/outgoing-webhooks/${webhook.id}`);
      setSecretModal(data.webhook);
    } catch (error: any) {
      toast.error(errorMessage(error, 'Erro ao carregar a chave'));
    }
  };

  const regenerateSecret = async () => {
    if (!secretModal) return;
    try {
      const { data } = await api.post(`/outgoing-webhooks/${secretModal.id}/regenerate-secret`);
      setSecretModal(data.webhook);
      toast.success('Nova chave gerada. Atualize-a no sistema que recebe o webhook.');
    } catch (error: any) {
      toast.error(errorMessage(error, 'Erro ao gerar nova chave'));
    }
  };

  const copy = (text: string, label: string) => {
    navigator.clipboard.writeText(text);
    toast.success(`${label} copiado!`);
  };

  const openHistory = async (webhook: OutgoingWebhook) => {
    setHistoryFor(webhook);
    setExpandedDelivery(null);
    await loadDeliveries(webhook.id);
  };

  const loadDeliveries = async (webhookId: number) => {
    setLoadingDeliveries(true);
    try {
      const { data } = await api.get(`/outgoing-webhooks/${webhookId}/deliveries`, { params: { limit: 50 } });
      setDeliveries(data.deliveries || []);
    } catch (error: any) {
      toast.error(errorMessage(error, 'Erro ao carregar histórico'));
    } finally {
      setLoadingDeliveries(false);
    }
  };

  const retryDelivery = async (delivery: Delivery) => {
    setRetryingId(delivery.id);
    try {
      const { data } = await api.post(`/outgoing-webhooks/deliveries/${delivery.id}/retry`);
      toast.success(data.message || 'Reenviado');
    } catch (error: any) {
      toast.error(errorMessage(error, 'Falha ao reenviar'));
    } finally {
      setRetryingId(null);
      if (historyFor) await loadDeliveries(historyFor.id);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-600"></div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
        <div>
          <h3 className="text-lg font-semibold text-gray-800">Webhooks</h3>
          <p className="text-sm text-gray-600 mt-1">
            Avise outro sistema (n8n, Make, Zapier, seu servidor...) automaticamente quando algo acontecer no painel.
          </p>
        </div>
        <button
          onClick={openCreate}
          className="inline-flex items-center justify-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
        >
          <Plus className="w-4 h-4" />
          Novo Webhook
        </button>
      </div>

      <div className="bg-blue-50 border border-blue-200 rounded-lg p-4 flex items-start gap-3">
        <AlertCircle className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" />
        <div className="text-sm text-blue-800 space-y-1">
          <p>
            Cada evento é enviado por <strong>POST</strong> em JSON, com o cabeçalho{' '}
            <code className="bg-blue-100 px-1 rounded">X-Webhook-Signature</code> ={' '}
            <code className="bg-blue-100 px-1 rounded">sha256=HMAC_SHA256(timestamp + "." + corpo, chave)</code>, onde o
            timestamp vem em <code className="bg-blue-100 px-1 rounded">X-Webhook-Timestamp</code>.
          </p>
          <p>
            Senhas só são enviadas se você marcar <strong>"Incluir senhas"</strong> (exige URL HTTPS). Se o destino falhar,
            o sistema tenta de novo em 1, 5, 15, 60 e 180 minutos.
          </p>
        </div>
      </div>

      {webhooks.length === 0 ? (
        <div className="text-center py-12 bg-gray-50 rounded-lg border border-gray-200">
          <Webhook className="w-12 h-12 text-gray-300 mx-auto mb-3" />
          <p className="text-gray-600">Nenhum webhook cadastrado</p>
          <p className="text-sm text-gray-500 mt-1">Crie um para receber os cadastros em outro sistema</p>
        </div>
      ) : (
        <div className="space-y-4">
          {webhooks.map((webhook) => (
            <div key={webhook.id} className="bg-white rounded-lg border border-gray-200 p-4">
              <div className="flex flex-col lg:flex-row lg:items-start justify-between gap-3">
                <div className="min-w-0 flex-1">
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="font-medium text-gray-900">{webhook.name}</span>
                    <span
                      className={`px-2 py-0.5 rounded-full text-xs font-medium ${
                        webhook.active ? 'bg-green-100 text-green-800' : 'bg-gray-200 text-gray-700'
                      }`}
                    >
                      {webhook.active ? 'Ativo' : 'Inativo'}
                    </span>
                    {webhook.include_sensitive && (
                      <span className="px-2 py-0.5 rounded-full text-xs font-medium bg-orange-100 text-orange-800">
                        Envia senhas
                      </span>
                    )}
                  </div>
                  <p className="text-sm text-gray-500 break-all mt-1">{webhook.url}</p>
                  <div className="flex flex-wrap gap-1 mt-2">
                    {webhook.events.map((event) => (
                      <span key={event} className="px-2 py-0.5 rounded-full text-xs bg-purple-100 text-purple-800">
                        {events[event] || event}
                      </span>
                    ))}
                  </div>
                  <p className="text-xs text-gray-500 mt-2">
                    Último envio: {formatDate(webhook.last_triggered_at)}
                    {webhook.last_status_code ? ` · HTTP ${webhook.last_status_code}` : ''}
                  </p>
                  {webhook.last_error && (
                    <p className="text-xs text-red-600 mt-1 break-all">Último erro: {webhook.last_error}</p>
                  )}
                </div>

                <div className="flex flex-wrap gap-2 lg:justify-end">
                  <button
                    onClick={() => handleTest(webhook)}
                    disabled={testingId === webhook.id}
                    className="inline-flex items-center gap-1 px-3 py-1.5 text-sm border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50"
                  >
                    <Send className="w-4 h-4" />
                    {testingId === webhook.id ? 'Enviando...' : 'Testar'}
                  </button>
                  <button
                    onClick={() => openHistory(webhook)}
                    className="inline-flex items-center gap-1 px-3 py-1.5 text-sm border border-gray-300 rounded-lg hover:bg-gray-50"
                  >
                    <History className="w-4 h-4" />
                    Histórico
                  </button>
                  <button
                    onClick={() => showSecret(webhook)}
                    className="inline-flex items-center gap-1 px-3 py-1.5 text-sm border border-gray-300 rounded-lg hover:bg-gray-50"
                  >
                    <Key className="w-4 h-4" />
                    Chave
                  </button>
                  <button
                    onClick={() => handleToggleActive(webhook)}
                    className="inline-flex items-center gap-1 px-3 py-1.5 text-sm border border-gray-300 rounded-lg hover:bg-gray-50"
                  >
                    {webhook.active ? 'Desativar' : 'Ativar'}
                  </button>
                  <button
                    onClick={() => openEdit(webhook)}
                    className="inline-flex items-center gap-1 px-3 py-1.5 text-sm text-purple-700 border border-purple-200 rounded-lg hover:bg-purple-50"
                  >
                    <Pencil className="w-4 h-4" />
                    Editar
                  </button>
                  <button
                    onClick={() => setDeleteId(webhook.id)}
                    className="inline-flex items-center gap-1 px-3 py-1.5 text-sm text-red-600 border border-red-200 rounded-lg hover:bg-red-50"
                  >
                    <Trash2 className="w-4 h-4" />
                  </button>
                </div>
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Criar / editar */}
      {showForm && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-lg max-w-lg w-full max-h-[90vh] overflow-y-auto">
            <form onSubmit={handleSave} className="p-6 space-y-4">
              <div className="flex items-center justify-between">
                <h3 className="text-lg font-semibold text-gray-800">
                  {editingId ? 'Editar Webhook' : 'Novo Webhook'}
                </h3>
                <button type="button" onClick={() => setShowForm(false)} className="text-gray-400 hover:text-gray-600">
                  <X className="w-5 h-5" />
                </button>
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-700 mb-1">Nome *</label>
                <input
                  type="text"
                  value={form.name}
                  onChange={(e) => setForm({ ...form, name: e.target.value })}
                  className={inputClass}
                  placeholder="Ex: n8n, Planilha, Meu sistema"
                  maxLength={100}
                  required
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-700 mb-1">URL de destino *</label>
                <input
                  type="url"
                  value={form.url}
                  onChange={(e) => setForm({ ...form, url: e.target.value })}
                  className={inputClass}
                  placeholder="https://seu-sistema.com/webhook"
                  required
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">Eventos *</label>
                <div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
                  {Object.entries(events).map(([event, label]) => (
                    <label
                      key={event}
                      className="flex items-start p-2 border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer"
                    >
                      <input
                        type="checkbox"
                        checked={form.events.includes(event)}
                        onChange={() => toggleEvent(event)}
                        className="form-checkbox h-4 w-4 text-purple-600 rounded mt-0.5"
                      />
                      <span className="ml-2 text-sm">
                        <span className="text-gray-800">{label}</span>
                        <span className="block text-xs text-gray-500 font-mono">{event}</span>
                      </span>
                    </label>
                  ))}
                </div>
              </div>

              <label className="flex items-start p-3 border border-orange-200 bg-orange-50 rounded-lg cursor-pointer">
                <input
                  type="checkbox"
                  checked={form.include_sensitive}
                  onChange={(e) => setForm({ ...form, include_sensitive: e.target.checked })}
                  className="form-checkbox h-4 w-4 text-purple-600 rounded mt-0.5"
                />
                <span className="ml-2 text-sm text-orange-900">
                  <strong>Incluir senhas</strong> (senha do cliente e senha do painel)
                  <span className="block text-xs mt-0.5">
                    Só funciona com URL HTTPS. Valide a assinatura no destino e não guarde as senhas em logs.
                  </span>
                </span>
              </label>

              <label className="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
                <input
                  type="checkbox"
                  checked={form.active}
                  onChange={(e) => setForm({ ...form, active: e.target.checked })}
                  className="form-checkbox h-4 w-4 text-purple-600 rounded"
                />
                Ativo
              </label>

              <div className="flex justify-end gap-2 pt-2">
                <button
                  type="button"
                  onClick={() => setShowForm(false)}
                  className="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"
                >
                  Cancelar
                </button>
                <button
                  type="submit"
                  disabled={saving}
                  className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 disabled:opacity-50"
                >
                  {saving ? 'Salvando...' : 'Salvar'}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* Chave secreta */}
      {secretModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-lg max-w-lg w-full p-6 space-y-4">
            <div className="flex items-center justify-between">
              <h3 className="text-lg font-semibold text-gray-800">Chave secreta · {secretModal.name}</h3>
              <button onClick={() => setSecretModal(null)} className="text-gray-400 hover:text-gray-600">
                <X className="w-5 h-5" />
              </button>
            </div>
            <p className="text-sm text-gray-600">
              Use esta chave no sistema de destino para conferir o cabeçalho{' '}
              <code className="bg-gray-100 px-1 rounded">X-Webhook-Signature</code>.
            </p>
            <div className="flex items-center gap-2">
              <code className="flex-1 bg-gray-100 px-3 py-2 rounded text-sm break-all">{secretModal.secret}</code>
              <button
                onClick={() => copy(secretModal.secret || '', 'Chave')}
                className="p-2 border border-gray-300 rounded-lg hover:bg-gray-50"
                title="Copiar"
              >
                <Copy className="w-4 h-4" />
              </button>
            </div>
            <details className="text-sm">
              <summary className="cursor-pointer text-purple-700">Exemplo de validação (Node.js)</summary>
              <pre className="mt-2 bg-gray-900 text-gray-100 p-3 rounded text-xs overflow-x-auto">{`const crypto = require('crypto');
// rawBody = corpo da requisição exatamente como chegou
const ts = req.headers['x-webhook-timestamp'];
const expected = 'sha256=' + crypto
  .createHmac('sha256', SECRET)
  .update(ts + '.' + rawBody)
  .digest('hex');
const ok = crypto.timingSafeEqual(
  Buffer.from(expected),
  Buffer.from(req.headers['x-webhook-signature'])
);
// recuse também timestamps com mais de 5 minutos`}</pre>
            </details>
            <div className="flex justify-between gap-2">
              <button
                onClick={regenerateSecret}
                className="inline-flex items-center gap-1 px-3 py-2 text-sm border border-gray-300 rounded-lg hover:bg-gray-50"
              >
                <RefreshCw className="w-4 h-4" />
                Gerar nova chave
              </button>
              <button
                onClick={() => setSecretModal(null)}
                className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700"
              >
                Fechar
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Histórico */}
      {historyFor && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-lg max-w-3xl w-full max-h-[90vh] flex flex-col">
            <div className="flex items-center justify-between p-4 border-b border-gray-200">
              <h3 className="text-lg font-semibold text-gray-800">Histórico · {historyFor.name}</h3>
              <div className="flex items-center gap-2">
                <button
                  onClick={() => loadDeliveries(historyFor.id)}
                  className="p-2 text-gray-500 hover:text-gray-700"
                  title="Atualizar"
                >
                  <RefreshCw className="w-4 h-4" />
                </button>
                <button onClick={() => setHistoryFor(null)} className="text-gray-400 hover:text-gray-600">
                  <X className="w-5 h-5" />
                </button>
              </div>
            </div>
            <div className="overflow-y-auto p-4 space-y-2">
              {loadingDeliveries ? (
                <div className="flex justify-center py-8">
                  <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-purple-600"></div>
                </div>
              ) : deliveries.length === 0 ? (
                <p className="text-center text-gray-500 py-8">Nenhum envio ainda</p>
              ) : (
                deliveries.map((delivery) => {
                  const status = statusLabels[delivery.status] || statusLabels.pending;
                  const expanded = expandedDelivery === delivery.id;
                  return (
                    <div key={delivery.id} className="border border-gray-200 rounded-lg">
                      <div className="flex flex-wrap items-center gap-2 p-3">
                        <span className={`px-2 py-0.5 rounded-full text-xs font-medium ${status.className}`}>
                          {status.label}
                        </span>
                        <span className="font-mono text-sm text-gray-800">{delivery.event}</span>
                        <span className="text-xs text-gray-500">{formatDate(delivery.created_at)}</span>
                        <span className="text-xs text-gray-500">
                          {delivery.response_code ? `HTTP ${delivery.response_code} · ` : ''}
                          {delivery.attempts} tentativa(s)
                        </span>
                        <div className="ml-auto flex gap-1">
                          {delivery.status !== 'success' && delivery.status !== 'processing' && (
                            <button
                              onClick={() => retryDelivery(delivery)}
                              disabled={retryingId === delivery.id}
                              className="px-2 py-1 text-xs border border-gray-300 rounded hover:bg-gray-50 disabled:opacity-50"
                            >
                              {retryingId === delivery.id ? 'Enviando...' : 'Reenviar'}
                            </button>
                          )}
                          <button
                            onClick={() => setExpandedDelivery(expanded ? null : delivery.id)}
                            className="p-1 text-gray-500 hover:text-gray-700"
                          >
                            {expanded ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
                          </button>
                        </div>
                      </div>
                      {delivery.error && (
                        <p className="px-3 pb-2 text-xs text-red-600 break-all">{delivery.error}</p>
                      )}
                      {delivery.status === 'pending' && delivery.next_attempt_at && (
                        <p className="px-3 pb-2 text-xs text-gray-500">
                          Próxima tentativa: {formatDate(delivery.next_attempt_at)}
                        </p>
                      )}
                      {expanded && (
                        <div className="border-t border-gray-200 p-3 space-y-2">
                          <p className="text-xs font-medium text-gray-600">Conteúdo enviado</p>
                          <pre className="bg-gray-900 text-gray-100 p-3 rounded text-xs overflow-x-auto">
                            {JSON.stringify(delivery.payload, null, 2)}
                          </pre>
                          {delivery.response_body && (
                            <>
                              <p className="text-xs font-medium text-gray-600">Resposta do destino</p>
                              <pre className="bg-gray-100 p-3 rounded text-xs overflow-x-auto whitespace-pre-wrap break-all">
                                {delivery.response_body}
                              </pre>
                            </>
                          )}
                        </div>
                      )}
                    </div>
                  );
                })
              )}
            </div>
          </div>
        </div>
      )}

      <ConfirmDialog
        isOpen={deleteId !== null}
        onClose={() => setDeleteId(null)}
        onConfirm={handleDelete}
        title="Remover webhook"
        message="O webhook e todo o histórico de envios serão removidos. Deseja continuar?"
        confirmText="Remover"
        type="danger"
      />
    </div>
  );
}
