// Integrations — tenant-level provider connections (GitHub, Stripe, Shopify, Square).
// Self-fetching (TagsSection pattern): not needed app-wide.
//
// The token/key field is write-only by design: the server validates it
// against the provider, encrypts it, and never returns it — so there is
// nothing to "show" after connecting except who it authenticates as.
//
// One generic ProviderCard drives both providers; each entry in PROVIDERS
// supplies the copy and the how-to-get-a-token walkthrough.

// Web-shop webhooks (0063): the "key" is the provider's webhook SIGNING
// SECRET; after connecting, the card shows the URL to paste into the shop.
// Orders land on the customer's timeline as order.created/paid/fulfilled/
// cancelled/refunded — the same events task presets bind to.
const webshopSteps = {
    shopify: [
        <li key="1">In Shopify admin open <strong>Settings → Notifications → Webhooks</strong> (at the bottom of the page)</li>,
        <li key="2">Copy the <strong>signing secret</strong> shown under the webhook list (starts with a long random string — that's the "key" below)</li>,
        <li key="3">Connect here, then come back to Shopify and <strong>Create webhook</strong> for each of: <em>Order creation, Order payment, Order fulfillment, Order cancellation, Refund create, Customer creation</em> — format JSON, URL = the one this card shows after connecting</li>,
        <li key="4">Send a test from Shopify's webhook list; it appears on the matching customer's Activity tab within seconds</li>,
    ],
    square: [
        <li key="1">Open the <a href="https://developer.squareup.com/apps" target="_blank" rel="noopener noreferrer">Square Developer dashboard <i className="fas fa-external-link-alt" style={{ fontSize: '0.65rem' }}></i></a> → your application → <strong>Webhooks → Subscriptions</strong></li>,
        <li key="2">Add a subscription (API version = latest) for: <em>payment.created, payment.updated, order.fulfillment.updated, order.updated, refund.updated, customer.created</em></li>,
        <li key="3">Copy the subscription's <strong>Signature key</strong> — that's the "key" below. Square signs every delivery with it AND the notification URL, so the URL you paste into Square must be exactly the one this card shows</li>,
        <li key="4">Square's "Send test event" shows up as an ignored (test) delivery — the real proof is a sandbox order</li>,
    ],
};
const INTEGRATION_PROVIDERS = [
    {
        provider: 'shopify',
        name: 'Shopify',
        icon: 'fab fa-shopify',
        webhook: true,
        blurb: 'Your Shopify store\'s orders — placed, paid, fulfilled, cancelled, refunded — land on the customer\'s timeline, and task presets can fire on each one. New shop customers become accounts automatically.',
        placeholder: 'Webhook signing secret',
        connectedNote: 'Paste the webhook URL below into Shopify → Settings → Notifications → Webhooks (one webhook per event you want). Bind presets to the order events in Settings → Task Presets.',
        disconnectWarning: 'Disconnect Shopify? Deliveries to the webhook URL will be refused; orders already on timelines stay. Remember to delete the webhooks in Shopify too.',
        steps: webshopSteps.shopify,
    },
    {
        provider: 'square',
        name: 'Square',
        icon: 'fas fa-square',
        webhook: true,
        blurb: 'Square orders — paid, fulfilled, cancelled, refunded — land on the customer\'s timeline and can fire task presets. Customers are matched by the buyer email on the payment.',
        placeholder: 'Webhook signature key',
        connectedNote: 'Paste the webhook URL below into the Square Developer dashboard as the subscription\'s notification URL — exactly as shown (Square signs with it).',
        disconnectWarning: 'Disconnect Square? Deliveries will be refused; orders already on timelines stay. Disable the subscription in Square too.',
        steps: webshopSteps.square,
    },
    {
        provider: 'github',
        pack: 'software-dev',   // card exists only when the pack that serves it is enabled
        name: 'GitHub',
        icon: 'fab fa-github',
        // Plan gate (0033): visible-but-locked on the free plan. The server
        // enforces; this render is just honesty about what paid includes.
        featureKey: 'integrations.github',
        blurb: 'Wire repositories to client accounts — commits appear on that client\'s activity timeline automatically, so the work you ship for them is part of their story.',
        placeholder: 'github_pat_…',
        connectedNote: 'Wire repos to accounts from an account\'s Activity tab (managers and admins).',
        disconnectWarning: 'Disconnect GitHub? Repo wirings will be removed; commits already on timelines stay.',
        steps: [
            <li key="1">
                <a href="https://github.com/settings/personal-access-tokens/new" target="_blank" rel="noopener noreferrer">
                    Open GitHub's new-token page <i className="fas fa-external-link-alt" style={{ fontSize: '0.65rem' }}></i>
                </a>
                {' '}(a <strong>fine-grained</strong> personal access token)
            </li>,
            <li key="2"><strong>Repository access:</strong> "Only select repositories" — pick the repos you want on client timelines</li>,
            <li key="3"><strong>Permissions → Contents:</strong> Read-only. That's the only permission it needs.</li>,
            <li key="4">Set an expiration — this page will show when it needs renewing</li>,
            <li key="5">Generate, copy the token, and paste it below</li>,
        ],
    },
    {
        provider: 'stripe',
        module: 'sales_billing',   // core module a SPEC-lightweight tenant has off — card hidden, connect refused server-side
        name: 'Stripe',
        icon: 'fab fa-stripe-s',
        blurb: 'Create payment links from a customer\'s account — one-time or monthly subscription. When they pay, it lands on their timeline and an urgent follow-up task is created automatically.',
        placeholder: 'rk_live_… (or rk_test_… to rehearse)',
        connectedNote: 'Create payment links from an account\'s Activity tab (managers and admins). Payments are picked up within a couple of minutes.',
        disconnectWarning: 'Disconnect Stripe? Existing payment links keep working on Stripe\'s side, but payments will no longer be logged here.',
        steps: [
            <li key="1">
                <a href="https://dashboard.stripe.com/apikeys" target="_blank" rel="noopener noreferrer">
                    Open Stripe → Developers → API keys <i className="fas fa-external-link-alt" style={{ fontSize: '0.65rem' }}></i>
                </a>
                {' '}and choose <strong>Create restricted key</strong> (not the full secret key)
            </li>,
            <li key="2"><strong>Write</strong> access: Products, Prices, Payment Links</li>,
            <li key="3"><strong>Read</strong> access: Events, Checkout Sessions, Subscriptions, Invoices, Customers — everything else stays None</li>,
            <li key="4">A restricted key can't refund, pay out, or read card data — that's the point</li>,
            <li key="5">Create, copy the key (rk_…), and paste it below</li>,
        ],
    },
];

// A feature the tenant's plan doesn't include: the card stays visible (so
// free workspaces can see what paid offers) but the connect flow is replaced
// by an honest one-liner. No fake buttons, no nag modal.
const LockedProviderCard = ({ cfg }) => (
    <div className="detail-info-card" style={{ maxWidth: 560, marginBottom: '1rem', opacity: 0.85 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
            <i className={cfg.icon} style={{ fontSize: '1.5rem' }}></i>
            <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 600 }}>
                    {cfg.name}
                    <span style={{
                        marginLeft: '0.5rem', fontSize: '0.6875rem', fontWeight: 600,
                        padding: '0.15rem 0.5rem', borderRadius: '999px',
                        background: 'var(--accent-soft, rgba(99,102,241,0.15))', color: 'var(--accent)',
                    }}>
                        <i className="fas fa-lock" style={{ fontSize: '0.6rem', marginRight: '0.3rem' }}></i>Paid plan
                    </span>
                </div>
                <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', margin: '0.15rem 0 0 0' }}>{cfg.blurb}</p>
                <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', margin: '0.4rem 0 0 0' }}>
                    Included in the paid plan. Everything else in your CRM stays fully functional on the free plan.
                </p>
            </div>
        </div>
    </div>
);

const ProviderCard = ({ cfg, connection, onChanged }) => {
    const [token, setToken]   = React.useState('');
    const [label, setLabel]   = React.useState('');
    const [open, setOpen]     = React.useState(false);
    const [saving, setSaving] = React.useState(false);
    const [error, setError]   = React.useState('');

    const handleConnect = async (e) => {
        e.preventDefault();
        setSaving(true); setError('');
        try {
            await api.createIntegration({ provider: cfg.provider, token: token.trim(), label: label.trim() });
            setToken(''); setLabel(''); setOpen(false);
            onChanged();
        } catch (err) { setError(err.message); }
        finally { setSaving(false); }
    };

    const handleDisconnect = async () => {
        if (!await confirmAction(cfg.disconnectWarning)) return;
        try { await api.deleteIntegration(connection.id); onChanged(); }
        catch (err) { alert(err.message); }
    };

    if (connection) return (
        <div className="detail-info-card" style={{ maxWidth: 560, marginBottom: '1rem' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
                <i className={cfg.icon} style={{ fontSize: '1.5rem' }}></i>
                <div style={{ flex: 1 }}>
                    <div style={{ fontWeight: 600 }}>
                        {connection.label || cfg.name}
                        {connection.provider_login && <span style={{ color: 'var(--text-3)', fontWeight: 400 }}> — connected as {connection.provider_login}</span>}
                    </div>
                    <div style={{ fontSize: '0.8125rem', marginTop: '0.15rem' }}>
                        {connection.status === 'active'
                            ? <span style={{ color: 'var(--success, #22c55e)' }}><i className="fas fa-check-circle"></i> Active</span>
                            : <span style={{ color: 'var(--danger, #ef4444)' }}><i className="fas fa-exclamation-circle"></i> {connection.status === 'revoked' ? 'Key expired or revoked — reconnect with a fresh one' : 'Error'}{connection.last_error ? ` · ${connection.last_error}` : ''}</span>}
                    </div>
                </div>
                <button className="btn btn-danger btn-small" onClick={handleDisconnect}>
                    <i className="fas fa-unlink"></i> Disconnect
                </button>
            </div>
            {cfg.webhook && connection.webhook_id && (() => {
                const url = `${window.location.origin}/api/webhooks/${cfg.provider}/${connection.webhook_id}`;
                return (
                    <div style={{ marginTop: '0.75rem' }}>
                        <div className="form-label" style={{ marginBottom: '0.25rem' }}>Webhook URL — paste into {cfg.name}</div>
                        <div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
                            <input className="form-input" readOnly value={url} onFocus={e => e.target.select()} style={{ fontFamily: 'monospace', fontSize: '0.75rem' }} />
                            <button type="button" className="btn btn-secondary btn-small" onClick={() => navigator.clipboard && navigator.clipboard.writeText(url)} title="Copy"><i className="fas fa-copy"></i></button>
                        </div>
                        <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', margin: '0.35rem 0 0 0' }}>
                            The address is only a locator — every delivery is verified against your signing secret before anything is stored.
                        </p>
                    </div>
                );
            })()}
            <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', marginTop: '0.75rem', marginBottom: 0 }}>
                {cfg.connectedNote}
            </p>
        </div>
    );

    if (!open) return (
        <div className="detail-info-card" style={{ maxWidth: 560, marginBottom: '1rem' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
                <i className={cfg.icon} style={{ fontSize: '1.5rem' }}></i>
                <div style={{ flex: 1 }}>
                    <div style={{ fontWeight: 600 }}>{cfg.name}</div>
                    <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', margin: '0.15rem 0 0 0' }}>{cfg.blurb}</p>
                </div>
                <button className="btn btn-primary btn-small" onClick={() => setOpen(true)}>
                    <i className="fas fa-plug"></i> Connect
                </button>
            </div>
        </div>
    );

    return (
        <form onSubmit={handleConnect} className="detail-info-card" style={{ maxWidth: 560, marginBottom: '1rem' }}>
            {error && <div className="api-error">{error}</div>}
            <div style={{ fontWeight: 600, marginBottom: '0.5rem' }}>
                <i className={cfg.icon} style={{ marginRight: '0.4rem' }}></i>
                {cfg.webhook ? `Connect ${cfg.name} webhooks — takes a few minutes` : `Get a key from ${cfg.name} — takes about a minute`}
            </div>
            <ol style={{ fontSize: '0.8125rem', color: 'var(--text-2)', lineHeight: 1.7, margin: '0 0 1rem 0', paddingLeft: '1.25rem' }}>
                {cfg.steps}
            </ol>
            <div className="form-group">
                <label className="form-label">{cfg.webhook ? 'Signing secret *' : 'Access token / key *'}</label>
                <input className="form-input" type="password" value={token}
                       onChange={e => setToken(e.target.value)}
                       placeholder={cfg.placeholder} required autoComplete="off" />
                <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', marginTop: '0.35rem' }}>
                    {cfg.webhook ? 'Stored encrypted, never shown again — every delivery is checked against it.' : `Verified with ${cfg.name} before it's saved, stored encrypted, never shown again.`}
                </p>
            </div>
            <div className="form-group">
                <label className="form-label">Label</label>
                <input className="form-input" value={label} onChange={e => setLabel(e.target.value)}
                       placeholder={`e.g. Company ${cfg.name}`} maxLength={100} />
            </div>
            <div style={{ display: 'flex', gap: '0.5rem' }}>
                <button type="submit" className="btn btn-primary" disabled={saving || !token.trim()}>
                    {saving ? <><i className="fas fa-spinner fa-spin"></i> {cfg.webhook ? 'Saving…' : `Checking with ${cfg.name}…`}</> : <><i className={cfg.icon}></i> Connect {cfg.name}</>}
                </button>
                <button type="button" className="btn btn-secondary" onClick={() => { setOpen(false); setError(''); }}>Cancel</button>
            </div>
        </form>
    );
};

const IntegrationsSection = ({ tenant }) => {
    const [connections, setConnections] = React.useState([]);
    // A failed refresh must not render every provider as "not connected"
    // (swallowed-error rule) — surface it with a retry.
    const [loadErr, setLoadErr] = React.useState(false);
    const refresh = () => api.getIntegrations().then(rows => { setConnections(rows); setLoadErr(false); }).catch(() => setLoadErr(true));
    React.useEffect(() => { refresh(); }, []);

    // Locked = the plan carries entitlements and this feature isn't in them.
    // Missing entitlements (old cache, plan data hiccup) renders UNLOCKED —
    // the server still refuses, and a wrongly-locked UI is the worse failure.
    const features = tenant?.entitlements?.features;
    const isLocked = (cfg) => !!(cfg.featureKey && features && features[cfg.featureKey] !== true);

    return (
        <div className="settings-form">
            {loadErr && (
                <div className="api-error" style={{ marginBottom: '0.75rem' }}>
                    <i className="fas fa-exclamation-triangle"></i> Couldn't load connections — cards below may be wrong.
                    <button className="btn btn-secondary btn-small" style={{ marginLeft: '0.75rem' }} onClick={refresh}><i className="fas fa-redo"></i> Retry</button>
                </div>
            )}
            <p style={{ fontSize: '0.875rem', color: 'var(--text-3)', marginBottom: '1.25rem' }}>
                Connect outside services to this workspace. Each connection uses its own
                least-privilege key, verified and encrypted at rest.
            </p>
            {/* Pack gate ≠ plan gate: a plan-locked feature renders a locked card
                (upsell honesty); an absent PACK renders nothing — different vertical. */}
            {INTEGRATION_PROVIDERS.filter(cfg => itemEnabled(tenant, cfg)).map(cfg => {
                // A live connection always renders fully (disconnect must work
                // even when the plan no longer includes the feature).
                const connection = connections.find(c => c.provider === cfg.provider);
                if (!connection && isLocked(cfg)) return <LockedProviderCard key={cfg.provider} cfg={cfg} />;
                return (
                    <ProviderCard key={cfg.provider} cfg={cfg}
                        connection={connection}
                        onChanged={refresh} />
                );
            })}
        </div>
    );
};
