/* ============================================================
   Magic — Magical Equipment Section (Phase 5d)
   
   Top-level container for Foci, Reagents, and Lodges. Rendered
   inside MagicView for awakened characters (magicians, mystic
   adepts, adepts, aspected). Adepts are restricted to Qi + Weapon
   foci only; technomancers don't see this section at all.
   ============================================================ */
const { useState, useEffect, useRef, useMemo, useCallback, Fragment } = React;

window.MagicalEquipmentSection = function MagicalEquipmentSection({ character, onChange }) {
    const C = SR5_CALC;
    const M = SR5_MAGIC;

    const [focusPickerOpen, setFocusPickerOpen] = useState(false);
    const [customFocusOpen, setCustomFocusOpen] = useState(false);
    const [reagentPickerOpen, setReagentPickerOpen] = useState(false);
    const [lodgeOpen, setLodgeOpen] = useState(false);

    const inCareer = C.isCareerMode(character);
    const pendingFoci = inCareer ? window.CareerGear.pendingOfKind(character, 'focus') : [];
    const pendingReagents = inCareer ? window.CareerGear.pendingOfKind(character, 'reagent') : [];
    const pendingLodges = inCareer ? window.CareerGear.pendingOfKind(character, 'lodge') : [];

    const foci = C.characterFoci(character);
    const reagents = C.characterReagents(character);
    const lodges = C.characterLodges(character);

    const boundCount = C.fociBoundCount(character);
    const forceSum = C.fociForceSum(character);
    const countLimit = C.fociCountLimit(character);
    const forceLimit = C.fociForceLimit(character);

    const overCount = boundCount > countLimit;
    const overForce = forceSum > forceLimit;

    const priority = C.priorityRow(character, 'magic');
    const isAdept = priority?.type === 'adept';
    const showReagents = !isAdept;
    const showLodges = !isAdept;

    function onAddFocus(payload) {
        if (inCareer) {
            const karmaCost = M.focusKarmaCost(payload.categoryKey, payload.force);
            const nuyenCost = M.focusNuyenCost(payload.categoryKey, payload.force);
            if (!window.CareerGear.canAfford(character, nuyenCost)) {
                alert(`Not enough nuyen: this focus costs ${nuyenCost.toLocaleString()}¥.`);
                return;
            }
            if (C.pendingKarmaDelta(character) + karmaCost > C.karmaCurrent(character)) {
                alert(`Not enough karma: bonding this focus costs ${karmaCost} karma.`);
                return;
            }
            const cat = M.findFocusCategory(payload.categoryKey);
            const name = (payload.name || '').trim()
                || `${cat?.label || 'Focus'} F${payload.force}`;
            onChange(C.stagePendingGear(character, {
                kind: 'focus',
                name,
                nuyenCost,
                karmaCost,
                extras: payload,
            }));
        } else {
            onChange(C.addFocus(character, payload));
        }
        setFocusPickerOpen(false);
        setCustomFocusOpen(false);
    }
    function onUpdateFocus(id, patch) {
        if (inCareer) return;
        onChange(C.updateFocus(character, id, patch));
    }
    function onRemoveFocus(id) {
        if (inCareer) { alert("Log lost/unbound foci in the career log."); return; }
        onChange(C.removeFocus(character, id));
    }
    function onAddReagent(payload) {
        if (inCareer) {
            const cost = payload.nuyen || 0;
            if (!window.CareerGear.canAfford(character, cost)) {
                alert(`Not enough nuyen: reagents cost ${cost.toLocaleString()}¥.`);
                return;
            }
            onChange(C.stagePendingGear(character, {
                kind: 'reagent',
                name: `${payload.amount || 0} drams ${payload.grade || 'refined'}`,
                nuyenCost: cost,
                extras: payload,
            }));
        } else {
            onChange(C.addReagent(character, payload));
        }
        setReagentPickerOpen(false);
    }
    function onUpdateReagent(id, patch) {
        if (inCareer) return;
        onChange(C.updateReagent(character, id, patch));
    }
    function onRemoveReagent(id) {
        if (inCareer) { alert("Consumed reagents should be logged in the career log."); return; }
        onChange(C.removeReagent(character, id));
    }
    function onAddLodge(payload) {
        if (inCareer) {
            const cost = payload.nuyen || (payload.force * 500);
            if (!window.CareerGear.canAfford(character, cost)) {
                alert(`Not enough nuyen: a Force ${payload.force} lodge costs ${cost.toLocaleString()}¥.`);
                return;
            }
            onChange(C.stagePendingGear(character, {
                kind: 'lodge',
                name: `Lodge F${payload.force}${payload.name ? ` — ${payload.name}` : ''}`,
                nuyenCost: cost,
                extras: payload,
            }));
        } else {
            onChange(C.addLodge(character, payload));
        }
        setLodgeOpen(false);
    }
    function onUpdateLodge(id, patch) {
        if (inCareer) return;
        onChange(C.updateLodge(character, id, patch));
    }
    function onRemoveLodge(id) {
        if (inCareer) { alert("Lodge destruction should be logged in the career log."); return; }
        onChange(C.removeLodge(character, id));
    }
    function onUnstage(tempId) {
        onChange(C.unstagePendingGear(character, tempId));
    }

    return (
        <>
            {/* Limits banner — shown for all awakened */}
            <div className="card">
                <div className="card-body">
                    <div className="foci-limits-ribbon">
                        <div className="fl-stat">
                            <div className="fl-label">Bonded foci</div>
                            <div className="fl-value" style={{ color: overCount ? 'var(--bad)' : 'var(--text-primary)' }}>
                                {boundCount}<span className="muted" style={{ fontSize: 13 }}>/{countLimit}</span>
                            </div>
                            <div className="fl-hint">Max = Magic</div>
                        </div>
                        <div className="fl-stat">
                            <div className="fl-label">Sum of Forces</div>
                            <div className="fl-value" style={{ color: overForce ? 'var(--bad)' : 'var(--text-primary)' }}>
                                {forceSum}<span className="muted" style={{ fontSize: 13 }}>/{forceLimit}</span>
                            </div>
                            <div className="fl-hint">Max = Magic × 5</div>
                        </div>
                        <div className="fl-stat">
                            <div className="fl-label">Karma on foci</div>
                            <div className="fl-value accent">{C.fociKarmaSpent(character)}</div>
                            <div className="fl-hint">Deducted from starting 25</div>
                        </div>
                        <div className="fl-stat">
                            <div className="fl-label">Nuyen on magical eq.</div>
                            <div className="fl-value accent">
                                {(C.fociNuyenSpent(character) + C.reagentsNuyenSpent(character) + C.lodgesNuyenSpent(character)).toLocaleString()}¥
                            </div>
                            <div className="fl-hint">Counts toward gear budget</div>
                        </div>
                    </div>
                    {(overCount || overForce) && (
                        <div className="foci-warning">
                            {overCount && <div>Bonded count ({boundCount}) exceeds your Magic ({countLimit}).</div>}
                            {overForce && <div>Sum of Forces ({forceSum}) exceeds your Magic × 5 ({forceLimit}).</div>}
                        </div>
                    )}
                </div>
            </div>

            {/* FOCI section */}
            <div className="card">
                <div className="card-header">
                    <h3 className="card-title">Foci</h3>
                    <div className="card-actions">
                        <button className="btn btn-primary" onClick={() => setFocusPickerOpen(true)}>+ Browse Focus Types</button>
                        {!inCareer && (
                            <button className="btn btn-ghost" onClick={() => setCustomFocusOpen(true)}>+ Custom Focus</button>
                        )}
                    </div>
                </div>
                <div className="card-body" style={{ padding: 0 }}>
                    {foci.length === 0 && pendingFoci.length === 0 ? (
                        <div className="spell-empty">
                            No foci bonded yet. Foci are astral constructs that channel mana for specific tasks —
                            spellcasting, summoning, weapons, etc. Each focus must be bonded with Karma before it works.
                            {isAdept && ' Adepts can only bond Qi foci (adept powers) and Weapon foci.'}
                        </div>
                    ) : (
                        <>
                            {foci.length > 0 && (
                                <FocusList
                                    foci={foci}
                                    onUpdate={onUpdateFocus}
                                    onRemove={onRemoveFocus}
                                    inCareer={inCareer}
                                />
                            )}
                            {pendingFoci.map(pg => (
                                <div key={pg.tempId} className="focus-row pending-new" style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 20px', borderTop: '1px solid var(--border-subtle)' }}>
                                    <div style={{ flex: 1 }}>
                                        <div className="mono" style={{ color: 'var(--accent)' }}>
                                            {pg.name} (Force {pg.extras?.force || 1})
                                        </div>
                                        <div className="muted mono" style={{ fontSize: 11 }}>
                                            {pg.karmaCost} karma + {(pg.nuyenCost || 0).toLocaleString()}¥ · pending
                                        </div>
                                    </div>
                                    <button className="btn-row-remove" onClick={() => onUnstage(pg.tempId)} title="Discard pending">×</button>
                                </div>
                            ))}
                        </>
                    )}
                </div>
            </div>

            {/* REAGENTS section — not for adepts */}
            {showReagents && (
                <div className="card">
                    <div className="card-header">
                        <h3 className="card-title">Reagents</h3>
                        <div className="card-actions">
                            <button className="btn btn-primary" onClick={() => setReagentPickerOpen(true)}>+ Buy Reagents</button>
                        </div>
                    </div>
                    <div className="card-body" style={{ padding: 0 }}>
                        {reagents.length === 0 && pendingReagents.length === 0 ? (
                            <div className="spell-empty">
                                No reagents stocked. Each dram of reagents lets you cast a spell at a Force higher than
                                your Magic cap (up to Magic × 2). Three grades: raw (cheap, bulky), refined, radical (illegal).
                            </div>
                        ) : (
                            <>
                                {reagents.length > 0 && (
                                    <ReagentList
                                        reagents={reagents}
                                        onUpdate={onUpdateReagent}
                                        onRemove={onRemoveReagent}
                                        inCareer={inCareer}
                                    />
                                )}
                                {pendingReagents.map(pg => (
                                    <div key={pg.tempId} className="reagent-row pending-new" style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 20px', borderTop: '1px solid var(--border-subtle)' }}>
                                        <div style={{ flex: 1 }}>
                                            <div className="mono" style={{ color: 'var(--accent)' }}>{pg.name}</div>
                                            <div className="muted mono" style={{ fontSize: 11 }}>
                                                {(pg.nuyenCost || 0).toLocaleString()}¥ · pending
                                            </div>
                                        </div>
                                        <button className="btn-row-remove" onClick={() => onUnstage(pg.tempId)} title="Discard pending">×</button>
                                    </div>
                                ))}
                            </>
                        )}
                    </div>
                </div>
            )}

            {/* LODGES section — not for adepts */}
            {showLodges && (
                <div className="card">
                    <div className="card-header">
                        <h3 className="card-title">Magical Lodges</h3>
                        <div className="card-actions">
                            <button className="btn btn-primary" onClick={() => setLodgeOpen(true)}>+ Add Lodge</button>
                        </div>
                    </div>
                    <div className="card-body" style={{ padding: 0 }}>
                        {lodges.length === 0 && pendingLodges.length === 0 ? (
                            <div className="spell-empty">
                                No lodges prepared. Lodges are required to bind spirits and perform rituals.
                                Force can be up to your Magic attribute. Cost: 500¥ × Force.
                            </div>
                        ) : (
                            <>
                                {lodges.length > 0 && (
                                    <LodgeList
                                        lodges={lodges}
                                        onUpdate={onUpdateLodge}
                                        onRemove={onRemoveLodge}
                                        maxForce={C.specialAttributeValue(character, 'mag')}
                                        inCareer={inCareer}
                                    />
                                )}
                                {pendingLodges.map(pg => (
                                    <div key={pg.tempId} className="lodge-row pending-new" style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 20px', borderTop: '1px solid var(--border-subtle)' }}>
                                        <div style={{ flex: 1 }}>
                                            <div className="mono" style={{ color: 'var(--accent)' }}>{pg.name}</div>
                                            <div className="muted mono" style={{ fontSize: 11 }}>
                                                {(pg.nuyenCost || 0).toLocaleString()}¥ · pending
                                            </div>
                                        </div>
                                        <button className="btn-row-remove" onClick={() => onUnstage(pg.tempId)} title="Discard pending">×</button>
                                    </div>
                                ))}
                            </>
                        )}
                    </div>
                </div>
            )}

            <div className="phase-note" style={{ marginTop: 20 }}>
                <strong>Phase 5d.</strong> Magical Equipment: foci (7 categories with per-Force karma/nuyen/avail scaling),
                reagents (3 grades per dram), and lodges (Force = Magic, 500¥×Force). Focus bonding and force-sum limits
                are enforced visually per CRB p. 317. Adepts see Qi and Weapon foci only; mundane and technomancer
                characters don't reach this tab.
            </div>

            {focusPickerOpen && (
                <FocusPickerModal
                    character={character}
                    onPick={onAddFocus}
                    onClose={() => setFocusPickerOpen(false)}
                />
            )}
            {customFocusOpen && (
                <CustomFocusDialog
                    character={character}
                    onSubmit={onAddFocus}
                    onClose={() => setCustomFocusOpen(false)}
                />
            )}
            {reagentPickerOpen && (
                <ReagentPickerModal
                    onAdd={onAddReagent}
                    onClose={() => setReagentPickerOpen(false)}
                />
            )}
            {lodgeOpen && (
                <LodgeDialog
                    character={character}
                    onSubmit={onAddLodge}
                    onClose={() => setLodgeOpen(false)}
                />
            )}
        </>
    );
};

/* -------- Focus list row table -------- */
window.FocusList = function FocusList({ foci, onUpdate, onRemove, inCareer }) {
    const M = SR5_MAGIC;
    return (
        <>
            <div className="focus-head">
                <span>Name</span>
                <span>Category</span>
                <span>Force</span>
                <span>Karma</span>
                <span>Nuyen</span>
                <span>Avail</span>
                <span>Bonded</span>
                <span></span>
            </div>
            {foci.map(f => {
                const cat = M.findFocusCategory(f.categoryKey);
                return (
                    <div key={f.id} className={`focus-row focus-cat-${f.categoryKey}`}>
                        <div className="focus-name">
                            {f.name}
                            {f.subtypeKey && cat?.subtypes && (
                                <span className="focus-subtype">
                                    ({cat.subtypes.find(s => s.key === f.subtypeKey)?.label})
                                </span>
                            )}
                        </div>
                        <div className="focus-cat">{cat?.label || f.categoryKey}</div>
                        <div className="focus-force">
                            {inCareer ? (
                                <span className="mono">{f.force}</span>
                            ) : (
                                <RatingStepper
                                    value={f.force}
                                    min={1}
                                    max={12}
                                    onChange={(n) => onUpdate(f.id, { force: n })}
                                />
                            )}
                        </div>
                        <div className="focus-karma">{f.karmaCost}</div>
                        <div className="focus-nuyen">{(f.nuyenCost || 0).toLocaleString()}¥</div>
                        <div className="focus-avail">{f.avail}</div>
                        <div className="focus-bonded">
                            <input type="checkbox"
                                   checked={f.bonded !== false}
                                   disabled={inCareer}
                                   onChange={e => onUpdate(f.id, { bonded: e.target.checked })}
                                   title={inCareer ? "Bonded status locked in career" : "Toggle bonded (karma paid)"} />
                        </div>
                        <button className="btn-row-remove"
                                onClick={() => onRemove(f.id)}
                                title={inCareer ? "Use career log for lost/unbound foci" : "Remove"}>×</button>
                    </div>
                );
            })}
        </>
    );
};

/* -------- Reagent list -------- */
window.ReagentList = function ReagentList({ reagents, onUpdate, onRemove, inCareer }) {
    const M = SR5_MAGIC;
    return (
        <>
            <div className="reagent-head">
                <span>Grade</span>
                <span>Drams</span>
                <span>Cost</span>
                <span>Avail</span>
                <span></span>
            </div>
            {reagents.map(r => {
                const g = M.findReagentGrade(r.gradeKey);
                return (
                    <div key={r.id} className={`reagent-row reagent-grade-${r.gradeKey}`}>
                        <div className="reagent-grade-name">{g?.label || r.gradeKey}</div>
                        <div className="reagent-drams">
                            {inCareer ? (
                                <span className="mono">{r.drams}</span>
                            ) : (
                                <input type="number"
                                       min="0"
                                       value={r.drams}
                                       onChange={e => onUpdate(r.id, { drams: parseInt(e.target.value, 10) || 0 })}
                                       style={{ width: 70 }} />
                            )}
                        </div>
                        <div className="reagent-cost">{(r.nuyen || 0).toLocaleString()}¥</div>
                        <div className="reagent-avail">{g?.avail || '—'}</div>
                        <button className="btn-row-remove"
                                onClick={() => onRemove(r.id)}
                                title={inCareer ? "Log consumed reagents in career log" : "Remove"}>×</button>
                    </div>
                );
            })}
        </>
    );
};

/* -------- Lodge list -------- */
window.LodgeList = function LodgeList({ lodges, onUpdate, onRemove, maxForce, inCareer }) {
    return (
        <>
            <div className="lodge-head">
                <span>Lodge</span>
                <span>Force</span>
                <span>Cost</span>
                <span>Avail</span>
                <span></span>
            </div>
            {lodges.map(l => (
                <div key={l.id} className="lodge-row">
                    <div className="lodge-name">
                        {l.tradition ? `${l.tradition} Lodge` : 'Magical Lodge'}
                    </div>
                    <div className="lodge-force">
                        {inCareer ? (
                            <span className="mono">{l.force}</span>
                        ) : (
                            <RatingStepper
                                value={l.force}
                                min={1}
                                max={maxForce || 6}
                                onChange={(n) => onUpdate(l.id, { force: n })}
                            />
                        )}
                    </div>
                    <div className="lodge-cost">{(l.nuyen || 0).toLocaleString()}¥</div>
                    <div className="lodge-avail">{l.avail}</div>
                    <button className="btn-row-remove"
                            onClick={() => onRemove(l.id)}
                            title={inCareer ? "Use career log for destroyed lodges" : "Remove"}>×</button>
                </div>
            ))}
        </>
    );
};
