import React, { useEffect, useState, useCallback, useRef } from 'react'
import { createPortal } from 'react-dom'
import { useRouter } from 'next/router'
import { motion, AnimatePresence } from 'framer-motion'
import {
  Plug2, CheckCircle2, XCircle, Settings, ChevronDown,
  ChevronUp, Loader2, AlertTriangle, Eye, EyeOff, Save,
  RefreshCw, ShieldCheck, Package, Database, Trash2, Plus,
  Info, MessageSquare, FileText, Image, Users, CreditCard,
  Stethoscope, ScanLine, Download, Film,
} from 'lucide-react'
import { useAuth } from '@/context/AuthContext'
import { api } from '@/services/chatApiService'
import { PageHeader, Card, Badge } from '@/components/ui'

// ─── Types ────────────────────────────────────────────────────────────────────

interface ConfigField {
  key: string
  label: string
  type: 'text' | 'password' | 'select' | 'toggle' | 'model_select' | 'provider_chain'
  placeholder?: string
  description?: string
  tooltip?: string
  options?: Array<{ label: string; value: string }>
  required?: boolean
  group?: string
  default?: string
}

interface Plugin {
  name: string
  displayName: string
  version: string
  description: string
  author: string
  category: string
  active: boolean
  canDisable: boolean
  dependencies: string[]
  configSchema: ConfigField[]
  config: Record<string, string>
  hooks: { subscribes: string[]; emits: string[] }
}

const CATEGORY_LABELS: Record<string, string> = {
  core: 'Core',
  business: 'Negócio',
  integration: 'Integração',
  utility: 'Utilitário',
}

const CATEGORY_COLORS: Record<string, string> = {
  core: 'bg-blue-500/10 text-blue-400 border border-blue-500/20',
  business: 'bg-green-500/10 text-green-400 border border-green-500/20',
  integration: 'bg-purple-500/10 text-purple-400 border border-purple-500/20',
  utility: 'bg-yellow-500/10 text-yellow-400 border border-yellow-500/20',
}

// ─── Modelos conhecidos por provider ─────────────────────────────────────────

const MODELS_BY_PROVIDER: Record<string, { label: string; value: string }[]> = {
  openai: [
    { label: 'GPT-4o (melhor qualidade)', value: 'gpt-4o' },
    { label: 'GPT-4o Mini (rápido / barato)', value: 'gpt-4o-mini' },
    { label: 'GPT-4 Turbo', value: 'gpt-4-turbo' },
    { label: 'GPT-3.5 Turbo', value: 'gpt-3.5-turbo' },
  ],
  anthropic: [
    { label: 'Claude Sonnet 4.5 (melhor)', value: 'claude-sonnet-4-5' },
    { label: 'Claude 3.5 Haiku (rápido / barato)', value: 'claude-3-5-haiku-20241022' },
    { label: 'Claude 3.5 Sonnet', value: 'claude-3-5-sonnet-20241022' },
  ],
  gemini: [
    { label: 'Gemini 2.0 Flash (recomendado)', value: 'gemini-2.0-flash' },
    { label: 'Gemini 2.0 Flash Lite (mais barato)', value: 'gemini-2.0-flash-lite' },
    { label: 'Gemini 2.5 Pro (mais poderoso)', value: 'gemini-2.5-pro-preview-03-25' },
    { label: 'Gemini 1.5 Pro', value: 'gemini-1.5-pro-latest' },
  ],
  ollama: [
    { label: 'Llama 3.1 (recomendado)', value: 'llama3.1' },
    { label: 'Llama 3', value: 'llama3' },
    { label: 'Mistral', value: 'mistral' },
    { label: 'Gemma 2', value: 'gemma2' },
    { label: 'Phi-3', value: 'phi3' },
    { label: 'Qwen 2.5', value: 'qwen2.5' },
  ],
}

// normaliza options que podem vir como string[] ou {label,value}[]
function normalizeOptions(opts: any[]): { label: string; value: string }[] {
  return opts.map(o => typeof o === 'string' ? { label: o, value: o } : o)
}

// ─── Provider Chain Field ─────────────────────────────────────────────────────

const PROVIDER_LABELS: Record<string, { label: string; color: string }> = {
  openai:    { label: 'OpenAI',    color: 'text-green-400' },
  gemini:    { label: 'Gemini',    color: 'text-blue-400' },
  anthropic: { label: 'Anthropic', color: 'text-purple-400' },
  ollama:    { label: 'Ollama',    color: 'text-yellow-400' },
}

const ALL_PROVIDERS = ['openai', 'gemini', 'anthropic', 'ollama']

function ProviderChainField({ value, onChange }: { value: string; onChange: (v: string) => void }) {
  const chain = (value || 'openai,gemini,anthropic,ollama')
    .split(',').map(s => s.trim()).filter(Boolean)

  // Garante que todos os providers existam na lista
  const full = [
    ...chain,
    ...ALL_PROVIDERS.filter(p => !chain.includes(p)),
  ]

  const move = (idx: number, dir: -1 | 1) => {
    const next = [...full]
    const swap = idx + dir
    if (swap < 0 || swap >= next.length) return
    ;[next[idx], next[swap]] = [next[swap], next[idx]]
    onChange(next.join(','))
  }

  return (
    <div className="space-y-1.5">
      {full.map((p, idx) => {
        const meta = PROVIDER_LABELS[p] ?? { label: p, color: 'text-slate-400' }
        return (
          <div key={p} className="flex items-center gap-2 bg-white/[0.03] border border-white/8 rounded-xl px-3 py-2">
            <span className="text-[10px] font-black text-slate-700 w-4">{idx + 1}</span>
            <span className={`flex-1 text-xs font-bold ${meta.color}`}>{meta.label}</span>
            <div className="flex gap-1">
              <button
                type="button"
                onClick={() => move(idx, -1)}
                disabled={idx === 0}
                className="w-6 h-6 rounded-lg flex items-center justify-center text-slate-600 hover:text-white hover:bg-white/10 disabled:opacity-20 transition-all"
              >
                <ChevronUp size={12} />
              </button>
              <button
                type="button"
                onClick={() => move(idx, 1)}
                disabled={idx === full.length - 1}
                className="w-6 h-6 rounded-lg flex items-center justify-center text-slate-600 hover:text-white hover:bg-white/10 disabled:opacity-20 transition-all"
              >
                <ChevronDown size={12} />
              </button>
            </div>
          </div>
        )
      })}
      <p className="text-[10px] text-slate-700 pt-1">
        Use ↑↓ para reordenar. Providers sem chave configurada são pulados automaticamente.
      </p>
    </div>
  )
}

// ─── Info Tooltip (portal — escapa do overflow do modal) ─────────────────────

function InfoTooltip({ text }: { text: string }) {
  const btnRef = useRef<HTMLButtonElement>(null)
  const [rect, setRect] = useState<DOMRect | null>(null)
  const [mounted, setMounted] = useState(false)

  useEffect(() => { setMounted(true) }, [])

  const show = () => setRect(btnRef.current?.getBoundingClientRect() ?? null)
  const hide = () => setRect(null)

  const tooltipLeft = rect ? Math.min(rect.right + 10, window.innerWidth - 270) : 0
  const tooltipTop  = rect ? rect.top + rect.height / 2 : 0

  return (
    <span className="inline-flex items-center ml-1.5 align-middle shrink-0">
      <button
        ref={btnRef}
        type="button"
        onMouseEnter={show}
        onMouseLeave={hide}
        onFocus={show}
        onBlur={hide}
        className="text-slate-600 hover:text-blue-400 transition-colors focus:outline-none"
        tabIndex={-1}
      >
        <Info size={12} />
      </button>

      {mounted && rect && createPortal(
        <div
          style={{
            position: 'fixed',
            left: tooltipLeft,
            top: tooltipTop,
            transform: 'translateY(-50%)',
            zIndex: 9999,
          }}
          className="w-64 bg-[#1a1d27] border border-white/15 rounded-xl px-3 py-2.5 text-[11px] text-slate-300 leading-relaxed shadow-2xl pointer-events-none"
        >
          {text}
        </div>,
        document.body
      )}
    </span>
  )
}

// ─── Category Buckets Editor ───────────────────────────────────────────────────

const CATEGORY_META: Record<string, { icon: React.ReactNode; label: string; color: string }> = {
  whatsapp:  { icon: <MessageSquare size={13} />, label: 'WhatsApp',  color: 'text-green-400 bg-green-500/10' },
  media:     { icon: <Film size={13} />,          label: 'Media',     color: 'text-blue-400 bg-blue-500/10' },
  documents: { icon: <FileText size={13} />,      label: 'Documents', color: 'text-amber-400 bg-amber-500/10' },
  posts:     { icon: <Image size={13} />,         label: 'Posts',     color: 'text-purple-400 bg-purple-500/10' },
  cards:     { icon: <CreditCard size={13} />,    label: 'Cards',     color: 'text-pink-400 bg-pink-500/10' },
  partners:  { icon: <Users size={13} />,         label: 'Partners',  color: 'text-cyan-400 bg-cyan-500/10' },
  cdi:       { icon: <Stethoscope size={13} />,   label: 'CDI',       color: 'text-red-400 bg-red-500/10' },
  xrays:     { icon: <ScanLine size={13} />,      label: 'Xrays',     color: 'text-indigo-400 bg-indigo-500/10' },
  exports:   { icon: <Download size={13} />,      label: 'Exports',   color: 'text-slate-400 bg-slate-500/10' },
}

function CategoryBucketsEditor({
  fields,
  form,
  setForm,
  mainBucket,
}: {
  fields: ConfigField[]
  form: Record<string, string>
  setForm: React.Dispatch<React.SetStateAction<Record<string, string>>>
  mainBucket: string
}) {
  return (
    <div className="space-y-2">
      <p className="text-[11px] text-slate-600 leading-relaxed mb-3">
        Cada categoria de arquivo pode ser enviada para um bucket dedicado.
        Deixe em branco para usar o <span className="text-slate-400 font-mono">{mainBucket || 'Bucket Principal'}</span>.
      </p>
      {fields.map(field => {
        const cat = field.key.replace('category_bucket_', '')
        const meta = CATEGORY_META[cat]
        const value = form[field.key] ?? ''
        return (
          <div
            key={field.key}
            className="flex items-center gap-3 bg-white/[0.02] border border-white/[0.06] rounded-xl px-3 py-2.5"
          >
            {/* Category badge */}
            <div className={`flex items-center gap-1.5 w-28 shrink-0 rounded-lg px-2 py-1 ${meta?.color ?? 'text-slate-400 bg-slate-500/10'}`}>
              {meta?.icon}
              <span className="text-[11px] font-bold">{meta?.label ?? cat}</span>
            </div>

            {/* Arrow */}
            <span className="text-slate-700 text-xs shrink-0">→</span>

            {/* Input */}
            <input
              type="text"
              value={value}
              onChange={e => setForm(f => ({ ...f, [field.key]: e.target.value }))}
              placeholder={mainBucket || field.placeholder || 'bucket principal'}
              className="flex-1 bg-transparent text-sm text-white placeholder-slate-700 focus:outline-none min-w-0"
            />

            {/* Tooltip */}
            {field.tooltip && <InfoTooltip text={field.tooltip} />}
          </div>
        )
      })}
    </div>
  )
}

// ─── Config Modal ──────────────────────────────────────────────────────────────

const GROUP_META: Record<string, { icon: React.ReactNode; color: string; defaultOpen?: boolean }> = {
  'Credenciais Wasabi': { icon: <ShieldCheck size={14} />, color: 'text-emerald-400', defaultOpen: true },
  'Armazenamento':      { icon: <Database size={14} />,    color: 'text-blue-400',    defaultOpen: true },
  'Avançado':           { icon: <Settings size={14} />,    color: 'text-slate-400',   defaultOpen: false },
  'Buckets por Categoria': { icon: <Package size={14} />, color: 'text-purple-400',  defaultOpen: true },
  'Geral':              { icon: <Settings size={14} />,    color: 'text-slate-400',   defaultOpen: true },
}

function ConfigFieldInput({
  field,
  value,
  onChange,
  showSecret,
  onToggleSecret,
  form,
}: {
  field: ConfigField
  value: string
  onChange: (v: string) => void
  showSecret: boolean
  onToggleSecret: () => void
  form: Record<string, string>
}) {
  if (field.type === 'toggle') {
    return (
      <button
        onClick={() => onChange(value === 'true' ? 'false' : 'true')}
        className={`w-12 h-6 rounded-full transition-colors ${value === 'true' ? 'bg-brand-500' : 'bg-white/10'}`}
      >
        <span className={`block w-4 h-4 rounded-full bg-white mx-1 transition-transform ${value === 'true' ? 'translate-x-6' : ''}`} />
      </button>
    )
  }
  if (field.type === 'select') {
    return (
      <select
        value={value}
        onChange={e => onChange(e.target.value)}
        className="w-full bg-[#12151e] border border-white/10 rounded-xl px-3 py-2.5 text-sm text-white focus:outline-none focus:border-brand-500/50"
      >
        <option value="" className="bg-[#12151e]">Selecionar...</option>
        {normalizeOptions(field.options ?? []).map(opt => (
          <option key={opt.value} value={opt.value} className="bg-[#12151e]">{opt.label}</option>
        ))}
      </select>
    )
  }
  if (field.type === 'model_select') {
    const provider = form['default_provider'] ?? ''
    const models = MODELS_BY_PROVIDER[provider] ?? Object.values(MODELS_BY_PROVIDER).flat()
    return (
      <select
        value={value}
        onChange={e => onChange(e.target.value)}
        className="w-full bg-[#12151e] border border-white/10 rounded-xl px-3 py-2.5 text-sm text-white focus:outline-none focus:border-brand-500/50"
      >
        <option value="" className="bg-[#12151e]">Auto (padrão do provider)</option>
        {models.map(m => (
          <option key={m.value} value={m.value} className="bg-[#12151e]">{m.label}</option>
        ))}
      </select>
    )
  }
  if (field.type === 'provider_chain') {
    return (
      <ProviderChainField
        value={value || field.default || 'openai,gemini,anthropic,ollama'}
        onChange={onChange}
      />
    )
  }
  // text / password
  return (
    <div className="relative">
      <input
        type={field.type === 'password' && !showSecret ? 'password' : 'text'}
        value={value}
        onChange={e => onChange(e.target.value)}
        placeholder={field.placeholder}
        className="w-full bg-white/[0.04] border border-white/10 rounded-xl px-3 py-2.5 text-sm text-white placeholder-slate-700 focus:outline-none focus:border-brand-500/40 transition-colors pr-10"
      />
      {field.type === 'password' && (
        <button
          type="button"
          onClick={onToggleSecret}
          className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-600 hover:text-white transition-colors"
        >
          {showSecret ? <EyeOff size={14} /> : <Eye size={14} />}
        </button>
      )}
    </div>
  )
}

function ConfigGroup({
  group,
  fields,
  form,
  setForm,
  showSecrets,
  setShowSecrets,
}: {
  group: string
  fields: ConfigField[]
  form: Record<string, string>
  setForm: React.Dispatch<React.SetStateAction<Record<string, string>>>
  showSecrets: Record<string, boolean>
  setShowSecrets: React.Dispatch<React.SetStateAction<Record<string, boolean>>>
}) {
  const meta = GROUP_META[group] ?? GROUP_META['Geral']
  const [open, setOpen] = useState(meta.defaultOpen ?? true)
  const isCategoryGroup = group === 'Buckets por Categoria'

  return (
    <div className="border border-white/[0.07] rounded-2xl overflow-hidden">
      {/* Group header */}
      <button
        type="button"
        onClick={() => setOpen(o => !o)}
        className="w-full flex items-center justify-between px-4 py-3 bg-white/[0.02] hover:bg-white/[0.04] transition-colors"
      >
        <div className="flex items-center gap-2.5">
          <span className={meta.color}>{meta.icon}</span>
          <span className="text-xs font-bold text-slate-300 tracking-wide">{group}</span>
          {!meta.defaultOpen && !open && (
            <span className="text-[10px] text-slate-600 font-normal">raramente necessário</span>
          )}
        </div>
        <ChevronDown
          size={14}
          className={`text-slate-600 transition-transform duration-200 ${open ? 'rotate-180' : ''}`}
        />
      </button>

      {/* Group body */}
      {open && (
        <div className="px-4 py-4 space-y-4 border-t border-white/[0.05]">
          {isCategoryGroup ? (
            <CategoryBucketsEditor
              fields={fields}
              form={form}
              setForm={setForm}
              mainBucket={form['wasabiBucket'] ?? ''}
            />
          ) : (
            fields.map(field => (
              <div key={field.key}>
                <label className="flex items-center gap-1 text-xs font-semibold text-slate-400 mb-1.5">
                  <span>{field.label}</span>
                  {field.required && <span className="text-red-400">*</span>}
                  {field.tooltip && <InfoTooltip text={field.tooltip} />}
                </label>
                {field.description && (
                  <p className="text-[11px] text-slate-600 mb-1.5 leading-relaxed">{field.description}</p>
                )}
                <ConfigFieldInput
                  field={field}
                  value={form[field.key] ?? ''}
                  onChange={v => setForm(f => ({ ...f, [field.key]: v }))}
                  showSecret={showSecrets[field.key] ?? false}
                  onToggleSecret={() => setShowSecrets(s => ({ ...s, [field.key]: !s[field.key] }))}
                  form={form}
                />
              </div>
            ))
          )}
        </div>
      )}
    </div>
  )
}

function ConfigModal({ plugin, onClose, onSaved }: {
  plugin: Plugin
  onClose: () => void
  onSaved: () => void
}) {
  const [form, setForm] = useState<Record<string, string>>(plugin.config ?? {})
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState('')
  const [showSecrets, setShowSecrets] = useState<Record<string, boolean>>({})

  const groups = Array.from(new Set(plugin.configSchema.map(f => f.group ?? 'Geral')))

  const handleSave = async () => {
    setSaving(true)
    setError('')
    try {
      await api.put(`/api/admin/plugins/${plugin.name}/config`, form)
      onSaved()
      onClose()
    } catch (err: any) {
      setError(err?.response?.data?.error ?? 'Erro ao salvar configuração')
    } finally {
      setSaving(false)
    }
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
      <motion.div
        initial={{ opacity: 0, scale: 0.97, y: 8 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        exit={{ opacity: 0, scale: 0.97, y: 8 }}
        transition={{ duration: 0.18, ease: 'easeOut' }}
        className="bg-[#0d1018] border border-white/10 rounded-2xl w-full max-w-lg shadow-2xl flex flex-col max-h-[90vh]"
      >
        {/* Header — fixed, não rola */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-white/[0.07] shrink-0">
          <div className="flex items-center gap-3">
            <div className="w-8 h-8 rounded-xl bg-white/5 flex items-center justify-center">
              <Settings size={15} className="text-slate-400" />
            </div>
            <div>
              <h2 className="text-white font-bold text-base leading-tight">{plugin.displayName}</h2>
              <p className="text-slate-600 text-xs">v{plugin.version}</p>
            </div>
          </div>
          <button
            onClick={onClose}
            className="w-8 h-8 flex items-center justify-center rounded-xl text-slate-500 hover:text-white hover:bg-white/8 transition-colors"
          >
            <XCircle size={16} />
          </button>
        </div>

        {/* Body — só esta parte rola */}
        <div className="overflow-y-auto flex-1 px-6 py-5 space-y-3">
          {groups.map(group => {
            const fields = plugin.configSchema.filter(f => (f.group ?? 'Geral') === group)
            return (
              <ConfigGroup
                key={group}
                group={group}
                fields={fields}
                form={form}
                setForm={setForm}
                showSecrets={showSecrets}
                setShowSecrets={setShowSecrets}
              />
            )
          })}

          {error && (
            <div className="flex items-center gap-2 text-red-400 bg-red-500/10 border border-red-500/20 rounded-xl px-4 py-3 text-sm">
              <AlertTriangle size={15} />
              {error}
            </div>
          )}
        </div>

        {/* Footer — fixed, não rola */}
        <div className="flex items-center justify-between px-6 py-4 border-t border-white/[0.07] shrink-0">
          <p className="text-[11px] text-slate-700">
            Passe o mouse sobre <Info size={10} className="inline mb-0.5 text-blue-400" /> para ver detalhes de cada campo
          </p>
          <div className="flex gap-2">
            <button
              onClick={onClose}
              className="px-4 py-2 text-sm text-slate-400 hover:text-white transition-colors rounded-xl hover:bg-white/5"
            >
              Cancelar
            </button>
            <button
              onClick={handleSave}
              disabled={saving}
              className="flex items-center gap-2 px-4 py-2 bg-brand-500 hover:bg-brand-600 text-white text-sm font-semibold rounded-xl transition-colors disabled:opacity-50"
            >
              {saving ? <Loader2 size={14} className="animate-spin" /> : <Save size={14} />}
              Salvar
            </button>
          </div>
        </div>
      </motion.div>
    </div>
  )
}

// ─── Wasabi Storage Modal ─────────────────────────────────────────────────────

const WASABI_REGIONS = [
  { region: 'us-east-1',      endpoint: 's3.wasabisys.com',              label: 'US East 1 (N. Virginia)'   },
  { region: 'us-east-2',      endpoint: 's3.us-east-2.wasabisys.com',    label: 'US East 2 (N. Virginia)'   },
  { region: 'us-central-1',   endpoint: 's3.us-central-1.wasabisys.com', label: 'US Central 1 (Texas)'      },
  { region: 'us-west-1',      endpoint: 's3.us-west-1.wasabisys.com',    label: 'US West 1 (Oregon)'        },
  { region: 'eu-central-1',   endpoint: 's3.eu-central-1.wasabisys.com', label: 'EU Central 1 (Amsterdam)'  },
  { region: 'eu-central-2',   endpoint: 's3.eu-central-2.wasabisys.com', label: 'EU Central 2 (Frankfurt)'  },
  { region: 'eu-west-1',      endpoint: 's3.eu-west-1.wasabisys.com',    label: 'EU West 1 (London)'        },
  { region: 'eu-west-2',      endpoint: 's3.eu-west-2.wasabisys.com',    label: 'EU West 2 (Paris)'         },
  { region: 'eu-south-1',     endpoint: 's3.eu-south-1.wasabisys.com',   label: 'EU South 1 (Milan)'        },
  { region: 'ap-northeast-1', endpoint: 's3.ap-northeast-1.wasabisys.com', label: 'AP Northeast 1 (Tokyo)' },
  { region: 'ap-northeast-2', endpoint: 's3.ap-northeast-2.wasabisys.com', label: 'AP Northeast 2 (Osaka)'  },
  { region: 'ap-southeast-1', endpoint: 's3.ap-southeast-1.wasabisys.com', label: 'AP Southeast 1 (Singapore)' },
  { region: 'ap-southeast-2', endpoint: 's3.ap-southeast-2.wasabisys.com', label: 'AP Southeast 2 (Sydney)'  },
]

type FetchStatus = 'idle' | 'loading' | 'ok' | 'error'

interface WasabiBucketItem { name: string; createdAt?: string }

function WasabiStorageModal({ plugin, onClose, onSaved }: {
  plugin: Plugin
  onClose: () => void
  onSaved: () => void
}) {
  const cfg = plugin.config ?? {}

  // Credenciais
  const [accessKey, setAccessKey]   = useState(cfg.wasabiAccessKey ?? '')
  const [secretKey, setSecretKey]   = useState(cfg.wasabiSecretKey ?? '')
  const [region,    setRegion]      = useState(cfg.wasabiRegion    ?? 'us-east-1')
  const [endpoint,  setEndpoint]    = useState(cfg.wasabiEndpoint  ?? '')
  const [showKey,   setShowKey]     = useState(false)
  const [showAdvanced, setShowAdvanced] = useState(!!(cfg.wasabiRegion || cfg.wasabiEndpoint))

  // Buckets
  const [buckets,       setBuckets]       = useState<WasabiBucketItem[]>([])
  const [selectedBucket, setSelectedBucket] = useState(cfg.wasabiBucket ?? '')
  const [fetchStatus,   setFetchStatus]   = useState<FetchStatus>('idle')
  const [fetchError,    setFetchError]    = useState('')

  // Criar bucket
  const [newName,   setNewName]   = useState('')
  const [creating,  setCreating]  = useState(false)
  const [createErr, setCreateErr] = useState('')

  // Salvar
  const [saving,   setSaving]   = useState(false)
  const [saveErr,  setSaveErr]  = useState('')

  // Auto-busca se já tiver credenciais salvas
  useEffect(() => {
    if (cfg.wasabiAccessKey && cfg.wasabiSecretKey) fetchBuckets()
  }, []) // eslint-disable-line

  const fetchBuckets = async () => {
    if (!accessKey || !secretKey) return
    setFetchStatus('loading')
    setFetchError('')
    try {
      const res = await api.post<{ buckets: WasabiBucketItem[] }>('/api/storage/wasabi/list-buckets', {
        accessKey, secretKey,
        region:   region   || undefined,
        endpoint: endpoint || undefined,
      })
      setBuckets(res.data.buckets)
      setFetchStatus('ok')
    } catch (err: any) {
      setFetchStatus('error')
      setFetchError(err?.response?.data?.error ?? 'Falha na conexão com a Wasabi')
    }
  }

  const handleCreate = async () => {
    if (!newName.trim()) return
    setCreating(true)
    setCreateErr('')
    try {
      const res = await api.post<{ name: string }>('/api/storage/wasabi/create-bucket', {
        accessKey, secretKey,
        region:   region   || undefined,
        endpoint: endpoint || undefined,
        name: newName.trim(),
      })
      await fetchBuckets()
      setSelectedBucket(res.data.name)
      setNewName('')
    } catch (err: any) {
      setCreateErr(err?.response?.data?.error ?? 'Erro ao criar bucket')
    } finally {
      setCreating(false)
    }
  }

  const handleSave = async () => {
    if (!selectedBucket) { setSaveErr('Selecione um bucket'); return }
    setSaving(true)
    setSaveErr('')
    try {
      const payload: Record<string, string> = {
        wasabiAccessKey: accessKey,
        wasabiSecretKey: secretKey,
        wasabiBucket:    selectedBucket,
      }
      if (region)   payload.wasabiRegion   = region
      if (endpoint) payload.wasabiEndpoint = endpoint
      await api.put(`/api/admin/plugins/${plugin.name}/config`, payload)
      onSaved()
      onClose()
    } catch (err: any) {
      setSaveErr(err?.response?.data?.error ?? 'Erro ao salvar')
    } finally {
      setSaving(false)
    }
  }

  const canFetch = accessKey.length > 0 && secretKey.length > 0

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
      <motion.div
        initial={{ opacity: 0, scale: 0.97, y: 8 }}
        animate={{ opacity: 1, scale: 1,    y: 0 }}
        exit={{    opacity: 0, scale: 0.97, y: 8 }}
        transition={{ duration: 0.18, ease: 'easeOut' }}
        className="bg-[#0d1018] border border-white/10 rounded-2xl w-full max-w-lg shadow-2xl flex flex-col max-h-[90vh]"
      >
        {/* ── Header ── */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-white/[0.07] shrink-0">
          <div className="flex items-center gap-3">
            <div className="w-9 h-9 rounded-xl bg-emerald-500/10 flex items-center justify-center">
              <Database size={17} className="text-emerald-400" />
            </div>
            <div>
              <h2 className="text-white font-bold text-base leading-tight">Wasabi Storage</h2>
              <p className="text-slate-600 text-xs">Armazenamento de mídias do WhatsApp</p>
            </div>
          </div>
          <button
            onClick={onClose}
            className="w-8 h-8 flex items-center justify-center rounded-xl text-slate-600 hover:text-white hover:bg-white/8 transition-colors"
          >
            <XCircle size={16} />
          </button>
        </div>

        {/* ── Body (scrollable) ── */}
        <div className="overflow-y-auto flex-1 px-6 py-5 space-y-5">

          {/* Credenciais */}
          <div className="space-y-3">
            <p className="text-[11px] font-bold text-slate-500 uppercase tracking-widest">Credenciais Wasabi</p>

            <div>
              <label className="flex items-center gap-1 text-xs font-semibold text-slate-400 mb-1.5">
                Access Key <span className="text-red-400">*</span>
                <InfoTooltip text="Chave de acesso pública gerada em Account → Access Keys no painel Wasabi." />
              </label>
              <input
                type="text"
                value={accessKey}
                onChange={e => setAccessKey(e.target.value)}
                placeholder="NK2RNWUWBNGC169FSN1N"
                className="w-full bg-white/[0.04] border border-white/10 rounded-xl px-3 py-2.5 text-sm text-white placeholder-slate-700 focus:outline-none focus:border-emerald-500/40 font-mono transition-colors"
              />
            </div>

            <div>
              <label className="flex items-center gap-1 text-xs font-semibold text-slate-400 mb-1.5">
                Secret Key <span className="text-red-400">*</span>
                <InfoTooltip text="Chave secreta correspondente à Access Key — exibida apenas uma vez no momento da criação no painel Wasabi." />
              </label>
              <div className="relative">
                <input
                  type={showKey ? 'text' : 'password'}
                  value={secretKey}
                  onChange={e => setSecretKey(e.target.value)}
                  placeholder="●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●"
                  className="w-full bg-white/[0.04] border border-white/10 rounded-xl px-3 py-2.5 text-sm text-white placeholder-slate-700 focus:outline-none focus:border-emerald-500/40 font-mono transition-colors pr-10"
                />
                <button
                  type="button"
                  onClick={() => setShowKey(v => !v)}
                  className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-600 hover:text-white transition-colors"
                >
                  {showKey ? <EyeOff size={14} /> : <Eye size={14} />}
                </button>
              </div>
            </div>

            {/* Avançado */}
            <button
              type="button"
              onClick={() => setShowAdvanced(v => !v)}
              className="flex items-center gap-1.5 text-[11px] text-slate-600 hover:text-slate-400 transition-colors"
            >
              <ChevronDown size={12} className={`transition-transform ${showAdvanced ? 'rotate-180' : ''}`} />
              Configurações avançadas (region / endpoint)
            </button>

            {showAdvanced && (
              <div className="space-y-3 pl-1">
                <div>
                  <label className="flex items-center gap-1 text-xs font-semibold text-slate-500 mb-1.5">
                    Região
                    <InfoTooltip text="Selecione a região onde seu bucket foi criado. O endpoint é preenchido automaticamente." />
                  </label>
                  <select
                    value={region}
                    onChange={e => {
                      const r = e.target.value
                      setRegion(r)
                      const ep = WASABI_REGIONS.find(x => x.region === r)?.endpoint ?? ''
                      setEndpoint(ep === 's3.wasabisys.com' ? '' : ep)
                    }}
                    className="w-full bg-white/[0.03] border border-white/8 rounded-xl px-3 py-2 text-sm text-white focus:outline-none focus:border-white/20 font-mono appearance-none"
                  >
                    {WASABI_REGIONS.map(r => (
                      <option key={r.region} value={r.region} className="bg-[#13151f]">
                        {r.region} — {r.label}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className="flex items-center gap-1 text-xs font-semibold text-slate-500 mb-1.5">
                    Endpoint
                    <InfoTooltip text="Preenchido automaticamente ao selecionar a região. Só altere manualmente se necessário." />
                  </label>
                  <div className="flex items-center gap-2">
                    <input
                      type="text"
                      value={endpoint || WASABI_REGIONS.find(x => x.region === region)?.endpoint || 's3.wasabisys.com'}
                      onChange={e => setEndpoint(e.target.value)}
                      className="flex-1 bg-white/[0.03] border border-white/8 rounded-xl px-3 py-2 text-sm text-slate-400 placeholder-slate-700 focus:outline-none focus:border-white/20 font-mono"
                    />
                  </div>
                </div>
              </div>
            )}

            {/* Botão buscar */}
            <button
              type="button"
              onClick={fetchBuckets}
              disabled={!canFetch || fetchStatus === 'loading'}
              className="flex items-center gap-2 px-4 py-2.5 bg-emerald-500/15 hover:bg-emerald-500/25 text-emerald-400 text-sm font-semibold rounded-xl transition-colors disabled:opacity-40 disabled:cursor-not-allowed w-full justify-center"
            >
              {fetchStatus === 'loading'
                ? <><Loader2 size={14} className="animate-spin" /> Conectando...</>
                : <><RefreshCw size={14} /> Buscar Buckets</>
              }
            </button>

            {fetchStatus === 'error' && (
              <div className="flex items-center gap-2 text-red-400 bg-red-500/10 border border-red-500/20 rounded-xl px-3 py-2.5 text-xs">
                <AlertTriangle size={13} />
                {fetchError}
              </div>
            )}
          </div>

          {/* Lista de buckets */}
          {fetchStatus === 'ok' && (
            <div className="space-y-3">
              <p className="text-[11px] font-bold text-slate-500 uppercase tracking-widest">
                Buckets disponíveis
                <span className="ml-2 text-slate-700 font-normal normal-case">— clique para selecionar</span>
              </p>

              {buckets.length === 0 ? (
                <p className="text-slate-600 text-xs text-center py-4">Nenhum bucket encontrado. Crie um abaixo.</p>
              ) : (
                <div className="space-y-1.5">
                  {buckets.map(b => {
                    const active = b.name === selectedBucket
                    return (
                      <button
                        key={b.name}
                        type="button"
                        onClick={() => setSelectedBucket(b.name ?? '')}
                        className={`w-full flex items-center justify-between px-4 py-3 rounded-xl border text-left transition-all ${
                          active
                            ? 'bg-emerald-500/10 border-emerald-500/40 text-emerald-300'
                            : 'bg-white/[0.02] border-white/[0.06] text-slate-300 hover:bg-white/[0.05] hover:border-white/15'
                        }`}
                      >
                        <div className="flex items-center gap-3">
                          <div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center shrink-0 ${active ? 'border-emerald-400' : 'border-slate-600'}`}>
                            {active && <div className="w-2 h-2 rounded-full bg-emerald-400" />}
                          </div>
                          <span className="text-sm font-mono">{b.name}</span>
                        </div>
                        {b.createdAt && (
                          <span className="text-xs text-slate-600 shrink-0 ml-2">
                            {new Date(b.createdAt).toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' })}
                          </span>
                        )}
                      </button>
                    )
                  })}
                </div>
              )}

              {/* Criar novo bucket */}
              <div className="border-t border-white/5 pt-3">
                <p className="text-[11px] font-bold text-slate-500 uppercase tracking-widest mb-2">Criar novo bucket</p>
                <div className="flex gap-2">
                  <input
                    type="text"
                    value={newName}
                    onChange={e => setNewName(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '-'))}
                    onKeyDown={e => e.key === 'Enter' && handleCreate()}
                    placeholder="nome-do-bucket"
                    className="flex-1 bg-white/[0.03] border border-white/8 rounded-xl px-3 py-2 text-sm text-white placeholder-slate-700 focus:outline-none focus:border-white/20 font-mono"
                  />
                  <button
                    type="button"
                    onClick={handleCreate}
                    disabled={creating || !newName.trim()}
                    className="flex items-center gap-1.5 px-4 py-2 bg-white/5 hover:bg-white/10 text-slate-300 text-sm font-semibold rounded-xl transition-colors disabled:opacity-40"
                  >
                    {creating ? <Loader2 size={13} className="animate-spin" /> : <Plus size={13} />}
                    Criar
                  </button>
                </div>
                {createErr && (
                  <p className="text-red-400 text-xs mt-1.5 flex items-center gap-1">
                    <AlertTriangle size={11} /> {createErr}
                  </p>
                )}
              </div>
            </div>
          )}

          {/* Bucket selecionado (feedback) */}
          {selectedBucket && fetchStatus === 'ok' && (
            <div className="flex items-center gap-2 bg-emerald-500/8 border border-emerald-500/20 rounded-xl px-4 py-3">
              <CheckCircle2 size={14} className="text-emerald-400 shrink-0" />
              <div>
                <p className="text-emerald-300 text-xs font-semibold">Bucket ativo selecionado</p>
                <p className="text-emerald-400/70 text-xs font-mono">{selectedBucket}</p>
              </div>
            </div>
          )}

          {saveErr && (
            <div className="flex items-center gap-2 text-red-400 bg-red-500/10 border border-red-500/20 rounded-xl px-3 py-2.5 text-xs">
              <AlertTriangle size={13} />
              {saveErr}
            </div>
          )}
        </div>

        {/* ── Footer ── */}
        <div className="flex items-center justify-between px-6 py-4 border-t border-white/[0.07] shrink-0">
          <p className="text-[11px] text-slate-700">
            {fetchStatus === 'ok'
              ? `${buckets.length} bucket${buckets.length !== 1 ? 's' : ''} encontrado${buckets.length !== 1 ? 's' : ''}`
              : 'Entre as credenciais e clique em Buscar'
            }
          </p>
          <div className="flex gap-2">
            <button
              onClick={onClose}
              className="px-4 py-2 text-sm text-slate-400 hover:text-white transition-colors rounded-xl hover:bg-white/5"
            >
              Cancelar
            </button>
            <button
              onClick={handleSave}
              disabled={saving || !selectedBucket || !accessKey || !secretKey}
              className="flex items-center gap-2 px-4 py-2 bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-300 text-sm font-semibold rounded-xl transition-colors disabled:opacity-40 disabled:cursor-not-allowed border border-emerald-500/20"
            >
              {saving ? <Loader2 size={14} className="animate-spin" /> : <Save size={14} />}
              Salvar
            </button>
          </div>
        </div>
      </motion.div>
    </div>
  )
}

// ─── Wasabi Buckets Panel ─────────────────────────────────────────────────────

interface WasabiBucket {
  name: string
  createdAt?: string
}


// ─── Plugin Card ───────────────────────────────────────────────────────────────

function PluginCard({ plugin, onToggle, onConfigure, toggling }: {
  plugin: Plugin
  onToggle: (name: string, enable: boolean) => void
  onConfigure: (plugin: Plugin) => void
  toggling: string | null
}) {
  const [expanded, setExpanded] = useState(false)
  const hasConfig = plugin.configSchema.length > 0
  const hasHooks = plugin.hooks.subscribes.length > 0 || plugin.hooks.emits.length > 0

  return (
    <div className={`bg-white/[0.03] border rounded-2xl transition-all ${plugin.active ? 'border-white/10' : 'border-white/5 opacity-60'}`}>
      <div className="p-5 flex items-start gap-4">
        {/* Icon */}
        <div className={`w-10 h-10 rounded-xl flex items-center justify-center shrink-0 ${plugin.active ? 'bg-brand-500/15' : 'bg-white/5'}`}>
          <Package size={20} className={plugin.active ? 'text-brand-400' : 'text-slate-500'} />
        </div>

        {/* Info */}
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="text-white font-semibold text-sm">{plugin.displayName}</span>
            <span className="text-slate-600 text-xs">v{plugin.version}</span>
            <span className={`text-xs px-2 py-0.5 rounded-full font-medium ${CATEGORY_COLORS[plugin.category] ?? 'bg-white/5 text-slate-400'}`}>
              {CATEGORY_LABELS[plugin.category] ?? plugin.category}
            </span>
            {!plugin.canDisable && (
              <span className="flex items-center gap-1 text-xs text-slate-500">
                <ShieldCheck size={11} /> Core
              </span>
            )}
          </div>
          <p className="text-slate-500 text-xs mt-1 line-clamp-2">{plugin.description}</p>
          {plugin.dependencies.length > 0 && (
            <p className="text-slate-600 text-xs mt-1">
              Deps: {plugin.dependencies.join(', ')}
            </p>
          )}
        </div>

        {/* Actions */}
        <div className="flex items-center gap-2 shrink-0">
          {hasConfig && (
            <button
              onClick={() => onConfigure(plugin)}
              className="flex items-center gap-1.5 px-3 py-1.5 bg-white/5 hover:bg-white/10 text-slate-300 hover:text-white text-xs font-medium rounded-lg transition-colors"
            >
              <Settings size={13} />
              Config
            </button>
          )}

          {plugin.canDisable && (
            <button
              onClick={() => onToggle(plugin.name, !plugin.active)}
              disabled={toggling === plugin.name}
              className={`relative w-11 h-6 rounded-full transition-colors shrink-0 disabled:opacity-50 ${plugin.active ? 'bg-brand-500' : 'bg-white/10'}`}
            >
              {toggling === plugin.name ? (
                <Loader2 size={12} className="absolute inset-0 m-auto text-white animate-spin" />
              ) : (
                <span className={`absolute top-1 w-4 h-4 rounded-full bg-white transition-all ${plugin.active ? 'left-6' : 'left-1'}`} />
              )}
            </button>
          )}

          {(hasHooks || plugin.hooks) && (
            <button
              onClick={() => setExpanded(e => !e)}
              className="text-slate-500 hover:text-white transition-colors"
            >
              {expanded ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
            </button>
          )}
        </div>
      </div>

      {/* Expanded: hooks info */}
      <AnimatePresence>
        {expanded && hasHooks && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="overflow-hidden"
          >
            <div className="px-5 pb-5 pt-0 border-t border-white/5 mt-0 grid grid-cols-2 gap-4">
              {plugin.hooks.subscribes.length > 0 && (
                <div>
                  <p className="text-xs font-bold text-slate-500 uppercase tracking-widest mb-2">Escuta</p>
                  <div className="flex flex-wrap gap-1">
                    {plugin.hooks.subscribes.map(h => (
                      <span key={h} className="text-xs bg-blue-500/10 text-blue-400 border border-blue-500/20 px-2 py-0.5 rounded-full">{h}</span>
                    ))}
                  </div>
                </div>
              )}
              {plugin.hooks.emits.length > 0 && (
                <div>
                  <p className="text-xs font-bold text-slate-500 uppercase tracking-widest mb-2">Emite</p>
                  <div className="flex flex-wrap gap-1">
                    {plugin.hooks.emits.map(h => (
                      <span key={h} className="text-xs bg-green-500/10 text-green-400 border border-green-500/20 px-2 py-0.5 rounded-full">{h}</span>
                    ))}
                  </div>
                </div>
              )}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  )
}

// ─── Page ─────────────────────────────────────────────────────────────────────

type StorageHealthReason = 'ok' | 'not_configured' | 'needs_restart' | 'auth_error' | 'billing_error' | 'bucket_not_found' | 'network_error' | 'unknown'

interface StorageHealthStatus {
  healthy: boolean
  configured: boolean
  reason: StorageHealthReason
  message: string
}

const STORAGE_ALERT_CONFIG: Record<StorageHealthReason, { color: string; icon: string; label: string }> = {
  ok:              { color: 'border-green-500/30 bg-green-500/10 text-green-300',  icon: '✓', label: 'Wasabi OK' },
  not_configured:  { color: 'border-yellow-500/30 bg-yellow-500/10 text-yellow-300', icon: '⚙', label: 'Wasabi não configurado' },
  needs_restart:   { color: 'border-blue-500/30 bg-blue-500/10 text-blue-300',    icon: '↺', label: 'Reinicialização necessária' },
  auth_error:      { color: 'border-red-500/30 bg-red-500/10 text-red-300',       icon: '✕', label: 'Chaves inválidas' },
  billing_error:   { color: 'border-orange-500/30 bg-orange-500/10 text-orange-300', icon: '!', label: 'Conta Wasabi — verificar pagamento' },
  bucket_not_found:{ color: 'border-red-500/30 bg-red-500/10 text-red-300',       icon: '✕', label: 'Bucket não encontrado' },
  network_error:   { color: 'border-red-500/30 bg-red-500/10 text-red-300',       icon: '✕', label: 'Sem conexão com Wasabi' },
  unknown:         { color: 'border-red-500/30 bg-red-500/10 text-red-300',       icon: '?', label: 'Erro desconhecido' },
}

export default function PluginsPage() {
  const router = useRouter()
  const { user, loading: authLoading } = useAuth()
  const [plugins, setPlugins] = useState<Plugin[]>([])
  const [loading, setLoading] = useState(true)
  const [toggling, setToggling] = useState<string | null>(null)
  const [configPlugin, setConfigPlugin] = useState<Plugin | null>(null)
  const [toast, setToast] = useState<{ msg: string; type: 'ok' | 'err' } | null>(null)
  const [storageHealth, setStorageHealth] = useState<StorageHealthStatus | null>(null)

  useEffect(() => {
    if (!authLoading && user?.role !== 'admin') router.replace('/dashboard')
  }, [authLoading, user, router])

  const fetchStorageHealth = useCallback(async () => {
    try {
      const res = await api.get<StorageHealthStatus>('/api/admin/plugins/storage/health')
      setStorageHealth(res.data)
    } catch {
      // silently ignore — storage health is informational only
    }
  }, [])

  const fetchPlugins = useCallback(async () => {
    try {
      const res = await api.get<Plugin[]>('/api/admin/plugins')
      setPlugins(res.data)
    } catch {
      showToast('Erro ao carregar plugins', 'err')
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    if (!authLoading && user?.role === 'admin') {
      fetchPlugins()
      fetchStorageHealth()
    }
  }, [authLoading, user, fetchPlugins, fetchStorageHealth])

  const showToast = (msg: string, type: 'ok' | 'err') => {
    setToast({ msg, type })
    setTimeout(() => setToast(null), 3500)
  }

  const handleToggle = async (name: string, enable: boolean) => {
    setToggling(name)
    try {
      await api.post(`/api/admin/plugins/${name}/${enable ? 'enable' : 'disable'}`)
      showToast(`Plugin ${enable ? 'ativado' : 'desativado'} com sucesso`, 'ok')
      await fetchPlugins()
    } catch (err: any) {
      showToast(err?.response?.data?.error ?? 'Erro ao alterar plugin', 'err')
    } finally {
      setToggling(null)
    }
  }

  if (authLoading || user?.role !== 'admin') return null

  const activeCount = plugins.filter(p => p.active).length
  const categories = ['core', 'integration', 'business', 'utility']
  return (
    <div className="min-h-screen bg-[#080a0e] text-white p-6 lg:p-8">
      <div className="max-w-4xl mx-auto">
        <div className="flex items-center justify-between mb-8">
          <div>
            <div className="flex items-center gap-3 mb-1">
              <div className="w-9 h-9 rounded-xl bg-brand-500/15 flex items-center justify-center">
                <Plug2 size={18} className="text-brand-400" />
              </div>
              <h1 className="text-2xl font-black text-white">Plugins</h1>
            </div>
            <p className="text-slate-500 text-sm ml-12">
              {activeCount} de {plugins.length} ativos
            </p>
          </div>
          <button
            onClick={fetchPlugins}
            className="flex items-center gap-2 px-3 py-2 bg-white/5 hover:bg-white/10 text-slate-400 hover:text-white text-sm rounded-xl transition-colors"
          >
            <RefreshCw size={14} />
            Atualizar
          </button>
        </div>

        {/* Banner de saúde do storage — visível apenas quando há problema */}
        {storageHealth && storageHealth.reason !== 'ok' && (() => {
          const cfg = STORAGE_ALERT_CONFIG[storageHealth.reason]
          return (
            <div className={`flex items-start gap-3 px-4 py-3 rounded-xl border mb-6 ${cfg.color}`}>
              <span className="text-lg font-bold shrink-0 mt-0.5">{cfg.icon}</span>
              <div className="flex-1 min-w-0">
                <p className="font-bold text-sm">{cfg.label}</p>
                <p className="text-xs mt-0.5 opacity-80">{storageHealth.message}</p>
              </div>
              <button
                onClick={fetchStorageHealth}
                className="shrink-0 text-xs underline opacity-60 hover:opacity-100 transition-opacity mt-0.5"
              >
                Verificar novamente
              </button>
            </div>
          )
        })()}

        {loading ? (
          <div className="flex items-center justify-center py-24">
            <Loader2 size={32} className="text-brand-500 animate-spin" />
          </div>
        ) : (
          <div className="space-y-8">
            {categories.map(cat => {
              const catPlugins = plugins.filter(p => p.category === cat)
              if (catPlugins.length === 0) return null
              return (
                <div key={cat}>
                  <h2 className="text-xs font-black text-slate-500 uppercase tracking-widest mb-3 flex items-center gap-2">
                    <span className={`inline-block w-2 h-2 rounded-full ${cat === 'core' ? 'bg-blue-400' : cat === 'integration' ? 'bg-purple-400' : cat === 'business' ? 'bg-green-400' : 'bg-yellow-400'}`} />
                    {CATEGORY_LABELS[cat]}
                  </h2>
                  <div className="space-y-3">
                    {catPlugins.map(plugin => (
                      <PluginCard
                        key={plugin.name}
                        plugin={plugin}
                        onToggle={handleToggle}
                        onConfigure={setConfigPlugin}
                        toggling={toggling}
                      />
                    ))}
                  </div>
                </div>
              )
            })}

          </div>
        )}
      </div>

      {/* Config Modal */}
      <AnimatePresence>
        {configPlugin && (
          configPlugin.name === 'UnifiedStorageProvider' ? (
            <WasabiStorageModal
              plugin={configPlugin}
              onClose={() => setConfigPlugin(null)}
              onSaved={() => {
                showToast('Configuração salva com sucesso', 'ok')
                fetchPlugins()
              }}
            />
          ) : (
            <ConfigModal
              plugin={configPlugin}
              onClose={() => setConfigPlugin(null)}
              onSaved={() => {
                showToast('Configuração salva com sucesso', 'ok')
                fetchPlugins()
              }}
            />
          )
        )}
      </AnimatePresence>

      {/* Toast */}
      <AnimatePresence>
        {toast && (
          <motion.div
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: 20 }}
            className={`fixed bottom-6 right-6 flex items-center gap-3 px-5 py-3.5 rounded-2xl shadow-2xl text-sm font-semibold z-[100] ${
              toast.type === 'ok'
                ? 'bg-green-500/15 border border-green-500/30 text-green-300'
                : 'bg-red-500/15 border border-red-500/30 text-red-300'
            }`}
          >
            {toast.type === 'ok' ? <CheckCircle2 size={16} /> : <XCircle size={16} />}
            {toast.msg}
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  )
}
