// BUILD pack — Components (rail). The roll-up of every part any BOM names:
// on hand / reorder point / supplier / link editable inline (manager+), a
// Low-only filter (selection = segmented pill, colour only as a legend dot —
// UI taste rule), and "Plan a build": N × product → need / have / short,
// grouped by supplier. Plan is read-time math on the server; nothing written.

const ComponentsView = ({ currentUser, openHint }) => {
    const canEdit = currentUser.role !== 'rep';
    const [rows, setRows]         = React.useState([]);
    const [loading, setLoading]   = React.useState(true);
    const [loadError, setLoadError] = React.useState(false);
    const [err, setErr]           = React.useState('');
    const [lowOnly, setLowOnly]   = React.useState(false);
    const [q, setQ]               = React.useState('');
    const [draft, setDraft]       = React.useState({});   // id -> partial edits
    const [merging, setMerging]   = React.useState(null); // component being merged away
    const [planOpen, setPlanOpen] = React.useState(false);

    const load = React.useCallback(async () => {
        setLoading(true);
        try { setRows(await api.getComponents()); setLoadError(false); }
        catch { setLoadError(true); }
        setLoading(false);
    }, []);
    React.useEffect(() => { load(); }, [load]);
    // ⌘K pick → pre-fill the search box so the row is on screen.
    React.useEffect(() => { if (openHint?.hint?.q != null) { setQ(openHint.hint.q); setLowOnly(false); } }, [openHint?.nonce]);

    const lowCount = rows.filter(r => r.low).length;
    const shown = rows.filter(r => (!lowOnly || r.low) &&
        (!q || `${r.name} ${r.value} ${r.supplier || ''}`.toLowerCase().includes(q.toLowerCase())));

    const setField = (id, k, v) => setDraft(d => ({ ...d, [id]: { ...(d[id] || {}), [k]: v } }));
    const commit = async (id) => {
        const patch = draft[id]; if (!patch) return;
        setErr('');
        try {
            const saved = await api.updateComponent(id, patch);
            setRows(rs => rs.map(r => r.id === id ? saved : r));
            setDraft(d => { const n = { ...d }; delete n[id]; return n; });
        } catch (e) { setErr(e.message || 'Save failed.'); }
    };
    const remove = async (r) => {
        if (!await confirmAction({ title: `Delete ${r.name}${r.value ? ' ' + r.value : ''}?`, message: 'Only possible when no product uses it.', confirmLabel: 'Delete' })) return;
        setErr('');
        try { await api.deleteComponent(r.id); setRows(rs => rs.filter(x => x.id !== r.id)); }
        catch (e) { setErr(e.message || 'Delete failed.'); }
    };
    const merge = async (intoId) => {
        setErr('');
        try { await api.mergeComponent(intoId, merging.id); setMerging(null); await load(); }
        catch (e) { setErr(e.message || 'Merge failed.'); }
    };

    const val = (r, k) => (draft[r.id] && draft[r.id][k] !== undefined) ? draft[r.id][k] : (r[k] ?? '');
    const cell = (r, k, type = 'text', style = {}) => canEdit
        ? <input className="form-input" type={type} min={type === 'number' ? 0 : undefined} step={type === 'number' ? 1 : undefined}
                 value={val(r, k)} style={{ ...style, minWidth: 0 }}
                 onChange={e => setField(r.id, k, e.target.value)} onBlur={() => commit(r.id)}
                 onKeyDown={e => { if (e.key === 'Enter') e.target.blur(); }} />
        : <span>{r[k] ?? '—'}</span>;

    return (
        <div className="view-content">
            <div className="list-view-header">
                <div className="list-view-actions" style={{ display: 'flex', gap: '0.75rem', alignItems: 'center', flexWrap: 'wrap' }}>
                    <div className="seg-control" role="tablist" aria-label="Filter">
                        <button type="button" role="tab" aria-selected={!lowOnly} className={`seg-btn ${!lowOnly ? 'on' : ''}`} onClick={() => setLowOnly(false)}>
                            All <span className="seg-n">{rows.length}</span></button>
                        <button type="button" role="tab" aria-selected={lowOnly} className={`seg-btn ${lowOnly ? 'on' : ''}`} onClick={() => setLowOnly(true)}>
                            <span style={{ width: 8, height: 8, borderRadius: 4, background: 'var(--warning, #f59e0b)', display: 'inline-block' }}></span>
                            Low <span className="seg-n">{lowCount}</span></button>
                    </div>
                    <input className="form-input" style={{ width: 220 }} placeholder="Search parts…" value={q} onChange={e => setQ(e.target.value)} />
                </div>
                <div className="list-view-actions">
                    <button type="button" className={`btn ${planOpen ? 'btn-secondary' : 'btn-primary'}`} onClick={() => setPlanOpen(o => !o)}>
                        <i className="fas fa-calculator"></i> {planOpen ? 'Close planner' : 'Plan a build'}
                    </button>
                </div>
            </div>

            {err && <div className="api-error">{err}</div>}
            {loadError && !loading && <LoadErrorBanner what="components" hasData={rows.length > 0} onRetry={load} />}
            {planOpen && <BuildPlanner onClose={() => setPlanOpen(false)} />}

            {loading ? <div className="loading-state"><i className="fas fa-spinner fa-spin"></i><p>Loading…</p></div> : (
                <table className="data-table">
                    <thead><tr>
                        <th>Part</th><th>Value</th><th>Used in</th><th style={{ width: 110 }}>On hand</th><th style={{ width: 110 }}>Reorder at</th>
                        <th>Supplier</th><th>Link</th>{canEdit && <th style={{ width: 80 }}></th>}
                    </tr></thead>
                    <tbody>
                        {shown.map(r => (
                            <tr key={r.id}>
                                <td>
                                    {r.low && <span title="At or below reorder point" style={{ width: 8, height: 8, borderRadius: 4, background: 'var(--warning, #f59e0b)', display: 'inline-block', marginRight: 6 }}></span>}
                                    {cell(r, 'name', 'text', { width: 160 })}
                                </td>
                                <td>{cell(r, 'value', 'text', { width: 110 })}</td>
                                <td style={{ color: 'var(--text-2)' }}>{r.used_in} product{r.used_in === 1 ? '' : 's'}</td>
                                <td>{cell(r, 'qty_on_hand', 'number', { width: 80 })}</td>
                                <td>{cell(r, 'reorder_point', 'number', { width: 80 })}</td>
                                <td>{cell(r, 'supplier', 'text', { width: 130 })}</td>
                                <td>
                                    {canEdit ? cell(r, 'link', 'text', { width: 160 })
                                             : (r.link ? <a href={r.link} target="_blank" rel="noopener noreferrer">Open</a> : '—')}
                                    {canEdit && r.link && <a href={r.link} target="_blank" rel="noopener noreferrer" title="Open link" style={{ marginLeft: 6 }}><i className="fas fa-external-link-alt"></i></a>}
                                </td>
                                {canEdit && <td style={{ whiteSpace: 'nowrap' }}>
                                    <button type="button" className="btn-icon" title="Merge into another part" onClick={() => setMerging(r)}><i className="fas fa-compress-alt"></i></button>
                                    <button type="button" className="btn-icon" title="Delete" onClick={() => remove(r)}><i className="fas fa-trash"></i></button>
                                </td>}
                            </tr>
                        ))}
                        {!shown.length && <tr><td colSpan={8} style={{ color: 'var(--text-3)' }}>
                            {rows.length ? 'Nothing matches.' : 'No components yet — open a product in Inventory and fill in its Components.'}
                        </td></tr>}
                    </tbody>
                </table>
            )}

            {merging && (
                <div className="modal-overlay" onClick={e => e.target === e.currentTarget && setMerging(null)}>
                    <div className="modal" style={{ maxWidth: 480 }}>
                        <div className="modal-header">
                            <h2 className="modal-title">Merge "{merging.name} {merging.value}" into…</h2>
                            <button className="modal-close-btn" onClick={() => setMerging(null)}>&times;</button>
                        </div>
                        <div className="modal-body">
                            <p style={{ fontSize: '0.85rem', color: 'var(--text-2)' }}>Every product using it switches to the part you pick; stock counts add together. This can't be undone.</p>
                            <div style={{ maxHeight: 300, overflowY: 'auto' }}>
                                {rows.filter(r => r.id !== merging.id).map(r => (
                                    <button key={r.id} type="button" className="btn btn-secondary" style={{ display: 'block', width: '100%', textAlign: 'left', marginBottom: 4 }} onClick={() => merge(r.id)}>
                                        {r.name} {r.value} <span style={{ color: 'var(--text-3)' }}>· {r.qty_on_hand} on hand</span>
                                    </button>
                                ))}
                            </div>
                        </div>
                    </div>
                </div>
            )}
        </div>
    );
};

// N × product → shortfall list, grouped by supplier. Products come from the
// core products API (only ones with a BOM matter, but the picker shows all —
// a product with no components simply contributes nothing).
const BuildPlanner = () => {
    const [products, setProducts] = React.useState([]);
    const [builds, setBuilds]     = React.useState([{ product_id: '', qty: 1 }]);
    const [lines, setLines]       = React.useState(null);
    const [err, setErr]           = React.useState('');
    const [shortOnly, setShortOnly] = React.useState(true);

    React.useEffect(() => {
        api.getProducts({ paged: 'true', limit: 500 }).then(r => setProducts(r.rows || r)).catch(() => setErr('Could not load products.'));
    }, []);

    const run = async () => {
        setErr('');
        const clean = builds.filter(b => b.product_id && Number(b.qty) >= 1).map(b => ({ product_id: Number(b.product_id), qty: Number(b.qty) }));
        if (!clean.length) { setLines([]); return; }
        try { setLines((await api.planBuild(clean)).lines); } catch (e) { setErr(e.message || 'Could not plan.'); }
    };
    const setB = (i, k, v) => setBuilds(bs => bs.map((b, j) => j === i ? { ...b, [k]: v } : b));

    const shown = (lines || []).filter(l => !shortOnly || l.short > 0);
    const groups = [];
    for (const l of shown) {
        const key = l.supplier || 'No supplier';
        let g = groups.find(x => x.key === key); if (!g) { g = { key, lines: [] }; groups.push(g); }
        g.lines.push(l);
    }
    const copyList = () => {
        const text = groups.map(g => `${g.key}\n` + g.lines.map(l => `  ${l.short} × ${l.name}${l.value ? ' ' + l.value : ''}${l.link ? '  ' + l.link : ''}`).join('\n')).join('\n');
        navigator.clipboard?.writeText(text);
    };

    return (
        <div className="form-fold" style={{ padding: '0.9rem', marginBottom: '1.25rem' }}>
            <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap', alignItems: 'flex-end' }}>
                {builds.map((b, i) => (
                    <div key={i} style={{ display: 'flex', gap: '0.4rem', alignItems: 'center' }}>
                        <input className="form-input" type="number" min="1" step="1" style={{ width: 70 }} value={b.qty} onChange={e => setB(i, 'qty', e.target.value)} />
                        <span>×</span>
                        <select className="form-input" style={{ width: 220 }} value={b.product_id} onChange={e => setB(i, 'product_id', e.target.value)}>
                            <option value="">Pick a product…</option>
                            {products.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                        </select>
                        {builds.length > 1 && <button type="button" className="btn-icon" onClick={() => setBuilds(bs => bs.filter((_, j) => j !== i))}><i className="fas fa-times"></i></button>}
                    </div>
                ))}
                <button type="button" className="btn btn-secondary btn-small" onClick={() => setBuilds(bs => [...bs, { product_id: '', qty: 1 }])}><i className="fas fa-plus"></i> Another product</button>
                <button type="button" className="btn btn-primary btn-small" onClick={run}>What do I need?</button>
            </div>
            {err && <div className="api-error" style={{ marginTop: '0.75rem' }}>{err}</div>}
            {lines && (
                <div style={{ marginTop: '1rem' }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.5rem' }}>
                        <div className="seg-control" role="tablist">
                            <button type="button" role="tab" className={`seg-btn ${shortOnly ? 'on' : ''}`} onClick={() => setShortOnly(true)}>To order <span className="seg-n">{lines.filter(l => l.short > 0).length}</span></button>
                            <button type="button" role="tab" className={`seg-btn ${!shortOnly ? 'on' : ''}`} onClick={() => setShortOnly(false)}>Everything needed <span className="seg-n">{lines.length}</span></button>
                        </div>
                        {shown.length > 0 && <button type="button" className="btn btn-secondary btn-small" onClick={copyList}><i className="fas fa-copy"></i> Copy list</button>}
                    </div>
                    {!shown.length && <p style={{ color: 'var(--text-3)', fontSize: '0.85rem' }}>{lines.length ? 'You have everything for this build.' : 'Those products have no components yet.'}</p>}
                    {groups.map(g => (
                        <div key={g.key} style={{ marginBottom: '0.75rem' }}>
                            <div style={{ fontWeight: 600, fontSize: '0.8rem', color: 'var(--text-2)', textTransform: 'uppercase', letterSpacing: '0.04em', margin: '0.5rem 0 0.25rem' }}>{g.key}</div>
                            <table className="data-table" style={{ boxShadow: 'none' }}>
                                <thead><tr><th>Part</th><th>Value</th><th>Need</th><th>Have</th><th>Short</th><th></th></tr></thead>
                                <tbody>{g.lines.map(l => (
                                    <tr key={l.component_id}>
                                        <td>{l.name}</td><td>{l.value}</td><td>{l.need}</td><td>{l.have}</td>
                                        <td style={{ fontWeight: l.short > 0 ? 700 : 400, color: l.short > 0 ? 'var(--hue-red)' : 'inherit' }}>{l.short}</td>
                                        <td>{l.link && <a href={l.link} target="_blank" rel="noopener noreferrer">Buy</a>}</td>
                                    </tr>))}</tbody>
                            </table>
                        </div>
                    ))}
                </div>
            )}
        </div>
    );
};
