/* ============================================================
   Bizia — Free Stack Planner  (/app/free-stack)
   Recommends and provisions the best free provider stack
   for a project. Never buys domains or creates accounts.
   ============================================================ */
(function () {
  const { useState, useEffect } = React;
  const { Card, Badge, Button, Icon, PageHeader, Chip } = window;

  const CATEGORY_ICONS = {
    hosting: 'cloud', database: 'database', auth: 'lock', dns: 'globe',
    seo: 'search', analytics: 'barChart', monitoring: 'activity', email: 'mail',
    cache: 'zap', vector: 'cpu', payments: 'creditCard',
  };

  const STATUS_TONE = {
    connected: 'success', missing_key: 'warning', demo: 'primary',
    disconnected: 'neutral', error: 'danger',
  };

  function StatusBadge({ status }) {
    const tone = STATUS_TONE[status] || 'neutral';
    const labels = { connected: 'Connected', missing_key: 'Needs Key', demo: 'Demo', disconnected: 'Not Set', error: 'Error' };
    return React.createElement(Badge, { tone, size: 'sm' }, labels[status] || status);
  }

  function ProviderCard({ p, health, onConnect, onDisconnect }) {
    const h = health[p.name] || {};
    const status = h.status || 'disconnected';
    const isConnected = status === 'connected';
    const needsOAuth = p.authType === 'oauth';

    return React.createElement(Card, { hover: true, pad: 18, style: { display: 'flex', flexDirection: 'column', gap: 10 } },
      React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' } },
        React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 10 } },
          React.createElement('div', {
            style: { width: 36, height: 36, borderRadius: 10, background: 'var(--surface-2)', display: 'flex', alignItems: 'center', justifyContent: 'center' }
          }, React.createElement(Icon, { name: CATEGORY_ICONS[p.category] || 'box', size: 18 })),
          React.createElement('div', null,
            React.createElement('div', { style: { fontWeight: 650, fontSize: 14 } }, p.label),
            React.createElement('div', { style: { fontSize: 12, color: 'var(--muted)' } }, p.category),
          ),
        ),
        React.createElement(StatusBadge, { status }),
      ),
      p.freeTier && React.createElement('div', { style: { fontSize: 12, color: 'var(--success)', display: 'flex', alignItems: 'center', gap: 4 } },
        React.createElement(Icon, { name: 'check', size: 12 }), 'Free tier available',
      ),
      p.requiresConsent && React.createElement('div', { style: { fontSize: 12, color: 'var(--warning)', display: 'flex', alignItems: 'center', gap: 4 } },
        React.createElement(Icon, { name: 'alertTriangle', size: 12 }), 'Requires consent before use',
      ),
      React.createElement('div', { style: { display: 'flex', gap: 8, marginTop: 4 } },
        isConnected
          ? React.createElement(Button, { variant: 'outline', size: 'sm', icon: 'xCircle', onClick: () => onDisconnect(p.name) }, 'Disconnect')
          : needsOAuth
            ? React.createElement(Button, { variant: 'soft', size: 'sm', icon: 'externalLink', onClick: () => onConnect(p.name, 'oauth') }, 'Connect via OAuth')
            : React.createElement(Button, { variant: 'primary', size: 'sm', icon: 'key', onClick: () => onConnect(p.name, 'key') }, 'Add Key'),
        React.createElement('a', {
          href: p.docsUrl, target: '_blank', rel: 'noopener noreferrer',
          style: { fontSize: 12, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 3, textDecoration: 'none' }
        }, React.createElement(Icon, { name: 'externalLink', size: 11 }), 'Docs'),
      ),
    );
  }

  function KeyModal({ provider, onClose, onSave }) {
    const [val, setVal] = useState('');
    const [saving, setSaving] = useState(false);
    return React.createElement('div', {
      style: {
        position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex',
        alignItems: 'center', justifyContent: 'center', zIndex: 9999,
      },
      onClick: onClose,
    },
      React.createElement(Card, { pad: 24, style: { width: 420, maxWidth: '90vw' }, onClick: e => e.stopPropagation() },
        React.createElement('h3', { style: { marginBottom: 12 } }, 'Connect ' + provider),
        React.createElement('p', { style: { fontSize: 13, color: 'var(--muted)', marginBottom: 16 } },
          'Paste your API key or DSN. It is encrypted and stored in your account only.'),
        React.createElement('input', {
          type: 'password', placeholder: 'sk-...', value: val,
          onChange: e => setVal(e.target.value),
          style: { width: '100%', padding: '8px 12px', borderRadius: 8, border: '1px solid var(--border)', fontSize: 14, boxSizing: 'border-box' },
        }),
        React.createElement('div', { style: { display: 'flex', gap: 8, marginTop: 16, justifyContent: 'flex-end' } },
          React.createElement(Button, { variant: 'ghost', size: 'sm', onClick: onClose }, 'Cancel'),
          React.createElement(Button, {
            variant: 'primary', size: 'sm', disabled: val.length < 8 || saving,
            onClick: async () => {
              setSaving(true);
              await onSave(val);
              setSaving(false);
              onClose();
            },
          }, saving ? 'Saving…' : 'Save & Connect'),
        ),
      ),
    );
  }

  const CONNECT_ENDPOINT = {
    cloudflare_pages: '/api/providers/cloudflare/connect-token',
    resend: '/api/providers/resend/connect-key',
    posthog: '/api/providers/posthog/connect-key',
    sentry: '/api/providers/sentry/connect-dsn',
    upstash_redis: '/api/providers/upstash/connect-key',
    pinecone: '/api/providers/pinecone/connect-key',
  };

  function FreeStackPage() {
    const [providers, setProviders] = useState([]);
    const [health, setHealth] = useState({});
    const [loading, setLoading] = useState(true);
    const [cat, setCat] = useState('All');
    const [keyModal, setKeyModal] = useState(null); // provider name or null

    // Hash-routed SPA — the ?project= query string lives inside
    // window.location.hash, not window.location.search (which is always
    // empty here). Reading .search silently fell back to a mock project.
    const projectId = new URLSearchParams(window.location.hash.split('?')[1] || '').get('project') || window.DATA.projects?.[0]?.id;

    useEffect(() => {
      Promise.all([
        window.API.req('GET', '/api/providers').then(r => r.data || []),
        window.API.req('GET', '/api/providers/status').then(r => {
          const map = {};
          (r.data || []).forEach(h => { map[h.provider] = h; });
          return map;
        }),
      ])
        .then(([p, h]) => { setProviders(p); setHealth(h); })
        .catch(() => window.toast({ title: 'Could not load providers', tone: 'danger' }))
        .finally(() => setLoading(false));
    }, []);

    const cats = ['All', ...Array.from(new Set(providers.map(p => p.category)))];
    const filtered = cat === 'All' ? providers : providers.filter(p => p.category === cat);

    const handleConnect = async (name, type) => {
      if (type === 'oauth') {
        const endpoint = name === 'google_search_console'
          ? '/api/providers/google/oauth/start'
          : '/api/providers/github/oauth/start';
        const r = await window.API.req('GET', endpoint).catch(() => null);
        if (r?.data?.url) window.open(r.data.url, '_blank', 'noopener,noreferrer');
        else window.toast({ title: 'OAuth not configured', tone: 'warning' });
        return;
      }
      setKeyModal(name);
    };

    const handleSaveKey = async (name, key) => {
      const ep = CONNECT_ENDPOINT[name];
      if (!ep) { window.toast({ title: 'No endpoint for ' + name, tone: 'warning' }); return; }
      const r = await window.API.req('POST', ep, { apiKey: key }).catch(() => null);
      if (r?.success) {
        window.toast({ title: 'Connected ' + name, tone: 'success' });
        const h = await window.API.req('GET', '/api/providers/status').then(r2 => {
          const m = {};
          (r2.data || []).forEach(x => { m[x.provider] = x; });
          return m;
        }).catch(() => health);
        setHealth(h);
      } else {
        window.toast({ title: 'Failed to connect ' + name, tone: 'danger' });
      }
    };

    const handleDisconnect = async (name) => {
      const r = await window.API.req('DELETE', `/api/providers/${name}/disconnect`).catch(() => null);
      if (r?.success) {
        window.toast({ title: 'Disconnected ' + name, tone: 'success' });
        setHealth(prev => ({ ...prev, [name]: { ...prev[name], status: 'missing_key' } }));
      } else {
        window.toast({ title: 'Failed to disconnect', tone: 'danger' });
      }
    };

    const connected = Object.values(health).filter(h => h.status === 'connected').length;
    const demo = Object.values(health).filter(h => h.status === 'demo').length;

    return React.createElement('div', { className: 'bz-anim-up' },
      React.createElement(PageHeader, {
        icon: 'layers', title: 'Free Stack Planner',
        sub: 'Connect optional services to power your site for free. No paid accounts created automatically.',
        action: projectId && React.createElement(Button, {
          variant: 'primary', icon: 'zap',
          onClick: () => window.navigate('/app/projects/' + projectId + '/stack'),
        }, 'View Stack Plan'),
      }),

      React.createElement('div', {
        style: { display: 'flex', gap: 12, marginBottom: 24, flexWrap: 'wrap' }
      },
        React.createElement(Card, { pad: 16, style: { flex: 1, minWidth: 160 } },
          React.createElement('div', { style: { fontSize: 28, fontWeight: 700 } }, providers.length),
          React.createElement('div', { style: { fontSize: 13, color: 'var(--muted)', marginTop: 2 } }, 'Total providers'),
        ),
        React.createElement(Card, { pad: 16, style: { flex: 1, minWidth: 160 } },
          React.createElement('div', { style: { fontSize: 28, fontWeight: 700, color: 'var(--success)' } }, connected),
          React.createElement('div', { style: { fontSize: 13, color: 'var(--muted)', marginTop: 2 } }, 'Connected'),
        ),
        React.createElement(Card, { pad: 16, style: { flex: 1, minWidth: 160 } },
          React.createElement('div', { style: { fontSize: 28, fontWeight: 700, color: 'var(--primary)' } }, demo),
          React.createElement('div', { style: { fontSize: 13, color: 'var(--muted)', marginTop: 2 } }, 'Demo mode'),
        ),
      ),

      React.createElement('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 20 } },
        cats.map(c => React.createElement(Chip, { key: c, active: cat === c, onClick: () => setCat(c) }, c)),
      ),

      loading
        ? React.createElement('div', { style: { textAlign: 'center', padding: 40, color: 'var(--muted)' } }, 'Loading providers…')
        : React.createElement('div', {
            style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(280px,1fr))', gap: 16 }
          },
            filtered.map(p => React.createElement(ProviderCard, {
              key: p.name, p, health,
              onConnect: handleConnect,
              onDisconnect: handleDisconnect,
            })),
          ),

      keyModal && React.createElement(KeyModal, {
        provider: keyModal,
        onClose: () => setKeyModal(null),
        onSave: (key) => handleSaveKey(keyModal, key),
      }),
    );
  }

  window.FreeStackPage = FreeStackPage;
})();
