// Settings → Project Space — the status page the platform operator publishes
// into this workspace (migration 0053). Read-only content for everyone; the
// one tenant-side lever is the admin's viewer picker: which teammates can
// open this page (admins always can).
//
// Rendering: the page is operator-authored HTML shown inside a SANDBOXED
// iframe — no scripts run, no same-origin access. The sandbox is
// browser-enforced, so even a script tag in the content is inert; we never
// innerHTML it into the app itself. The ONLY two grants are popup-related
// (found live 2026-08-21: a status page's target="_blank" link did nothing):
//   allow-popups                   — a user click may open a new tab
//   allow-popups-to-escape-sandbox — that tab is a normal page, not a
//                                    script-less sandboxed one (the linked
//                                    site would otherwise render broken)
// Never add allow-scripts / allow-same-origin here — those are the lines that
// would let published content reach the app's session.

// "CRM updates" tab: every release note this tenant can see, rendered as a
// vertical timeline (the presentation the owner asked to keep, 2026-08-29).
// Same feed as the login modal via loadWhatsNewEntries — updates itself
// each release, no operator publishing involved.
const WhatsNewTimeline = ({ tenant }) => {
    const [notes, setNotes] = React.useState(undefined);   // undefined = loading, null = nothing
    React.useEffect(() => {
        if (!tenant) return;
        loadWhatsNewEntries(tenant).then(setNotes).catch(() => setNotes(null));
    }, [tenant]);
    if (notes === undefined) return <p style={{ color: 'var(--text-3)', fontSize: '0.875rem' }}>Loading…</p>;
    if (!notes) return <p style={{ color: 'var(--text-3)', fontSize: '0.875rem' }}>No release notes yet.</p>;
    return (
        <div className="wn-timeline">
            {notes.entries.map(entry => (
                <div key={entry.version} className="wn-timeline-entry">
                    <div className="wn-timeline-dot"></div>
                    <div className="wn-timeline-meta">
                        <span className="whatsnew-version">v{entry.version}</span>
                        {entry.date && <span className="wn-timeline-date">{new Date(entry.date + 'T12:00:00').toLocaleDateString()}</span>}
                    </div>
                    <div className="wn-timeline-title">{entry.title}</div>
                    {entry.items.length > 0 && (
                        <ul>{entry.items.map((item, i) => <li key={i}>{item}</li>)}</ul>
                    )}
                    {(entry.packItems || []).map(p => (
                        <div key={p.label}>
                            <div className="wn-timeline-packlabel">{p.label}</div>
                            <ul>{p.items.map((item, i) => <li key={i}>{item}</li>)}</ul>
                        </div>
                    ))}
                </div>
            ))}
        </div>
    );
};

// "Your data & security" tab — product-posture copy, the same for every
// tenant. DOWNSTREAM COPY: canonical text lives in HQ's
// prospects/_shared/data-and-capacity.html; HQ messages on change (2026-08-29).
// Transcribed to JSX on purpose — first-party themed content, never innerHTML.
const DataSecurityTab = () => {
    const P = { fontSize: '0.875rem', color: 'var(--text-2)', lineHeight: 1.6, marginBottom: '0.75rem' };
    const H = { fontSize: '1.05rem', fontWeight: 700, margin: '0 0 0.2rem' };
    const S = { fontSize: '0.8125rem', color: 'var(--text-3)', marginBottom: '0.75rem' };
    const B = ({ children }) => <strong style={{ color: 'var(--text-1)' }}>{children}</strong>;
    return (
        <div style={{ maxWidth: 760 }}>
            <h3 style={H}>How we handle your data</h3>
            <p style={S}>The same posture across everything we operate — stated plainly so it can be checked.</p>
            <p style={P}><B>Your data is yours.</B> It stays exportable and leaves with you if you leave. We run no analytics trackers, no advertising scripts, and no AI services reading customer data. Nothing leaves our servers except toward providers you deliberately connect, and those connections run on least-scope keys — the narrowest permission the integration needs — stored encrypted.</p>
            <p style={P}><B>Who can see it.</B> You and the people you add. On our side, access is limited to what operating the service requires, and every change to a record is logged by the database itself — who, what, when — in a trail that application code cannot skip.</p>
            <h3 style={{ ...H, marginTop: '1.25rem' }}>Where it runs and how it's secured</h3>
            <p style={S}>A short account of the servers and the measures around them. The full version, including known limitations, is on our Security page.</p>
            <p style={P}><B>The servers.</B> Your service runs on cloud servers we provision and operate ourselves. Shared-client, private-client, and testing environments are separate machines by design; testing never holds a copy of customer data. The database runs as a managed service with automated backups and point-in-time recovery.</p>
            <p style={P}><B>Security measures.</B> Customer access is HTTPS with automatic certificates. Administrative access is key-only — no passwords — and our production server is reachable by us only over a private VPN; repeated failed logins are banned automatically. On shared infrastructure, separation between clients is enforced by the database itself (row-level security), not by application code remembering to filter. Secrets never live in code. Every line of application logic is written in house; the third-party code surface is fifteen pinned, inspectable open-source packages. Before selling to anyone, we ran an internal adversarial security review of the CRM across authorization, data layer, and concurrency, and fixed every finding first.</p>
            <p style={P}><B>Capacity.</B> In August 2026 we load-tested the hosted CRM on a separate staging server (synthetic data, never a customer copy) from 10 to 200 simultaneous users on a single one-core machine: zero errors at every level, responsive through roughly 50 concurrent users. A typical small business puts two to ten people in the CRM, so one small server carries far more than any one client; beyond that we add servers, not complexity — each client can run on shared infrastructure or its own private machine, provisioned from the same scripts.</p>
        </div>
    );
};

// "From KzNet" tab — company pages that apply to every customer. URLs live on
// kznettech.com/chart/ (verified live 2026-08-29; the old /biz/ 301s here).
const FROM_KZNET_LINKS = [
    { label: 'Products & Services', href: 'https://kznettech.com/chart/CATALOG.html',       blurb: 'What we sell and what each thing includes.' },
    { label: 'Roadmap',             href: 'https://kznettech.com/chart/ROADMAP.html',       blurb: "What we're building next, in order." },
    { label: 'Security',            href: 'https://kznettech.com/chart/SECURITY.html',      blurb: 'How your instance is hosted, backed up, and protected.' },
    { label: 'Service Terms',       href: 'https://kznettech.com/chart/SERVICE-TERMS.html', blurb: 'The terms you accepted, current version.' },
];
const FromKzNetTab = () => (
    <div style={{ maxWidth: 760 }}>
        <p style={{ fontSize: '0.875rem', color: 'var(--text-2)', marginBottom: '0.9rem' }}>
            Company pages that apply to every customer. They open in a new tab.
        </p>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '0.75rem' }}>
            {FROM_KZNET_LINKS.map(l => (
                <a key={l.href} href={l.href} target="_blank" rel="noopener noreferrer"
                   style={{ display: 'block', padding: '0.85rem 1rem', border: '1px solid var(--border)', borderRadius: '0.5rem',
                            background: 'var(--surface)', textDecoration: 'none' }}>
                    <div style={{ fontWeight: 600, color: 'var(--text-1)', marginBottom: '0.2rem' }}>
                        {l.label} <i className="fas fa-arrow-up-right-from-square" style={{ fontSize: '0.7rem', color: 'var(--text-3)', marginLeft: '0.25rem' }}></i>
                    </div>
                    <div style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>{l.blurb}</div>
                </a>
            ))}
        </div>
    </div>
);

const CollabSection = ({ currentUser, tenant }) => {
    const [data, setData]     = React.useState(null);   // GET /api/collab payload
    const [users, setUsers]   = React.useState(null);   // admin: tenant user list for the picker
    const [picked, setPicked] = React.useState([]);     // staged viewer ids
    const [saving, setSaving] = React.useState(false);
    const [saved, setSaved]   = React.useState(false);
    const [error, setError]   = React.useState(null);
    // Tabs (owner's ask 2026-08-29): the published doc is ONE tab ("Your
    // project" — status/timeline/website live inside it); generic content is
    // native tabs beside it. "Your data & security" / "From KzNet" join this
    // array when their content lands (HQ leg — TODO).
    const [tab, setTab] = React.useState('project');
    const TABS = [
        { id: 'project', label: 'Your project' },
        { id: 'traffic', label: 'Traffic' },
        { id: 'data',    label: 'Your data & security' },
        { id: 'updates', label: 'CRM updates' },
        { id: 'kznet',   label: 'From KzNet' },
    ];

    const isAdmin = currentUser.role === 'admin';

    React.useEffect(() => {
        api.getCollab()
            .then(d => { setData(d); setPicked(d.viewers || []); })
            .catch(err => setError(err.message));
        if (isAdmin) api.getUsers().then(setUsers).catch(() => {});
    }, []);

    const toggle = (id) => {
        setSaved(false);
        setPicked(p => p.includes(id) ? p.filter(x => x !== id) : [...p, id]);
    };

    const saveViewers = async () => {
        setSaving(true); setError(null); setSaved(false);
        try {
            const r = await api.setCollabViewers(picked);
            setPicked(r.viewers);
            setSaved(true);
        } catch (err) {
            setError(err.message);
        } finally {
            setSaving(false);
        }
    };

    if (error && !data) return <p style={{ color: 'var(--danger)', fontSize: '0.875rem' }}>{error}</p>;
    if (!data) return <p style={{ color: 'var(--text-3)', fontSize: '0.875rem' }}>Loading…</p>;

    // Admins with nothing published yet get an honest empty state; anyone
    // else without access shouldn't normally land here (the card is hidden),
    // but say something sane if they do.
    if (!data.can_view) {
        return <p style={{ color: 'var(--text-3)', fontSize: '0.875rem' }}>This page hasn't been shared with you.</p>;
    }

    const dirty = data.viewers && JSON.stringify([...picked].sort()) !== JSON.stringify([...(data.viewers || [])].sort());
    // Admins always see the page — the picker is for everyone else.
    const pickable = (users || []).filter(u => u.role !== 'admin' && u.is_active);

    // The frame sits OUTSIDE .settings-form so it gets the section's full
    // width (the form column is capped at 720px for readability; a client
    // status page wants the room). Height is fixed tall rather than sized to
    // content: the sandbox has no allow-scripts, so the page can't postMessage
    // its height, and a sandboxed srcdoc is an opaque origin we can't measure.
    return (
        <div>
            {/* Tab bar — segmented control (selection = raised pill, house taste) */}
            <div className="seg-control" style={{ marginBottom: '0.75rem' }} role="tablist">
                {TABS.map(t => (
                    <button key={t.id} type="button" role="tab" aria-selected={tab === t.id}
                            className={`seg-btn ${tab === t.id ? 'on' : ''}`} onClick={() => setTab(t.id)}>
                        {t.label}
                    </button>
                ))}
            </div>

            {tab === 'traffic' && <TrafficTab tenant={tenant} />}
            {tab === 'updates' && <WhatsNewTimeline tenant={tenant} />}
            {tab === 'data' && <DataSecurityTab />}
            {tab === 'kznet' && <FromKzNetTab />}

            {tab === 'project' && (data.published ? (
                <>
                    <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', marginBottom: '0.5rem' }}>
                        <strong style={{ color: 'var(--text-1)' }}>{data.doc.title}</strong>
                        {' · '}updated {new Date(data.doc.updated_at).toLocaleDateString()} — published by your service provider.
                    </p>
                    <iframe
                        sandbox="allow-popups allow-popups-to-escape-sandbox"
                        srcDoc={data.doc.html}
                        title={data.doc.title}
                        style={{ width: '100%', height: 'calc(100vh - 220px)', minHeight: '80vh', border: '1px solid var(--border)',
                                 borderRadius: '8px', background: '#fff', display: 'block' }}
                    />
                </>
            ) : (
                <p style={{ fontSize: '0.875rem', color: 'var(--text-3)' }}>
                    Nothing has been published to your Project Space yet — updates from your
                    service provider will appear here.
                </p>
            ))}

            {isAdmin && tab === 'project' && (
                <div className="settings-form" style={{ marginTop: '1.25rem' }}>
                    <h4 style={{ marginBottom: '0.35rem' }}>Who can see this page</h4>
                    <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', marginBottom: '0.5rem' }}>
                        Admins always can. Pick any teammates who should too — everyone else
                        won't even see the card.
                    </p>
                    {!data.published ? (
                        <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>Sharing opens up once something is published.</p>
                    ) : !users ? (
                        <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>Loading teammates…</p>
                    ) : pickable.length === 0 ? (
                        <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>No non-admin teammates yet.</p>
                    ) : (
                        <>
                            {/* House rule: chips, never checkbox lists */}
                            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.4rem', marginBottom: '0.6rem' }}>
                                {pickable.map(u => (
                                    <button
                                        key={u.id}
                                        type="button"
                                        className={`filter-chip ${picked.includes(u.id) ? 'active' : ''}`}
                                        onClick={() => toggle(u.id)}
                                    >
                                        {u.first_name} {u.last_name}
                                    </button>
                                ))}
                            </div>
                            <div style={{ display: 'flex', gap: '0.6rem', alignItems: 'center' }}>
                                <button className="btn btn-primary" disabled={saving || !dirty} onClick={saveViewers}>
                                    {saving ? <><i className="fas fa-spinner fa-spin"></i> Saving…</> : 'Save sharing'}
                                </button>
                                {saved && !dirty && (
                                    <span style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>
                                        <i className="fas fa-check" style={{ color: 'var(--success)' }}></i> Saved
                                    </span>
                                )}
                            </div>
                        </>
                    )}
                    {error && <p style={{ color: 'var(--danger)', fontSize: '0.875rem', marginTop: '0.5rem' }}>{error}</p>}
                </div>
            )}
        </div>
    );
};
