/**
 * Widoki panelu administratora dla modułu marketingowego: Leady + grupy docelowe, Kampanie oraz
 * konfiguracja poczty SMTP i bramki SMS. Wydzielone z App.tsx (monolit 22k linii), aby go nie
 * powiększać. Komponent `Icon` przekazywany jest propem, żeby uniknąć cyklicznego importu.
 */
import { useCallback, useEffect, useState } from 'react';
import { apiFetch } from '../auth';

type IconComponent = (props: { name: string }) => JSX.Element | null;

type LeadSource = 'REGISTERED_USER' | 'MANUAL' | 'IMPORT' | 'FORM';
type LeadStatus = 'NEW' | 'CONTACTED' | 'RESPONDED' | 'UNSUBSCRIBED';

type Lead = {
  id: number;
  name: string | null;
  email: string | null;
  phone: string | null;
  city: string | null;
  source: LeadSource;
  userId: number | null;
  status: LeadStatus;
  tags: string[];
  emailConsent: boolean;
  smsConsent: boolean;
  emailOptOut: boolean;
  smsOptOut: boolean;
  notes: string | null;
  createdAt: string;
};

type TargetGroup = {
  id: number;
  name: string;
  description: string | null;
  sources: LeadSource[];
  city: string | null;
  tag: string | null;
  status: LeadStatus | null;
  requireEmail: boolean;
  requirePhone: boolean;
  requireEmailConsent: boolean;
  requireSmsConsent: boolean;
  memberCount: number;
  createdAt: string;
};

type Channel = 'EMAIL' | 'SMS';
type CampaignStatus = 'DRAFT' | 'SCHEDULED' | 'SENDING' | 'PAUSED' | 'COMPLETED' | 'CANCELLED';

type Campaign = {
  id: number;
  name: string;
  channel: Channel;
  subject: string | null;
  body: string;
  targetGroupId: number;
  scheduledAt: string | null;
  dailyLimit: number;
  status: CampaignStatus;
  sentToday: number;
  createdAt: string;
  createdBy: string | null;
  totalRecipients: number;
  sentCount: number;
};

type CampaignStats = {
  total: number;
  queued: number;
  sent: number;
  delivered: number;
  failed: number;
  bounced: number;
  optedOut: number;
};

const SOURCE_LABEL: Record<LeadSource, string> = {
  REGISTERED_USER: 'Użytkownik',
  MANUAL: 'Ręczny',
  IMPORT: 'Import',
  FORM: 'Formularz',
};

const STATUS_LABEL: Record<LeadStatus, string> = {
  NEW: 'Nowy',
  CONTACTED: 'Kontakt',
  RESPONDED: 'Odpowiedział',
  UNSUBSCRIBED: 'Wypisany',
};

const CAMPAIGN_STATUS_LABEL: Record<CampaignStatus, string> = {
  DRAFT: 'Robocza',
  SCHEDULED: 'Zaplanowana',
  SENDING: 'Wysyłka',
  PAUSED: 'Wstrzymana',
  COMPLETED: 'Zakończona',
  CANCELLED: 'Anulowana',
};

const ALL_SOURCES: LeadSource[] = ['REGISTERED_USER', 'MANUAL', 'IMPORT', 'FORM'];

function errorMessage(err: unknown): string {
  return err instanceof Error ? err.message : 'Wystąpił błąd. Spróbuj ponownie.';
}

/* ============================ LEADY + GRUPY DOCELOWE ============================ */

export function AdminLeadsView({ Icon }: { Icon: IconComponent }) {
  const [section, setSection] = useState<'leads' | 'groups'>('leads');
  return (
    <div className="mkt-wrap">
      <div className="mkt-subnav">
        <button type="button" className={section === 'leads' ? 'active' : ''} onClick={() => setSection('leads')}>
          <Icon name="user" /> Baza leadów
        </button>
        <button type="button" className={section === 'groups' ? 'active' : ''} onClick={() => setSection('groups')}>
          <Icon name="list" /> Grupy docelowe
        </button>
      </div>
      {section === 'leads' ? <LeadsSection Icon={Icon} /> : <TargetGroupsSection Icon={Icon} />}
    </div>
  );
}

function LeadsSection({ Icon }: { Icon: IconComponent }) {
  const [leads, setLeads] = useState<Lead[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [sourceFilter, setSourceFilter] = useState<'' | LeadSource>('');
  const [search, setSearch] = useState('');
  const [busyId, setBusyId] = useState<number | null>(null);

  // Formularz nowego leada.
  const [form, setForm] = useState({ name: '', email: '', phone: '', city: '', tags: '' });
  const [saving, setSaving] = useState(false);

  // Import.
  const [csv, setCsv] = useState('');
  const [importTag, setImportTag] = useState('');
  const [importing, setImporting] = useState(false);
  const [importResult, setImportResult] = useState<string | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const params = new URLSearchParams();
      if (sourceFilter) params.set('source', sourceFilter);
      if (search.trim()) params.set('search', search.trim());
      const data = await apiFetch<Lead[]>(`/admin/leads${params.toString() ? `?${params.toString()}` : ''}`);
      setLeads(data);
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setLoading(false);
    }
  }, [sourceFilter, search]);

  useEffect(() => {
    const timer = setTimeout(load, 200);
    return () => clearTimeout(timer);
  }, [load]);

  const addLead = async () => {
    if (!form.email.trim() && !form.phone.trim()) {
      setError('Podaj co najmniej e-mail lub telefon.');
      return;
    }
    setSaving(true);
    setError(null);
    try {
      await apiFetch<Lead>('/admin/leads', {
        method: 'POST',
        body: JSON.stringify({
          name: form.name.trim() || null,
          email: form.email.trim() || null,
          phone: form.phone.trim() || null,
          city: form.city.trim() || null,
          tags: form.tags.split(',').map((t) => t.trim()).filter(Boolean),
        }),
      });
      setForm({ name: '', email: '', phone: '', city: '', tags: '' });
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setSaving(false);
    }
  };

  const runImport = async () => {
    if (!csv.trim()) return;
    setImporting(true);
    setImportResult(null);
    setError(null);
    try {
      const res = await apiFetch<{ imported: number; skipped: number; messages: string[] }>(
        '/admin/leads/import',
        { method: 'POST', body: JSON.stringify({ csv, defaultTag: importTag.trim() || null }) },
      );
      setImportResult(`Dodano ${res.imported}, pominięto ${res.skipped}.`);
      setCsv('');
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setImporting(false);
    }
  };

  const optOut = async (lead: Lead) => {
    setBusyId(lead.id);
    try {
      await apiFetch(`/admin/leads/${lead.id}`, {
        method: 'PATCH',
        body: JSON.stringify({ emailOptOut: true, smsOptOut: true }),
      });
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setBusyId(null);
    }
  };

  const remove = async (lead: Lead) => {
    setBusyId(lead.id);
    try {
      await apiFetch(`/admin/leads/${lead.id}`, { method: 'DELETE' });
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setBusyId(null);
    }
  };

  return (
    <div className="admin-card mkt-card">
      <div className="admin-card-head">
        <h2>Baza leadów</h2>
        <span className="mkt-count">{leads.length} kontaktów</span>
      </div>

      <div className="mkt-toolbar">
        <div className="mkt-search">
          <Icon name="search" />
          <input
            type="search"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Szukaj po nazwie, e-mailu, telefonie, mieście..."
          />
        </div>
        <select value={sourceFilter} onChange={(e) => setSourceFilter(e.target.value as '' | LeadSource)}>
          <option value="">Wszystkie źródła</option>
          {ALL_SOURCES.map((s) => (
            <option key={s} value={s}>{SOURCE_LABEL[s]}</option>
          ))}
        </select>
      </div>

      <div className="mkt-addrow">
        <input placeholder="Nazwa / imię" value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} />
        <input placeholder="E-mail" value={form.email} onChange={(e) => setForm({ ...form, email: e.target.value })} />
        <input placeholder="Telefon" value={form.phone} onChange={(e) => setForm({ ...form, phone: e.target.value })} />
        <input placeholder="Miasto" value={form.city} onChange={(e) => setForm({ ...form, city: e.target.value })} />
        <input placeholder="Tagi (po przecinku)" value={form.tags} onChange={(e) => setForm({ ...form, tags: e.target.value })} />
        <button type="button" className="admin-btn approve" onClick={addLead} disabled={saving}>
          {saving ? 'Zapisywanie...' : 'Dodaj lead'}
        </button>
      </div>

      {error && <p className="mkt-error">{error}</p>}

      {loading ? (
        <p className="admin-empty">Ładowanie...</p>
      ) : leads.length === 0 ? (
        <p className="admin-empty">Brak leadów. Dodaj kontakt lub zaimportuj listę.</p>
      ) : (
        <div className="mkt-table-scroll">
          <table className="mkt-table">
            <thead>
              <tr>
                <th>Nazwa</th><th>Kontakt</th><th>Miasto</th><th>Źródło</th><th>Status</th><th>Zgody</th><th></th>
              </tr>
            </thead>
            <tbody>
              {leads.map((lead) => (
                <tr key={lead.id}>
                  <td>{lead.name || '—'}</td>
                  <td>
                    <div className="mkt-contact">
                      {lead.email && <span>{lead.email}</span>}
                      {lead.phone && <span className="mkt-muted">{lead.phone}</span>}
                    </div>
                  </td>
                  <td>{lead.city || '—'}</td>
                  <td><span className="mkt-chip">{SOURCE_LABEL[lead.source]}</span></td>
                  <td>{STATUS_LABEL[lead.status]}</td>
                  <td>
                    <div className="mkt-consents">
                      <span className={`mkt-dot ${lead.emailConsent && !lead.emailOptOut ? 'on' : 'off'}`} title="Zgoda e-mail">@</span>
                      <span className={`mkt-dot ${lead.smsConsent && !lead.smsOptOut ? 'on' : 'off'}`} title="Zgoda SMS">SMS</span>
                    </div>
                  </td>
                  <td className="mkt-actions">
                    {!(lead.emailOptOut && lead.smsOptOut) && (
                      <button type="button" title="Wypisz z kampanii" disabled={busyId === lead.id} onClick={() => optOut(lead)}>
                        <Icon name="lock" />
                      </button>
                    )}
                    <button type="button" title="Usuń lead" disabled={busyId === lead.id} onClick={() => remove(lead)}>
                      <Icon name="trash" />
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      <div className="mkt-import">
        <h3><Icon name="document" /> Import kontaktów (CSV)</h3>
        <p className="mkt-muted">Kolumny: <code>nazwa;email;telefon;miasto</code> — jeden kontakt w wierszu, nagłówek opcjonalny.</p>
        <textarea
          rows={4}
          value={csv}
          onChange={(e) => setCsv(e.target.value)}
          placeholder={'Jan Kowalski;jan@example.pl;600100200;Warszawa'}
        />
        <div className="mkt-import-actions">
          <input placeholder="Tag dla importu (opcjonalnie)" value={importTag} onChange={(e) => setImportTag(e.target.value)} />
          <button type="button" className="admin-btn approve" onClick={runImport} disabled={importing || !csv.trim()}>
            {importing ? 'Importowanie...' : 'Importuj'}
          </button>
        </div>
        {importResult && <p className="mkt-ok">{importResult}</p>}
      </div>
    </div>
  );
}

function TargetGroupsSection({ Icon }: { Icon: IconComponent }) {
  const emptyForm = {
    name: '',
    description: '',
    sources: [] as LeadSource[],
    city: '',
    tag: '',
    requireEmail: false,
    requirePhone: false,
    requireEmailConsent: false,
    requireSmsConsent: false,
  };
  const [groups, setGroups] = useState<TargetGroup[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [form, setForm] = useState(emptyForm);
  const [saving, setSaving] = useState(false);
  const [busyId, setBusyId] = useState<number | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      setGroups(await apiFetch<TargetGroup[]>('/admin/target-groups'));
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setLoading(false);
    }
  }, []);

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

  const toggleSource = (s: LeadSource) => {
    setForm((f) => ({
      ...f,
      sources: f.sources.includes(s) ? f.sources.filter((x) => x !== s) : [...f.sources, s],
    }));
  };

  const create = async () => {
    if (!form.name.trim()) {
      setError('Podaj nazwę grupy.');
      return;
    }
    setSaving(true);
    setError(null);
    try {
      await apiFetch<TargetGroup>('/admin/target-groups', {
        method: 'POST',
        body: JSON.stringify({
          name: form.name.trim(),
          description: form.description.trim() || null,
          sources: form.sources,
          city: form.city.trim() || null,
          tag: form.tag.trim() || null,
          requireEmail: form.requireEmail,
          requirePhone: form.requirePhone,
          requireEmailConsent: form.requireEmailConsent,
          requireSmsConsent: form.requireSmsConsent,
        }),
      });
      setForm(emptyForm);
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setSaving(false);
    }
  };

  const remove = async (group: TargetGroup) => {
    setBusyId(group.id);
    try {
      await apiFetch(`/admin/target-groups/${group.id}`, { method: 'DELETE' });
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setBusyId(null);
    }
  };

  return (
    <div className="mkt-grid-2">
      <div className="admin-card mkt-card">
        <div className="admin-card-head"><h2>Nowa grupa docelowa</h2></div>
        <p className="mkt-muted">Grupa to dynamiczny segment — odbiorcy wyliczają się na bieżąco z kryteriów.</p>
        <div className="mkt-form">
          <label>Nazwa
            <input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="np. Deweloperzy Warszawa" />
          </label>
          <label>Opis
            <input value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} placeholder="Opcjonalny opis" />
          </label>
          <fieldset className="mkt-fieldset">
            <legend>Źródła (puste = wszystkie)</legend>
            <div className="mkt-checks">
              {ALL_SOURCES.map((s) => (
                <label key={s} className="mkt-check">
                  <input type="checkbox" checked={form.sources.includes(s)} onChange={() => toggleSource(s)} />
                  {SOURCE_LABEL[s]}
                </label>
              ))}
            </div>
          </fieldset>
          <div className="mkt-form-row">
            <label>Miasto
              <input value={form.city} onChange={(e) => setForm({ ...form, city: e.target.value })} placeholder="dowolne" />
            </label>
            <label>Tag
              <input value={form.tag} onChange={(e) => setForm({ ...form, tag: e.target.value })} placeholder="dowolny" />
            </label>
          </div>
          <div className="mkt-checks mkt-checks-col">
            <label className="mkt-check"><input type="checkbox" checked={form.requireEmail} onChange={(e) => setForm({ ...form, requireEmail: e.target.checked })} /> Wymagany e-mail</label>
            <label className="mkt-check"><input type="checkbox" checked={form.requirePhone} onChange={(e) => setForm({ ...form, requirePhone: e.target.checked })} /> Wymagany telefon</label>
            <label className="mkt-check"><input type="checkbox" checked={form.requireEmailConsent} onChange={(e) => setForm({ ...form, requireEmailConsent: e.target.checked })} /> Tylko ze zgodą e-mail</label>
            <label className="mkt-check"><input type="checkbox" checked={form.requireSmsConsent} onChange={(e) => setForm({ ...form, requireSmsConsent: e.target.checked })} /> Tylko ze zgodą SMS</label>
          </div>
          {error && <p className="mkt-error">{error}</p>}
          <button type="button" className="admin-btn approve" onClick={create} disabled={saving}>
            {saving ? 'Zapisywanie...' : 'Utwórz grupę'}
          </button>
        </div>
      </div>

      <div className="admin-card mkt-card">
        <div className="admin-card-head">
          <h2>Grupy docelowe</h2>
          <span className="mkt-count">{groups.length}</span>
        </div>
        {loading ? (
          <p className="admin-empty">Ładowanie...</p>
        ) : groups.length === 0 ? (
          <p className="admin-empty">Brak grup. Utwórz pierwszy segment.</p>
        ) : (
          <ul className="mkt-list">
            {groups.map((g) => (
              <li key={g.id}>
                <div>
                  <strong>{g.name}</strong>
                  {g.description && <span className="mkt-muted"> — {g.description}</span>}
                  <div className="mkt-group-meta">
                    <span className="mkt-badge">{g.memberCount} odbiorców</span>
                    {g.sources.length > 0 && <span className="mkt-muted">{g.sources.map((s) => SOURCE_LABEL[s]).join(', ')}</span>}
                    {g.city && <span className="mkt-muted">miasto: {g.city}</span>}
                    {g.requireEmailConsent && <span className="mkt-muted">zgoda e-mail</span>}
                    {g.requireSmsConsent && <span className="mkt-muted">zgoda SMS</span>}
                  </div>
                </div>
                <button type="button" className="mkt-icon-btn" title="Usuń grupę" disabled={busyId === g.id} onClick={() => remove(g)}>
                  <Icon name="trash" />
                </button>
              </li>
            ))}
          </ul>
        )}
      </div>
    </div>
  );
}

/* ============================ KAMPANIE ============================ */

export function AdminCampaignsView({ Icon }: { Icon: IconComponent }) {
  const [campaigns, setCampaigns] = useState<Campaign[]>([]);
  const [groups, setGroups] = useState<TargetGroup[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [busyId, setBusyId] = useState<number | null>(null);
  const [statsFor, setStatsFor] = useState<{ id: number; stats: CampaignStats } | null>(null);

  const empty = { name: '', channel: 'EMAIL' as Channel, subject: '', body: '', targetGroupId: '', dailyLimit: 200, scheduledAt: '' };
  const [form, setForm] = useState(empty);
  const [saving, setSaving] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const [c, g] = await Promise.all([
        apiFetch<Campaign[]>('/admin/campaigns'),
        apiFetch<TargetGroup[]>('/admin/target-groups'),
      ]);
      setCampaigns(c);
      setGroups(g);
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setLoading(false);
    }
  }, []);

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

  const create = async () => {
    if (!form.name.trim() || !form.body.trim() || !form.targetGroupId) {
      setError('Uzupełnij nazwę, treść i grupę docelową.');
      return;
    }
    if (form.channel === 'EMAIL' && !form.subject.trim()) {
      setError('Kampania e-mail wymaga tematu.');
      return;
    }
    setSaving(true);
    setError(null);
    try {
      await apiFetch<Campaign>('/admin/campaigns', {
        method: 'POST',
        body: JSON.stringify({
          name: form.name.trim(),
          channel: form.channel,
          subject: form.channel === 'EMAIL' ? form.subject.trim() : null,
          body: form.body,
          targetGroupId: Number(form.targetGroupId),
          dailyLimit: Number(form.dailyLimit) || 1,
          scheduledAt: form.scheduledAt ? new Date(form.scheduledAt).toISOString() : null,
        }),
      });
      setForm(empty);
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setSaving(false);
    }
  };

  const action = async (id: number, path: string) => {
    setBusyId(id);
    setError(null);
    try {
      await apiFetch(`/admin/campaigns/${id}/${path}`, { method: 'POST' });
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setBusyId(null);
    }
  };

  const remove = async (id: number) => {
    setBusyId(id);
    try {
      await apiFetch(`/admin/campaigns/${id}`, { method: 'DELETE' });
      if (statsFor?.id === id) setStatsFor(null);
      await load();
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setBusyId(null);
    }
  };

  const showStats = async (id: number) => {
    try {
      const stats = await apiFetch<CampaignStats>(`/admin/campaigns/${id}/stats`);
      setStatsFor({ id, stats });
    } catch (err) {
      setError(errorMessage(err));
    }
  };

  return (
    <div className="mkt-grid-2">
      <div className="admin-card mkt-card">
        <div className="admin-card-head"><h2>Nowa kampania</h2></div>
        <div className="mkt-form">
          <label>Nazwa
            <input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="np. Newsletter lipiec" />
          </label>
          <div className="mkt-form-row">
            <label>Kanał
              <select value={form.channel} onChange={(e) => setForm({ ...form, channel: e.target.value as Channel })}>
                <option value="EMAIL">E-mail</option>
                <option value="SMS">SMS</option>
              </select>
            </label>
            <label>Grupa docelowa
              <select value={form.targetGroupId} onChange={(e) => setForm({ ...form, targetGroupId: e.target.value })}>
                <option value="">— wybierz —</option>
                {groups.map((g) => (
                  <option key={g.id} value={g.id}>{g.name} ({g.memberCount})</option>
                ))}
              </select>
            </label>
          </div>
          {form.channel === 'EMAIL' && (
            <label>Temat
              <input value={form.subject} onChange={(e) => setForm({ ...form, subject: e.target.value })} placeholder="Temat wiadomości" />
            </label>
          )}
          <label>Treść <span className="mkt-muted">(użyj {'{{name}}'} dla personalizacji; stopka z rezygnacją dodawana automatycznie)</span>
            <textarea rows={5} value={form.body} onChange={(e) => setForm({ ...form, body: e.target.value })} placeholder="Cześć {{name}}, ..." />
          </label>
          <div className="mkt-form-row">
            <label>Dzienny limit
              <input type="number" min={1} value={form.dailyLimit} onChange={(e) => setForm({ ...form, dailyLimit: Number(e.target.value) })} />
            </label>
            <label>Zaplanuj na (opcjonalnie)
              <input type="datetime-local" value={form.scheduledAt} onChange={(e) => setForm({ ...form, scheduledAt: e.target.value })} />
            </label>
          </div>
          {error && <p className="mkt-error">{error}</p>}
          <button type="button" className="admin-btn approve" onClick={create} disabled={saving}>
            {saving ? 'Zapisywanie...' : 'Utwórz kampanię (robocza)'}
          </button>
        </div>
      </div>

      <div className="admin-card mkt-card">
        <div className="admin-card-head">
          <h2>Kampanie</h2>
          <span className="mkt-count">{campaigns.length}</span>
        </div>
        {loading ? (
          <p className="admin-empty">Ładowanie...</p>
        ) : campaigns.length === 0 ? (
          <p className="admin-empty">Brak kampanii.</p>
        ) : (
          <ul className="mkt-list">
            {campaigns.map((c) => (
              <li key={c.id} className="mkt-campaign">
                <div>
                  <strong>{c.name}</strong>
                  <span className={`mkt-status mkt-status-${c.status.toLowerCase()}`}>{CAMPAIGN_STATUS_LABEL[c.status]}</span>
                  <div className="mkt-group-meta">
                    <span className="mkt-chip">{c.channel === 'EMAIL' ? 'E-mail' : 'SMS'}</span>
                    <span className="mkt-muted">{c.sentCount}/{c.totalRecipients} wysłanych</span>
                    <span className="mkt-muted">limit/dzień: {c.dailyLimit}</span>
                  </div>
                  {statsFor?.id === c.id && (
                    <div className="mkt-stats">
                      w kolejce: {statsFor.stats.queued} · wysłane: {statsFor.stats.sent} · dostarczone: {statsFor.stats.delivered} · błędy: {statsFor.stats.failed}
                    </div>
                  )}
                </div>
                <div className="mkt-campaign-actions">
                  {(c.status === 'DRAFT' || c.status === 'PAUSED') && (
                    <button type="button" className="admin-btn approve" disabled={busyId === c.id} onClick={() => action(c.id, 'schedule')}>
                      Uruchom
                    </button>
                  )}
                  {(c.status === 'SENDING' || c.status === 'SCHEDULED') && (
                    <button type="button" className="admin-btn" disabled={busyId === c.id} onClick={() => action(c.id, 'pause')}>
                      Wstrzymaj
                    </button>
                  )}
                  <button type="button" className="mkt-icon-btn" title="Statystyki" onClick={() => showStats(c.id)}><Icon name="chart" /></button>
                  <button type="button" className="mkt-icon-btn" title="Usuń" disabled={busyId === c.id} onClick={() => remove(c.id)}><Icon name="trash" /></button>
                </div>
              </li>
            ))}
          </ul>
        )}
      </div>
    </div>
  );
}

/* ============================ KONFIGURACJA SMTP + SMS ============================ */

type SmtpConfig = {
  host: string | null;
  port: number | null;
  sslEnabled: boolean;
  username: string | null;
  fromName: string | null;
  contactFormRecipient: string | null;
  enabled: boolean;
  passwordSet: boolean;
};

type SmsConfig = {
  endpointUrl: string | null;
  creator: string | null;
  timeoutSeconds: number | null;
  enabled: boolean;
  apiKeySet: boolean;
};

export function AdminMailConfigView({ Icon }: { Icon: IconComponent }) {
  return (
    <div className="mkt-wrap">
      <SmtpCard Icon={Icon} />
      <SmsCard Icon={Icon} />
    </div>
  );
}

function SmtpCard({ Icon }: { Icon: IconComponent }) {
  const [config, setConfig] = useState<SmtpConfig | null>(null);
  const [password, setPassword] = useState('');
  const [saving, setSaving] = useState(false);
  const [note, setNote] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [testTo, setTestTo] = useState('');
  const [testing, setTesting] = useState(false);
  const [testResult, setTestResult] = useState<string | null>(null);

  const load = useCallback(async () => {
    try {
      setConfig(await apiFetch<SmtpConfig>('/admin/mail-config/smtp'));
    } catch (err) {
      setError(errorMessage(err));
    }
  }, []);
  useEffect(() => { load(); }, [load]);

  if (!config) return <div className="admin-card mkt-card"><p className="admin-empty">Ładowanie konfiguracji SMTP...</p></div>;

  const set = (patch: Partial<SmtpConfig>) => setConfig({ ...config, ...patch });

  const save = async () => {
    setSaving(true);
    setNote(null);
    setError(null);
    try {
      const updated = await apiFetch<SmtpConfig>('/admin/mail-config/smtp', {
        method: 'PUT',
        body: JSON.stringify({
          host: config.host,
          port: config.port,
          sslEnabled: config.sslEnabled,
          username: config.username,
          fromName: config.fromName,
          contactFormRecipient: config.contactFormRecipient,
          enabled: config.enabled,
          password: password || null,
        }),
      });
      setConfig(updated);
      setPassword('');
      setNote('Zapisano ustawienia SMTP.');
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setSaving(false);
    }
  };

  const test = async () => {
    if (!testTo.trim()) return;
    setTesting(true);
    setTestResult(null);
    try {
      const res = await apiFetch<{ ok: boolean; error: string | null }>('/admin/mail-config/smtp/test', {
        method: 'POST',
        body: JSON.stringify({ recipient: testTo.trim() }),
      });
      setTestResult(res.ok ? 'Wiadomość testowa wysłana.' : `Błąd: ${res.error}`);
    } catch (err) {
      setTestResult(`Błąd: ${errorMessage(err)}`);
    } finally {
      setTesting(false);
    }
  };

  return (
    <div className="admin-card mkt-card mkt-config">
      <div className="admin-card-head mkt-config-head">
        <span className="mkt-config-icon"><Icon name="mail" /></span>
        <h2>Konto e-mail (SMTP)</h2>
      </div>
      <div className="mkt-config-grid">
        <label>Adres odbiorcy wiadomości z formularza kontaktowego
          <input value={config.contactFormRecipient ?? ''} onChange={(e) => set({ contactFormRecipient: e.target.value })} placeholder="np. kontakt@twojadomena.pl" />
        </label>
        <label>Wyświetlana nazwa nadawcy
          <input value={config.fromName ?? ''} onChange={(e) => set({ fromName: e.target.value })} placeholder="np. Marketing" />
        </label>
        <label>Serwer SMTP
          <input value={config.host ?? ''} onChange={(e) => set({ host: e.target.value })} placeholder="np. smtp.twojadomena.pl" />
        </label>
        <label>Hasło do konta e-mail {config.passwordSet && <span className="mkt-badge-set"><Icon name="lock" /> ustawione</span>}
          <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="wpisz, aby zmienić" />
        </label>
        <label>Port SMTP (465 = SSL)
          <input type="number" value={config.port ?? ''} onChange={(e) => set({ port: e.target.value ? Number(e.target.value) : null })} placeholder="465" />
        </label>
        <label>Użyj SSL dla połączenia SMTP
          <select value={config.sslEnabled ? 'on' : 'off'} onChange={(e) => set({ sslEnabled: e.target.value === 'on' })}>
            <option value="on">Włączone</option>
            <option value="off">Wyłączone</option>
          </select>
        </label>
        <label>Login SMTP / adres nadawcy
          <input value={config.username ?? ''} onChange={(e) => set({ username: e.target.value })} placeholder="np. marketing@twojadomena.pl" />
        </label>
        <label>Wysyłka kampanii e-mail aktywna
          <select value={config.enabled ? 'on' : 'off'} onChange={(e) => set({ enabled: e.target.value === 'on' })}>
            <option value="off">Wyłączone (sandbox)</option>
            <option value="on">Włączone</option>
          </select>
        </label>
      </div>
      {error && <p className="mkt-error">{error}</p>}
      {note && <p className="mkt-ok">{note}</p>}
      <div className="mkt-config-save">
        <button type="button" className="admin-btn approve" onClick={save} disabled={saving}>
          {saving ? 'Zapisywanie...' : 'Zapisz ustawienia'}
        </button>
      </div>
      <div className="mkt-test">
        <h3>Test konfiguracji</h3>
        <div className="mkt-test-row">
          <input value={testTo} onChange={(e) => setTestTo(e.target.value)} placeholder="Adres e-mail do testu" />
          <button type="button" className="admin-btn" onClick={test} disabled={testing || !testTo.trim()}>
            <Icon name="mail" /> {testing ? 'Wysyłanie...' : 'Wyślij (e-mail)'}
          </button>
        </div>
        {testResult && <p className={testResult.startsWith('Błąd') ? 'mkt-error' : 'mkt-ok'}>{testResult}</p>}
      </div>
    </div>
  );
}

function SmsCard({ Icon }: { Icon: IconComponent }) {
  const [config, setConfig] = useState<SmsConfig | null>(null);
  const [apiKey, setApiKey] = useState('');
  const [saving, setSaving] = useState(false);
  const [note, setNote] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [testTo, setTestTo] = useState('');
  const [testing, setTesting] = useState(false);
  const [testResult, setTestResult] = useState<string | null>(null);

  const load = useCallback(async () => {
    try {
      setConfig(await apiFetch<SmsConfig>('/admin/mail-config/sms'));
    } catch (err) {
      setError(errorMessage(err));
    }
  }, []);
  useEffect(() => { load(); }, [load]);

  if (!config) return <div className="admin-card mkt-card"><p className="admin-empty">Ładowanie konfiguracji SMS...</p></div>;

  const set = (patch: Partial<SmsConfig>) => setConfig({ ...config, ...patch });

  const save = async () => {
    setSaving(true);
    setNote(null);
    setError(null);
    try {
      const updated = await apiFetch<SmsConfig>('/admin/mail-config/sms', {
        method: 'PUT',
        body: JSON.stringify({
          endpointUrl: config.endpointUrl,
          creator: config.creator,
          timeoutSeconds: config.timeoutSeconds,
          enabled: config.enabled,
          apiKey: apiKey || null,
        }),
      });
      setConfig(updated);
      setApiKey('');
      setNote('Zapisano ustawienia bramki SMS.');
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setSaving(false);
    }
  };

  const test = async () => {
    if (!testTo.trim()) return;
    setTesting(true);
    setTestResult(null);
    try {
      const res = await apiFetch<{ ok: boolean; error: string | null }>('/admin/mail-config/sms/test', {
        method: 'POST',
        body: JSON.stringify({ recipient: testTo.trim() }),
      });
      setTestResult(res.ok ? 'SMS testowy wysłany.' : `Błąd: ${res.error}`);
    } catch (err) {
      setTestResult(`Błąd: ${errorMessage(err)}`);
    } finally {
      setTesting(false);
    }
  };

  return (
    <div className="admin-card mkt-card mkt-config">
      <div className="admin-card-head mkt-config-head">
        <span className="mkt-config-icon"><Icon name="message" /></span>
        <h2>Bramka SMS</h2>
      </div>
      <div className="mkt-config-grid">
        <label>Klucz API bramki SMS {config.apiKeySet && <span className="mkt-badge-set"><Icon name="lock" /> ustawione</span>}
          <input type="password" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="wpisz, aby zmienić" />
        </label>
        <label>Znacznik źródła wiadomości (pole creator, max 50 znaków)
          <input maxLength={50} value={config.creator ?? ''} onChange={(e) => set({ creator: e.target.value })} placeholder="np. Marketing" />
        </label>
        <label>Czy wysyłka SMS jest aktywna
          <select value={config.enabled ? 'on' : 'off'} onChange={(e) => set({ enabled: e.target.value === 'on' })}>
            <option value="off">Wyłączone (sandbox)</option>
            <option value="on">Włączone</option>
          </select>
        </label>
        <label>Pełny URL endpointu bramki SMS
          <input value={config.endpointUrl ?? ''} onChange={(e) => set({ endpointUrl: e.target.value })} placeholder="https://api.softspm.pl/send_sms_api.php" />
        </label>
        <label>Timeout żądania HTTP do bramki (s)
          <input type="number" value={config.timeoutSeconds ?? ''} onChange={(e) => set({ timeoutSeconds: e.target.value ? Number(e.target.value) : null })} placeholder="10" />
        </label>
      </div>
      {error && <p className="mkt-error">{error}</p>}
      {note && <p className="mkt-ok">{note}</p>}
      <div className="mkt-config-save">
        <button type="button" className="admin-btn approve" onClick={save} disabled={saving}>
          {saving ? 'Zapisywanie...' : 'Zapisz ustawienia'}
        </button>
      </div>
      <div className="mkt-test">
        <h3>Test konfiguracji</h3>
        <div className="mkt-test-row">
          <input value={testTo} onChange={(e) => setTestTo(e.target.value)} placeholder="Numer telefonu do testu" />
          <button type="button" className="admin-btn" onClick={test} disabled={testing || !testTo.trim()}>
            <Icon name="message" /> {testing ? 'Wysyłanie...' : 'Wyślij (SMS)'}
          </button>
        </div>
        {testResult && <p className={testResult.startsWith('Błąd') ? 'mkt-error' : 'mkt-ok'}>{testResult}</p>}
      </div>
    </div>
  );
}
