/* ============================================================
   Matrix — Matrix View (Phase 6a)
   
   Top-level container for cyberdeck configuration + persona stats.
   Branches on character type:
     - Technomancer → Living Persona panel (read-only, derived)
     - Decker (has cyberdeck in electronics) → active deck picker,
       ASDF configurator, programs panel
     - Neither → informative empty state
   ============================================================ */
const { useState, useEffect, useRef, useMemo, useCallback, Fragment } = React;

window.MatrixView = function MatrixView({ character, onChange }) {
    const C = SR5_CALC;
    const magicType = C.priorityRow(character, 'magic')?.type;
    const isTechnomancer = magicType === 'technomancer';
    const decks = C.characterCyberdecks(character);

    const [actionsRefOpen, setActionsRefOpen] = useState(false);

    /* Header with a always-available "Matrix Actions" reference button. */
    const headerButton = (
        <button className="btn btn-ghost" onClick={() => setActionsRefOpen(true)}>
            Matrix Actions ↗
        </button>
    );

    if (isTechnomancer) {
        return (
            <>
                <ContentHeader title="08 / Matrix" heading="Living Persona" right={headerButton} />
                <LivingPersonaPanel character={character} />
                <SpritesSection character={character} onChange={onChange} />
                <RegisteredSpritesSection character={character} onChange={onChange} />
                <SubmersionSection character={character} onChange={onChange} />
                <EchoesSection character={character} onChange={onChange} />
                <div className="phase-note" style={{ marginTop: 20 }}>
                    <strong>Phase 10.</strong> Submersion added: technomancer metamagic progression
                    with karma cost 10 + (Grade × 3), Resonance cap raised by grade, and one echo slot
                    granted per grade. Echoes are now gated by available submersion grades.
                </div>
                {actionsRefOpen && <MatrixActionsReference onClose={() => setActionsRefOpen(false)} />}
            </>
        );
    }

    if (decks.length === 0) {
        return (
            <>
                <ContentHeader title="08 / Matrix" heading="Matrix capabilities" right={headerButton} />
                <div className="card">
                    <div className="card-body muted" style={{ padding: 24 }}>
                        This character has no cyberdeck and isn't a technomancer. To participate in
                        the Matrix beyond basic commlink use, buy a cyberdeck in the{' '}
                        <strong className="accent">Gear → Electronics</strong> tab. Entry-level
                        options include the Erika MCD-1 (49,500¥) and Microdeck Summit (98,500¥).
                        {' '}You can still browse the <strong>Matrix Actions</strong> reference above.
                    </div>
                </div>
                {actionsRefOpen && <MatrixActionsReference onClose={() => setActionsRefOpen(false)} />}
            </>
        );
    }

    /* Decker: deck selector + ASDF + programs */
    return (
        <>
            <ContentHeader title="08 / Matrix" heading="Decker" right={headerButton} />
            <ActiveDeckPanel character={character} onChange={onChange} />
            {character.matrix?.activeDeckId && (
                <>
                    <AsdfConfigurator character={character} onChange={onChange} />
                    <ProgramsPanel character={character} onChange={onChange} />
                </>
            )}
            <div className="phase-note" style={{ marginTop: 20 }}>
                <strong>Phase 6c.</strong> Configure your cyberdeck's ASDF array and load programs.
                Swap two attributes by clicking them. Click the <strong>Matrix Actions</strong> button
                above for a full quick-reference of all 37 actions, their tests, and marks requirements.
            </div>
            {actionsRefOpen && <MatrixActionsReference onClose={() => setActionsRefOpen(false)} />}
        </>
    );
};

/* ============================================================
   ActiveDeckPanel — pick which owned deck is booted
   ============================================================ */
window.ActiveDeckPanel = function ActiveDeckPanel({ character, onChange }) {
    const C = SR5_CALC;
    const decks = C.characterCyberdecks(character);
    const active = C.activeCyberdeck(character);

    function onPickDeck(id) {
        onChange(C.setActiveCyberdeck(character, id));
    }
    function onEject() {
        if (confirm('Eject the active deck? This will unload all running programs and reset your ASDF.')) {
            onChange(C.setActiveCyberdeck(character, null));
        }
    }

    return (
        <div className="card">
            <div className="card-header">
                <h3 className="card-title">Active Cyberdeck</h3>
                {active && (
                    <div className="card-actions">
                        <button className="btn btn-ghost" onClick={onEject}>Eject</button>
                    </div>
                )}
            </div>
            <div className="card-body">
                {decks.length === 1 && !active && (
                    <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                        <span className="muted">
                            You own one cyberdeck: <strong className="accent">{decks[0].name}</strong>.
                        </span>
                        <button className="btn btn-primary" onClick={() => onPickDeck(decks[0].id)}>
                            Boot it
                        </button>
                    </div>
                )}

                {decks.length > 1 && (
                    <div className="deck-picker">
                        {decks.map(d => {
                            const isActive = character.matrix?.activeDeckId === d.id;
                            return (
                                <div key={d.id}
                                     className={`deck-card ${isActive ? 'active' : ''}`}
                                     onClick={() => onPickDeck(d.id)}>
                                    <div className="dc-name">{d.name}</div>
                                    <div className="dc-meta">DR {d.rating} · {d.avail} · {(d.nuyen || 0).toLocaleString()}¥</div>
                                    {isActive && <div className="dc-badge">Booted</div>}
                                </div>
                            );
                        })}
                    </div>
                )}

                {active && (
                    <div className="deck-summary" style={{ marginTop: 12 }}>
                        <div className="ds-name accent">{active.gearEntry.name}</div>
                        <div className="ds-stats">
                            <span><span className="muted">DR</span> <strong>{active.gearEntry.rating || active.template.rating}</strong></span>
                            <span><span className="muted">Matrix CM</span> <strong>{C.personaStats(character).matrixConditionMonitor}</strong></span>
                            <span><span className="muted">Program slots</span> <strong>{active.template.programSlots}</strong></span>
                            <span><span className="muted">Storage</span> <strong>{active.template.storageSlots}</strong></span>
                            <span><span className="muted">Base array</span> <strong style={{ fontFamily: 'var(--font-mono)' }}>[{active.template.attributeArray.join(', ')}]</strong></span>
                        </div>
                    </div>
                )}
            </div>
        </div>
    );
};

/* ============================================================
   AsdfConfigurator — 4 attribute cards, click-to-swap
   ============================================================ */
window.AsdfConfigurator = function AsdfConfigurator({ character, onChange }) {
    const C = SR5_CALC;
    const asdf = character.matrix?.asdf;
    const stats = C.personaStats(character);
    const [selected, setSelected] = useState(null);

    if (!asdf) return null;

    const ATTRS = [
        { key: 'attack',         label: 'Attack',          short: 'ATT' },
        { key: 'sleaze',         label: 'Sleaze',          short: 'SLZ' },
        { key: 'dataProcessing', label: 'Data Processing', short: 'DP'  },
        { key: 'firewall',       label: 'Firewall',        short: 'FW'  },
    ];

    function onCardClick(attrKey) {
        if (selected === null) {
            setSelected(attrKey);
            return;
        }
        if (selected === attrKey) {
            setSelected(null);
            return;
        }
        onChange(C.swapAsdfAttributes(character, selected, attrKey));
        setSelected(null);
    }

    return (
        <div className="card">
            <div className="card-header">
                <h3 className="card-title">ASDF Array</h3>
                <div className="card-subtitle muted">
                    {selected
                        ? `Selected "${ATTRS.find(a => a.key === selected).label}" — click another to swap`
                        : 'Click two attributes to swap their values'}
                </div>
            </div>
            <div className="card-body">
                <div className="asdf-grid">
                    {ATTRS.map(a => {
                        const val = asdf[a.key];
                        const isSel = selected === a.key;
                        return (
                            <div key={a.key}
                                 className={`asdf-card ${isSel ? 'selected' : ''}`}
                                 onClick={() => onCardClick(a.key)}>
                                <div className="asdf-short">{a.short}</div>
                                <div className="asdf-label">{a.label}</div>
                                <div className="asdf-value">{val}</div>
                            </div>
                        );
                    })}
                </div>
                <div className="muted" style={{ fontSize: 11, marginTop: 12, lineHeight: 1.5 }}>
                    <strong>Offensive:</strong> Attack dice go to hostile Matrix actions (Data Spike, Attack).
                    <strong> Stealthy:</strong> Sleaze evades detection (Hide, Spoof Command, Hack on the Fly).
                    <strong> Productive:</strong> Data Processing handles utility (Matrix Search, Edit File, Matrix Perception).
                    <strong> Defensive:</strong> Firewall resists all hostile actions.
                </div>
            </div>
        </div>
    );
};

/* ============================================================
   ProgramsPanel — load/unload programs owned in gear
   ============================================================ */
window.ProgramsPanel = function ProgramsPanel({ character, onChange }) {
    const C = SR5_CALC;
    const active = C.activeCyberdeck(character);
    if (!active) return null;

    const slots = active.template.programSlots || 0;
    const programs = C.characterPrograms(character);
    const loaded = C.loadedPrograms(character);
    const loadedIds = new Set(loaded.map(p => p.id));
    const stored = programs.filter(p => !loadedIds.has(p.id));
    const atCapacity = loaded.length >= slots;

    function onLoad(id) {
        if (atCapacity) return;
        onChange(C.loadProgram(character, id));
    }
    function onUnload(id) {
        onChange(C.unloadProgram(character, id));
    }

    return (
        <div className="card">
            <div className="card-header">
                <h3 className="card-title">Programs</h3>
                <div className="card-actions">
                    <span className="muted" style={{ fontSize: 12 }}>
                        <strong style={{ color: atCapacity ? 'var(--good)' : 'var(--text-primary)' }}>
                            {loaded.length}
                        </strong>
                        <span className="muted">/{slots} slots</span>
                    </span>
                </div>
            </div>
            <div className="card-body" style={{ padding: 0 }}>
                {programs.length === 0 ? (
                    <div className="spell-empty">
                        No programs owned. Buy programs in the <strong>Gear → Electronics</strong> tab —
                        most cost 250¥ and are freely available; hacking programs (Attack, Hammer, etc.)
                        are restricted.
                    </div>
                ) : (
                    <div className="programs-split">
                        <div className="ps-col">
                            <div className="ps-heading">Loaded ({loaded.length}/{slots})</div>
                            {loaded.length === 0 ? (
                                <div className="ps-empty">No programs loaded yet.</div>
                            ) : loaded.map(p => {
                                const tpl = window.SR5_EQUIPMENT.findItem(p.key);
                                const isHacking = tpl?.tags?.includes('hacking');
                                return (
                                    <div key={p.id} className={`ps-row loaded ${isHacking ? 'hacking' : ''}`}>
                                        <div className="ps-name">{p.name}</div>
                                        <div className="ps-desc">{tpl?.description || ''}</div>
                                        <button className="btn btn-ghost ps-btn"
                                                onClick={() => onUnload(p.id)}>Unload</button>
                                    </div>
                                );
                            })}
                        </div>
                        <div className="ps-col">
                            <div className="ps-heading">Stored ({stored.length})</div>
                            {stored.length === 0 ? (
                                <div className="ps-empty">All programs loaded.</div>
                            ) : stored.map(p => {
                                const tpl = window.SR5_EQUIPMENT.findItem(p.key);
                                const isHacking = tpl?.tags?.includes('hacking');
                                return (
                                    <div key={p.id} className={`ps-row stored ${isHacking ? 'hacking' : ''}`}>
                                        <div className="ps-name">{p.name}</div>
                                        <div className="ps-desc">{tpl?.description || ''}</div>
                                        <button className={`btn ${atCapacity ? 'btn-ghost' : 'btn-primary'} ps-btn`}
                                                disabled={atCapacity}
                                                onClick={() => onLoad(p.id)}>Load</button>
                                    </div>
                                );
                            })}
                        </div>
                    </div>
                )}
            </div>
        </div>
    );
};

/* ============================================================
   LivingPersonaPanel — read-only derived stats for technomancers
   ============================================================ */
window.LivingPersonaPanel = function LivingPersonaPanel({ character }) {
    const C = SR5_CALC;
    const stats = C.personaStats(character);

    const ATTRS = [
        { key: 'attack',         label: 'Attack',          short: 'ATT', derived: 'Charisma' },
        { key: 'sleaze',         label: 'Sleaze',          short: 'SLZ', derived: 'Intuition' },
        { key: 'dataProcessing', label: 'Data Processing', short: 'DP',  derived: 'Logic' },
        { key: 'firewall',       label: 'Firewall',        short: 'FW',  derived: 'Willpower' },
    ];

    return (
        <>
            <div className="card">
                <div className="card-header">
                    <h3 className="card-title">Living Persona Stats</h3>
                    <div className="card-subtitle muted">Device Rating = Resonance ({stats.deviceRating})</div>
                </div>
                <div className="card-body">
                    <div className="asdf-grid">
                        {ATTRS.map(a => (
                            <div key={a.key} className="asdf-card living">
                                <div className="asdf-short">{a.short}</div>
                                <div className="asdf-label">{a.label}</div>
                                <div className="asdf-value">{stats[a.key]}</div>
                                <div className="asdf-derived muted">= {a.derived}</div>
                            </div>
                        ))}
                    </div>
                </div>
            </div>

            <div className="card">
                <div className="card-header">
                    <h3 className="card-title">Matrix Damage</h3>
                </div>
                <div className="card-body">
                    <div className="muted" style={{ fontSize: 12, lineHeight: 1.5 }}>
                        Living personas have no separate Matrix Condition Monitor. Matrix damage
                        that gets through your Firewall hits your <strong className="accent">Stun track</strong> directly
                        (biofeedback from hot-sim can spill into Physical). Your only defense is
                        your Firewall, your <strong>Willpower</strong>, and — at higher Submersion
                        grades — various echoes. Unlike deckers you can't reboot a deck to escape
                        convergence.
                    </div>
                </div>
            </div>
        </>
    );
};
