/* Shared components & utilities */
const { useState, useEffect, useRef, useMemo, createContext, useContext } = React;

/* -------- Router (hash-based) -------- */

const RouterContext = createContext({ path: '/', go: () => {} });

function RouterProvider({ children }) {
  const [path, setPath] = useState(() => (window.location.hash.replace('#', '') || '/'));

  useEffect(() => {
    const onHash = () => setPath(window.location.hash.replace('#', '') || '/');
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);

  const go = (to) => {
    window.location.hash = to;
    window.scrollTo({ top: 0, behavior: 'instant' });
  };

  return (
    <RouterContext.Provider value={{ path, go }}>
      {children}
    </RouterContext.Provider>
  );
}

function useRouter() { return useContext(RouterContext); }

/* -------- Date helpers -------- */

function pad2(n) { return String(n).padStart(2, '0'); }
function fmtDate(d) { return `${pad2(d.getDate())}.${pad2(d.getMonth() + 1)}.${d.getFullYear()}`; }
function addMonths(d, m) { const x = new Date(d); x.setMonth(x.getMonth() + m); return x; }
function addDays(d, n) { const x = new Date(d); x.setDate(x.getDate() + n); return x; }

/* Parse a free-text block of domains (newline / comma / space / semicolon separated),
   normalise them (strip protocol, path, www) and de-duplicate. */
function parseDomains(text) {
  const raw = (text || '')
    .split(/[\s,;]+/)
    .map((s) => s.trim().toLowerCase())
    .filter(Boolean)
    .map((s) => s.replace(/^https?:\/\//, '').replace(/\/.*$/, '').replace(/^www\./, ''));
  const seen = new Set();
  const valid = [];
  const invalid = [];
  const domainRe = /^(?=.{1,253}$)([a-z0-9-]{1,63}\.)+[a-z]{2,}$/;
  for (const d of raw) {
    if (seen.has(d)) continue;
    seen.add(d);
    (domainRe.test(d) ? valid : invalid).push(d);
  }
  return { valid, invalid };
}

function Link({ to, children, className, onClick, ...rest }) {
  const { go } = useRouter();
  return (
    <a
      href={'#' + to}
      className={className}
      onClick={(e) => {
        e.preventDefault();
        if (onClick) onClick(e);
        go(to);
      }}
      {...rest}
    >
      {children}
    </a>
  );
}

/* -------- App state (auth + orders + tickets) -------- */

const AppStateContext = createContext(null);

const DEMO_ORDERS = [
  {
    id: 'CG-2025-0418',
    domain: 'meine-firma.de',
    product: 'Let\'s Encrypt SSL Einrichtungs- & Überwachungsservice',
    term: 12,
    start: '18.04.2025',
    end: '17.04.2026',
    status: 'aktiv',
    autoRenew: true,
    lastCheck: '04.05.2026',
    nextCheck: '12.08.2026',
    daysUntilExpiry: 340,
    price: 14.50,
  },
  {
    id: 'CG-2024-1102',
    domain: 'shop.handwerk-mueller.de',
    product: 'Let\'s Encrypt SSL Einrichtungs- & Überwachungsservice',
    term: 24,
    start: '02.11.2024',
    end: '01.11.2026',
    status: 'aktiv',
    autoRenew: false,
    lastCheck: '28.04.2026',
    nextCheck: '06.08.2026',
    daysUntilExpiry: 538,
    price: 14.50,
  },
  {
    id: 'CG-2025-0612',
    domain: 'praxis-bergmann.com',
    product: 'Let\'s Encrypt SSL Einrichtungs- & Überwachungsservice',
    term: 12,
    start: '12.06.2025',
    end: '11.06.2026',
    status: 'in Bearbeitung',
    autoRenew: true,
    lastCheck: '—',
    nextCheck: '—',
    daysUntilExpiry: 30,
    price: 14.50,
  },
];

const DEMO_INVOICES = [
  { id: 'RE-2025-00418', date: '18.04.2025', amount: 14.50, order: 'CG-2025-0418', status: 'bezahlt', method: 'Kreditkarte' },
  { id: 'RE-2024-01102', date: '02.11.2024', amount: 29.00, order: 'CG-2024-1102', status: 'bezahlt', method: 'Kreditkarte' },
  { id: 'RE-2025-00612', date: '12.06.2025', amount: 14.50, order: 'CG-2025-0612', status: 'bezahlt', method: 'Kreditkarte' },
];

const DEMO_TICKETS = [
  {
    id: 'TCK-2041',
    subject: 'Frage zur DNS-Konfiguration bei IONOS',
    category: 'SSL-Einrichtung',
    status: 'beantwortet',
    domain: 'meine-firma.de',
    updated: '08.05.2026',
    messages: [
      { from: 'Sie', date: '06.05.2026 14:22', body: 'Hallo, ich habe einen CNAME bei IONOS gesetzt, aber die ACME-Challenge schlägt fehl. Können Sie kurz prüfen?' },
      { from: 'Support', date: '07.05.2026 09:11', body: 'Hallo, vielen Dank für Ihre Anfrage. Wir haben den DNS-Eintrag geprüft – der CNAME zeigt aktuell auf eine ältere Verifizierung. Bitte ergänzen Sie zusätzlich den TXT-Record _acme-challenge.meine-firma.de mit dem im Anhang genannten Wert. Anschließend führen wir die Prüfung erneut aus.' },
      { from: 'Sie', date: '08.05.2026 08:30', body: 'Perfekt, TXT-Record gesetzt. Können Sie nochmal prüfen?' },
      { from: 'Support', date: '08.05.2026 10:02', body: 'Die Prüfung war erfolgreich. Das Zertifikat ist aktiv und korrekt eingebunden. Die nächste turnusmäßige Kontrolle erfolgt automatisch in ca. 40 Tagen.' },
    ],
  },
  {
    id: 'TCK-2038',
    subject: 'Rechnungsadresse aktualisieren',
    category: 'Rechnung / Zahlung',
    status: 'geschlossen',
    domain: '—',
    updated: '02.05.2026',
    messages: [],
  },
  {
    id: 'TCK-2045',
    subject: 'Verlängerung deaktivieren bestätigen',
    category: 'Kündigung / Verlängerung',
    status: 'offen',
    domain: 'shop.handwerk-mueller.de',
    updated: '10.05.2026',
    messages: [],
  },
];

const EMPTY_USER = {
  loggedIn: false, id: null, email: '',
  first: '', last: '', phone: '', customerType: 'company',
  street: '', zip: '', city: '', country: 'Deutschland',
  company: { name: '', form: 'GmbH', vat: '', addr: '', contact: '' },
};

function mapProfileToUser(session, profile) {
  const p = profile || {};
  const first = p.first_name || '';
  const last = p.last_name || '';
  return {
    loggedIn: true,
    id: session.user.id,
    email: p.email || session.user.email || '',
    first, last,
    phone: p.phone || '',
    customerType: p.customer_type || 'company',
    street: p.street || '', zip: p.zip || '', city: p.city || '',
    country: p.country || 'Deutschland',
    company: {
      name: p.company_name || '',
      form: p.company_form || 'GmbH',
      vat: p.vat_id || '',
      addr: [p.street, [p.zip, p.city].filter(Boolean).join(' ')].filter(Boolean).join(', '),
      contact: [first, last].filter(Boolean).join(' '),
    },
  };
}

function mapOrder(row) {
  const d = (v) => v ? fmtDate(new Date(v)) : '—';
  return {
    id: row.order_no || row.id, _uuid: row.id,
    domain: row.domain, product: row.product, term: row.term_months,
    status: row.status, autoRenew: row.auto_renew,
    start: d(row.start_date), end: d(row.end_date),
    lastCheck: d(row.last_check), nextCheck: d(row.next_check),
    price: row.price,
  };
}

function mapTicket(row) {
  const date = row.created_at ? fmtDate(new Date(row.created_at)) : '';
  return {
    id: row.ticket_no || row.id, _uuid: row.id,
    subject: row.subject, category: row.category, status: row.status,
    domain: row.domain || '—', updated: date,
    messages: row.message ? [{ from: 'Sie', date, body: row.message }] : [],
  };
}

function AppStateProvider({ children }) {
  const sb = window.sb;
  const [user, setUser] = useState(EMPTY_USER);
  const [authReady, setAuthReady] = useState(false);
  const [orders, setOrders] = useState([]);
  const [tickets, setTickets] = useState([]);
  const [invoices] = useState([]); // Rechnungen kommen spaeter aus Stripe
  const [toast, setToast] = useState(null);

  const showToast = (msg) => { setToast(msg); setTimeout(() => setToast(null), 2600); };

  const reloadOrders = async () => {
    if (!sb) return;
    const { data } = await sb.from('orders').select('*').order('created_at', { ascending: false });
    setOrders((data || []).map(mapOrder));
  };
  const reloadTickets = async () => {
    if (!sb) return;
    const { data } = await sb.from('support_tickets').select('*').order('created_at', { ascending: false });
    setTickets((data || []).map(mapTicket));
  };

  const loadSession = async (session) => {
    if (!session) { setUser(EMPTY_USER); setOrders([]); setTickets([]); return; }
    let profile = null;
    try {
      const res = await sb.from('profiles').select('*').eq('id', session.user.id).maybeSingle();
      profile = res.data;
    } catch (e) { /* ignore */ }
    setUser(mapProfileToUser(session, profile));
    await reloadOrders();
    await reloadTickets();
  };

  useEffect(() => {
    if (!sb) { setAuthReady(true); return; }
    let mounted = true;
    sb.auth.getSession().then(({ data }) => {
      if (!mounted) return;
      loadSession(data.session).finally(() => setAuthReady(true));
    });
    const { data: sub } = sb.auth.onAuthStateChange((_event, session) => { loadSession(session); });
    return () => { mounted = false; if (sub && sub.subscription) sub.subscription.unsubscribe(); };
  }, []);

  // --- Auth (passwortloser E-Mail-Code) ---
  const sendLoginCode = (email) =>
    sb.auth.signInWithOtp({ email, options: { shouldCreateUser: false } });

  const registerCompany = (payload) => {
    sessionStorage.setItem('cg.authEmail', payload.email);
    sessionStorage.setItem('cg.pendingProfile', JSON.stringify(payload));
    return sb.auth.signInWithOtp({ email: payload.email, options: { shouldCreateUser: true } });
  };

  const resendCode = (email) => {
    const isRegister = !!sessionStorage.getItem('cg.pendingProfile');
    return sb.auth.signInWithOtp({ email, options: { shouldCreateUser: isRegister } });
  };

  const verifyCode = async (email, token) => {
    const pending = sessionStorage.getItem('cg.pendingProfile');
    // Registrierung -> 'signup'-Code, Login -> 'email'-Code; beide Reihenfolgen probieren
    const types = pending ? ['signup', 'email'] : ['email', 'signup'];
    let res = { error: { message: 'Code ungültig oder abgelaufen.' } };
    for (const t of types) {
      res = await sb.auth.verifyOtp({ email, token, type: t });
      if (!res.error) break;
    }
    if (res.error) return res;
    if (pending && res.data && res.data.user) {
      try {
        const p = JSON.parse(pending);
        await sb.from('profiles').upsert({
          id: res.data.user.id,
          email: p.email, first_name: p.first, last_name: p.last, phone: p.phone || null,
          customer_type: 'company', company_name: p.companyName, company_form: p.form,
          vat_id: p.vat || null, street: p.street, zip: p.zip, city: p.city, country: p.country,
          updated_at: new Date().toISOString(),
        }, { onConflict: 'id' });
      } catch (e) { /* ignore */ }
      sessionStorage.removeItem('cg.pendingProfile');
    }
    sessionStorage.removeItem('cg.authEmail');
    // Session direkt laden, damit das Dashboard sofort die richtigen Daten zeigt
    if (res.data && res.data.session) await loadSession(res.data.session);
    return res;
  };

  const signOut = async () => {
    if (sb) await sb.auth.signOut();
    setUser(EMPTY_USER); setOrders([]); setTickets([]);
  };

  // --- Profil ---
  const updateProfile = async (next) => {
    if (!user.id) return;
    await sb.from('profiles').update({
      first_name: next.first, last_name: next.last, email: next.email, phone: next.phone || null,
      street: next.street, zip: next.zip, city: next.city, country: next.country,
      updated_at: new Date().toISOString(),
    }).eq('id', user.id);
    setUser((u) => ({ ...u, ...next }));
    showToast('Kundendaten gespeichert.');
  };
  const updateCompany = async (comp) => {
    if (!user.id) return;
    await sb.from('profiles').update({
      company_name: comp.name, company_form: comp.form, vat_id: comp.vat || null,
      updated_at: new Date().toISOString(),
    }).eq('id', user.id);
    setUser((u) => ({ ...u, company: { ...u.company, ...comp } }));
    showToast('Firmendaten gespeichert.');
  };

  // --- Bestellungen: Auto-Verlaengerung via Stripe kuendigen/reaktivieren ---
  const setRenew = async (uuid, cancel) => {
    try {
      const { data } = await sb.auth.getSession();
      const token = data && data.session && data.session.access_token;
      const res = await fetch('/api/cancel-subscription', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
        body: JSON.stringify({ orderId: uuid, cancel }),
      });
      if (!res.ok) throw new Error('Fehler');
      setOrders((prev) => prev.map(o => o._uuid === uuid ? { ...o, autoRenew: !cancel } : o));
      showToast(cancel
        ? 'Automatische Verlängerung gestoppt — Vertrag läuft bis zum Laufzeitende.'
        : 'Automatische Verlängerung wieder aktiviert.');
    } catch (e) {
      showToast('Änderung konnte nicht gespeichert werden.');
    }
  };
  const stopAutoRenew = (uuid) => setRenew(uuid, true);
  const enableAutoRenew = (uuid) => setRenew(uuid, false);

  // --- Tickets ---
  const createTicket = async (t) => {
    if (!user.id) return;
    const { error } = await sb.from('support_tickets').insert({
      user_id: user.id, subject: t.subject, category: t.category,
      message: t.message, status: 'offen',
    });
    if (error) { showToast('Ticket konnte nicht erstellt werden.'); return; }
    await reloadTickets();
    showToast('Ticket wurde erstellt.');
  };

  return (
    <AppStateContext.Provider value={{
      user, authReady, orders, invoices, tickets,
      sendLoginCode, registerCompany, resendCode, verifyCode, signOut,
      updateProfile, updateCompany, stopAutoRenew, enableAutoRenew,
      createTicket, reloadOrders, reloadTickets, showToast,
    }}>
      {children}
      {toast ? (
        <div className="toast">
          <Icon name="check" />
          {toast}
        </div>
      ) : null}
    </AppStateContext.Provider>
  );
}

function useApp() { return useContext(AppStateContext); }

/* -------- Icons (simple inline SVG) -------- */

function Icon({ name, size = 16, stroke = 1.6 }) {
  const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'lock':
      return (<svg {...common}><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg>);
    case 'lock-check':
      return (<svg {...common}><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/><path d="M9.5 16l1.7 1.7L14.5 14.5"/></svg>);
    case 'shield':
      return (<svg {...common}><path d="M12 3l8 3v6c0 4.5-3.3 8.5-8 9-4.7-.5-8-4.5-8-9V6l8-3z"/></svg>);
    case 'shield-check':
      return (<svg {...common}><path d="M12 3l8 3v6c0 4.5-3.3 8.5-8 9-4.7-.5-8-4.5-8-9V6l8-3z"/><path d="M8.5 12.5l2.3 2.3L15.5 10"/></svg>);
    case 'check':
      return (<svg {...common}><path d="M5 12l4 4 10-10"/></svg>);
    case 'check-circle':
      return (<svg {...common}><circle cx="12" cy="12" r="9"/><path d="M8 12l3 3 5-6"/></svg>);
    case 'arrow-right':
      return (<svg {...common}><path d="M5 12h14"/><path d="M13 6l6 6-6 6"/></svg>);
    case 'plus':
      return (<svg {...common}><path d="M12 5v14M5 12h14"/></svg>);
    case 'x':
      return (<svg {...common}><path d="M6 6l12 12M18 6L6 18"/></svg>);
    case 'mail':
      return (<svg {...common}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>);
    case 'phone':
      return (<svg {...common}><path d="M5 4h4l2 5-3 2a12 12 0 0 0 5 5l2-3 5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z"/></svg>);
    case 'user':
      return (<svg {...common}><circle cx="12" cy="8" r="4"/><path d="M4 21v-1a6 6 0 0 1 6-6h4a6 6 0 0 1 6 6v1"/></svg>);
    case 'building':
      return (<svg {...common}><rect x="4" y="3" width="16" height="18" rx="1"/><path d="M9 7h1M9 11h1M9 15h1M14 7h1M14 11h1M14 15h1"/></svg>);
    case 'clock':
      return (<svg {...common}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>);
    case 'refresh':
      return (<svg {...common}><path d="M4 12a8 8 0 0 1 14-5l2-2v6h-6"/><path d="M20 12a8 8 0 0 1-14 5l-2 2v-6h6"/></svg>);
    case 'globe':
      return (<svg {...common}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/></svg>);
    case 'key':
      return (<svg {...common}><circle cx="7.5" cy="15.5" r="4.5"/><path d="M10.7 12.3 20 3"/><path d="M16 7l3 3"/></svg>);
    case 'monitor':
      return (<svg {...common}><rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/></svg>);
    case 'cog':
      return (<svg {...common}><circle cx="12" cy="12" r="3"/><path d="M19 12a7 7 0 0 0-.1-1.2l2-1.5-2-3.5-2.4.8a7 7 0 0 0-2.1-1.2L14 3h-4l-.4 2.4a7 7 0 0 0-2.1 1.2L5.1 5.8l-2 3.5 2 1.5A7 7 0 0 0 5 12c0 .4 0 .8.1 1.2l-2 1.5 2 3.5 2.4-.8a7 7 0 0 0 2.1 1.2L10 21h4l.4-2.4a7 7 0 0 0 2.1-1.2l2.4.8 2-3.5-2-1.5c.1-.4.1-.8.1-1.2z"/></svg>);
    case 'card':
      return (<svg {...common}><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M3 10h18"/></svg>);
    case 'doc':
      return (<svg {...common}><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/></svg>);
    case 'support':
      return (<svg {...common}><circle cx="12" cy="12" r="9"/><path d="M9 9.5a3 3 0 0 1 6 .5c0 1.5-2 2-2 3.5"/><circle cx="12" cy="17" r=".5" fill="currentColor"/></svg>);
    case 'download':
      return (<svg {...common}><path d="M12 4v12"/><path d="M7 11l5 5 5-5"/><path d="M4 20h16"/></svg>);
    case 'eye':
      return (<svg {...common}><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg>);
    case 'info':
      return (<svg {...common}><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8v.01"/></svg>);
    case 'home':
      return (<svg {...common}><path d="M4 11l8-7 8 7v9a1 1 0 0 1-1 1h-4v-6h-6v6H5a1 1 0 0 1-1-1v-9z"/></svg>);
    case 'bell':
      return (<svg {...common}><path d="M6 8a6 6 0 0 1 12 0c0 7 3 8 3 8H3s3-1 3-8z"/><path d="M10 21a2 2 0 0 0 4 0"/></svg>);
    case 'logout':
      return (<svg {...common}><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/></svg>);
    case 'chevron-down':
      return (<svg {...common}><path d="M6 9l6 6 6-6"/></svg>);
    case 'chevron-right':
      return (<svg {...common}><path d="M9 6l6 6-6 6"/></svg>);
    case 'search':
      return (<svg {...common}><circle cx="11" cy="11" r="7"/><path d="M21 21l-5-5"/></svg>);
    case 'paperclip':
      return (<svg {...common}><path d="M21 12.5L12.5 21a5 5 0 0 1-7-7L14 5.5a3.5 3.5 0 0 1 5 5L10.5 19"/></svg>);
    case 'menu':
      return (<svg {...common}><path d="M3 6h18M3 12h18M3 18h18"/></svg>);
    case 'alert':
      return (<svg {...common}><path d="M12 3l10 17H2L12 3z"/><path d="M12 10v4M12 17v.01"/></svg>);
    default:
      return null;
  }
}

/* -------- Logo / brand -------- */

function Logo({ light }) {
  return (
    <span className="brand">
      <span className="brand-mark">
        <Icon name="lock-check" size={16} />
      </span>
      <span style={{ color: light ? 'white' : 'var(--navy-900)' }}>ReadySSL</span>
    </span>
  );
}

/* -------- Public top nav + footer -------- */

function TopNav() {
  const { path, go } = useRouter();
  const { user, signOut } = useApp();
  const isActive = (p) => path === p ? 'nav-link active' : 'nav-link';
  return (
    <header className="topnav">
      <div className="topnav-inner">
        <Link to="/"><Logo /></Link>
        <nav className="nav-links hide-sm">
          <Link to="/product" className={isActive('/product')}>Produkt</Link>
          <Link to="/faq" className={isActive('/faq')}>FAQ</Link>
          <Link to="/agb" className={isActive('/agb')}>AGB</Link>
        </nav>
        <div className="nav-spacer" />
        <div className="nav-right">
          {user.loggedIn ? (
            <React.Fragment>
              <Link to="/dashboard" className="btn btn-ghost btn-sm">Dashboard</Link>
              <button className="btn btn-secondary btn-sm" onClick={async () => { await signOut(); go('/'); }}>Abmelden</button>
            </React.Fragment>
          ) : (
            <React.Fragment>
              <Link to="/login" className="btn btn-ghost btn-sm">Anmelden</Link>
              <Link to="/register" className="btn btn-primary btn-sm">
                <Icon name="lock" size={14} />
                SSL-Service buchen
              </Link>
            </React.Fragment>
          )}
        </div>
      </div>
    </header>
  );
}

function Footer() {
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer-grid">
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
              <span className="brand-mark"><Icon name="lock-check" size={16} /></span>
              <span style={{ color: 'white', fontWeight: 600 }}>ReadySSL</span>
            </div>
            <p style={{ fontSize: 13.5, color: 'oklch(0.78 0.02 250)', maxWidth: 280 }}>
              Einrichtung und laufende Überwachung kostenloser Let's Encrypt SSL-Zertifikate für Ihre Domain.
            </p>
            <p className="mono" style={{ fontSize: 12, color: 'oklch(0.62 0.02 250)', marginTop: 14 }}>
              Abrechnung über Vitalarista LLC, USA.
            </p>
          </div>
          <div>
            <h5>Produkt</h5>
            <ul>
              <li><Link to="/product">Service-Details</Link></li>
              <li><Link to="/checkout">Jetzt buchen</Link></li>
              <li><Link to="/faq">FAQ</Link></li>
            </ul>
          </div>
          <div>
            <h5>Konto</h5>
            <ul>
              <li><Link to="/login">Anmelden</Link></li>
              <li><Link to="/register">Registrieren</Link></li>
              <li><Link to="/dashboard">Dashboard</Link></li>
            </ul>
          </div>
          <div>
            <h5>Support</h5>
            <ul>
              <li><Link to="/dashboard/support">Ticket erstellen</Link></li>
              <li><a href="#/faq">Hilfecenter</a></li>
              <li><a href="#/impressum">Kontakt</a></li>
            </ul>
          </div>
          <div>
            <h5>Rechtliches</h5>
            <ul>
              <li><Link to="/agb">AGB</Link></li>
              <li><Link to="/datenschutz">Datenschutz</Link></li>
              <li><Link to="/impressum">Impressum</Link></li>
            </ul>
          </div>
        </div>
        <div className="footer-bot">
          <div>© 2026 Vitalarista LLC. Alle Rechte vorbehalten.</div>
          <div className="row" style={{ gap: 18 }}>
            <span><Icon name="shield-check" size={14} /> SSL Labs A+ Standard</span>
            <span>Made in EU · Hosted in EU</span>
          </div>
        </div>
      </div>
    </footer>
  );
}

/* -------- Dashboard layout -------- */

function DashboardShell({ children, active, title, subtitle, actions }) {
  const { user, authReady, signOut } = useApp();
  const { go } = useRouter();
  useEffect(() => { if (authReady && !user.loggedIn) go('/login'); }, [authReady, user.loggedIn]);
  if (!authReady) return <div style={{ minHeight: '60vh', display: 'grid', placeItems: 'center', color: 'var(--muted)' }}>Lädt …</div>;
  if (!user.loggedIn) return null;
  const initials = ((user.first[0] || user.email[0] || '?') + (user.last[0] || '')).toUpperCase();
  return (
    <div className="app-shell">
      <aside className="sidebar">
        <Link to="/dashboard" className="sidebar-brand">
          <span className="brand-mark"><Icon name="lock-check" size={16} /></span>
          ReadySSL
        </Link>

        <div className="side-section">Übersicht</div>
        <nav className="side-nav">
          <Link to="/dashboard" className={'side-link' + (active === 'overview' ? ' active' : '')}>
            <Icon name="home" /> Übersicht
          </Link>
          <Link to="/dashboard/orders" className={'side-link' + (active === 'orders' ? ' active' : '')}>
            <Icon name="shield-check" /> Meine Käufe
          </Link>
          <Link to="/dashboard/domains/new" className={'side-link' + (active === 'add-domain' ? ' active' : '')}>
            <Icon name="plus" /> Domain hinzufügen
          </Link>
          <Link to="/dashboard/invoices" className={'side-link' + (active === 'invoices' ? ' active' : '')}>
            <Icon name="doc" /> Rechnungen
          </Link>
        </nav>

        <div className="side-section">Konto</div>
        <nav className="side-nav">
          <Link to="/dashboard/profile" className={'side-link' + (active === 'profile' ? ' active' : '')}>
            <Icon name="user" /> Kundendaten
          </Link>
          <Link to="/dashboard/company" className={'side-link' + (active === 'company' ? ' active' : '')}>
            <Icon name="building" /> Firmendaten
          </Link>
        </nav>

        <div className="side-section">Hilfe</div>
        <nav className="side-nav">
          <Link to="/dashboard/support" className={'side-link' + (active === 'support' ? ' active' : '')}>
            <Icon name="support" /> Support-Tickets
          </Link>
          <Link to="/faq" className="side-link">
            <Icon name="info" /> FAQ
          </Link>
        </nav>

        <div className="side-bottom">
          <div className="user-row">
            <div className="avatar">{initials}</div>
            <div className="user-meta">
              <div style={{ fontWeight: 500, color: 'var(--ink)' }}>{user.first} {user.last}</div>
              <div className="e">{user.email}</div>
            </div>
          </div>
          <button className="side-link" style={{ width: '100%', textAlign: 'left', background: 'transparent', border: 0, marginTop: 4 }} onClick={async () => { await signOut(); go('/'); }}>
            <Icon name="logout" /> Abmelden
          </button>
        </div>
      </aside>

      <main className="app-main">
        <div className="app-topbar">
          <div className="page-title">
            <h1>{title}</h1>
            {subtitle ? <p>{subtitle}</p> : null}
          </div>
          <div className="row">
            {actions}
            <button className="btn btn-secondary btn-sm" title="Benachrichtigungen">
              <Icon name="bell" size={14} />
            </button>
          </div>
        </div>
        {children}
      </main>
    </div>
  );
}

/* -------- Public page wrapper -------- */

function PublicPage({ children, noFooter }) {
  return (
    <div className="shell">
      <TopNav />
      <main className="main">{children}</main>
      {noFooter ? null : <Footer />}
    </div>
  );
}

/* -------- Small primitives -------- */

function StatusBadge({ status, ar }) {
  // ar = autoRenew flag for separate display
  if (status === 'aktiv') return <span className="badge badge-green"><span className="dot dot-pulse" />aktiv</span>;
  if (status === 'in Bearbeitung') return <span className="badge badge-amber"><span className="dot" />in Bearbeitung</span>;
  if (status === 'abgelaufen') return <span className="badge badge-red"><span className="dot" />abgelaufen</span>;
  if (status === 'gekündigt') return <span className="badge">gekündigt</span>;
  return <span className="badge">{status}</span>;
}

function FAQItem({ q, a, open, onClick }) {
  return (
    <div className={'faq-item' + (open ? ' open' : '')}>
      <button className="faq-q" onClick={onClick}>
        <span>{q}</span>
        <Icon name="plus" size={18} />
      </button>
      <div className="faq-a">{a}</div>
    </div>
  );
}

/* Stripe Embedded Checkout — bettet das Bezahlfeld direkt in die Seite ein
   (kein Wechsel zu stripe.com). Erwartet clientSecret + publishableKey aus
   /api/create-checkout-session. */
function StripeEmbeddedCheckout({ clientSecret, publishableKey, onError }) {
  const ref = useRef(null);
  useEffect(() => {
    if (!clientSecret) return;
    if (!window.Stripe) { if (onError) onError('Stripe.js konnte nicht geladen werden.'); return; }
    if (!publishableKey) { if (onError) onError('Stripe-Publishable-Key fehlt — STRIPE_PUBLISHABLE_KEY in Vercel setzen.'); return; }

    let checkout = null;
    let cancelled = false;
    const stripe = window.Stripe(publishableKey);
    stripe.initEmbeddedCheckout({ fetchClientSecret: () => Promise.resolve(clientSecret) })
      .then((c) => {
        if (cancelled) { c.destroy(); return; }
        checkout = c;
        if (ref.current) c.mount(ref.current);
      })
      .catch((err) => { if (onError) onError(err && err.message ? err.message : 'Bezahlfeld konnte nicht geladen werden.'); });

    return () => { cancelled = true; if (checkout) { try { checkout.destroy(); } catch (e) {} } };
  }, [clientSecret, publishableKey]);

  return <div ref={ref} className="stripe-embed" />;
}

/* expose */
Object.assign(window, {
  RouterProvider, RouterContext, useRouter, Link,
  AppStateProvider, useApp, AppStateContext,
  Icon, Logo, TopNav, Footer, DashboardShell, PublicPage,
  StatusBadge, FAQItem, StripeEmbeddedCheckout,
  parseDomains, fmtDate, addMonths, addDays,
});
