const ProductsView = ({ currentUser }) => {
    const [products, setProducts] = React.useState([]);
    const [loading, setLoading]   = React.useState(true);
    const [search, setSearch]     = React.useState('');
    const [editing, setEditing]   = React.useState(null); // null | 'new' | product object
    const [saving, setSaving]     = React.useState(false);
    const [formErr, setFormErr]   = React.useState('');
    const canEdit = currentUser.role !== 'rep';

    const emptyForm = { sku: '', name: '', description: '', category: '', unit_price: '', unit_cost: '', stock_qty: 0, is_active: true, item_type: 'physical', billing_interval: 'month', tags_on_paid: [], tasks_on_paid: [] };
    const [form, setForm] = React.useState(emptyForm);

    // Controlled vocabularies (0042 rule: classification is picked, never
    // free-typed). Categories + tags are admin-defined in Settings; the form
    // offers exactly those lists.
    const [categories, setCategories] = React.useState([]);
    const [allTags, setAllTags]       = React.useState([]);

    // Tags-on-paid: toggleable chips from the Tags vocabulary, max 5.
    const toggleTag = (name) => setForm(p => {
        const cur = p.tags_on_paid || [];
        if (cur.some(t => t.toLowerCase() === name.toLowerCase()))
            return { ...p, tags_on_paid: cur.filter(t => t.toLowerCase() !== name.toLowerCase()) };
        return cur.length >= 5 ? p : { ...p, tags_on_paid: [...cur, name] };
    });

    // tasks_on_paid rows (0041) — the follow-up work a sale of this item creates.
    const addTask = () => setForm(p => ({ ...p, tasks_on_paid: [...(p.tasks_on_paid || []), { title: '', notes: '' }] }));
    const removeTask = (i) => setForm(p => ({ ...p, tasks_on_paid: (p.tasks_on_paid || []).filter((_, x) => x !== i) }));
    const setTaskField = (i, key, val) => setForm(p => ({
        ...p, tasks_on_paid: (p.tasks_on_paid || []).map((t, x) => x === i ? { ...t, [key]: val } : t),
    }));
    const set = k => e => setForm(p => ({ ...p, [k]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }));
    const [importMsg, setImportMsg] = React.useState('');
    const fileRef = React.useRef(null);

    // Item-type vocabulary (0034) — label + icon per type; the server derives
    // is_subscription from this, the form never sends the legacy flag.
    const TYPES = [
        ['physical',     'Physical',     'fa-box'],
        ['service',      'Service',      'fa-wrench'],
        ['subscription', 'Subscription', 'fa-rotate'],
        ['software',     'Software',     'fa-compact-disc'],
    ];
    const typeLabel = t => (TYPES.find(x => x[0] === t) || TYPES[0])[1];

    // A failed fetch must not render as an empty catalog — surface it (swallowed-error rule).
    const [loadError, setLoadError] = React.useState(false);
    // Server-paged + server-searched (IMP-1): search moved off the client so
    // paging and filtering compose — a match on page 4 is still findable.
    const PAGE = 100;
    const [total, setTotal] = React.useState(0);
    const load = (append) => {
        append = append === true; // guard: load is also an onClick callback (first arg = event)
        return api.getProducts({
            paged: 'true', limit: PAGE, offset: append ? products.length : 0,
            ...(search.trim() ? { search: search.trim() } : {}),
        }).then(({ rows, total }) => {
            setProducts(p => append ? [...p, ...rows] : rows);
            setTotal(total); setLoadError(false);
        }).catch(() => setLoadError(true)).finally(() => setLoading(false));
    };
    React.useEffect(() => {
        const t = setTimeout(() => { load(); }, 250); // debounced — no request per keystroke
        return () => clearTimeout(t);
    }, [search]);
    React.useEffect(() => {
        api.getProductCategories().then(setCategories).catch(() => {});
        api.getTags().then(setAllTags).catch(() => {});
    }, []);

    const startEdit = (p) => { setForm(p ? { ...p } : emptyForm); setEditing(p || 'new'); setFormErr(''); };

    const handleSave = async (e) => {
        e.preventDefault();
        if (!form.name) { setFormErr('Name is required.'); return; }
        setSaving(true); setFormErr('');
        try {
            const data = { ...form, unit_price: parseFloat(form.unit_price) || 0, unit_cost: form.unit_cost ? parseFloat(form.unit_cost) : null, stock_qty: parseInt(form.stock_qty) || 0, sku: form.sku || null };
            delete data.is_subscription;   // server derives it from item_type
            // Drop fully blank task rows (an added-then-abandoned row shouldn't 400)
            data.tasks_on_paid = (form.tasks_on_paid || []).filter(t => (t.title || '').trim() || (t.notes || '').trim());
            if (editing === 'new') await api.createProduct(data);
            else await api.updateProduct(editing.id, data);
            await load();
            setEditing(null);
        } catch(err) { setFormErr(err.message); }
        finally { setSaving(false); }
    };

    const handleDelete = async (p) => {
        if (!window.confirm(`Delete product "${p.name}"? This cannot be undone.`)) return;
        try { await api.deleteProduct(p.id); await load(); }
        catch(err) { alert(err.message); }
    };

    const handleStockAdj = async (p, delta) => {
        const newQty = Math.max(0, p.stock_qty + delta);
        try { await api.updateProduct(p.id, { stock_qty: newQty }); await load(); }
        catch(err) { alert(err.message); }
    };

    const filtered = products; // search happens server-side now (IMP-1)

    return (
        <div className="view-content">
            {/* No in-view title — the topbar names the view (rail UI rule).
                Search stretches like the Accounts toolbar; actions sit right. */}
            <div className="list-view-header">
                <div className="list-view-actions" style={{ flex: 1 }}>
                    <input className="form-input" style={{ flex: 1, minWidth: 200 }} placeholder="Search…" value={search} onChange={e => setSearch(e.target.value)} />
                    {canEdit && <button className="btn btn-secondary btn-small" title="Download inventory as CSV"
                        onClick={() => api.exportProductsCsv().catch(err => alert(err.message))}>
                        <i className="fas fa-file-export"></i> Export</button>}
                    {currentUser.role === 'admin' && <>
                        <button className="btn btn-secondary btn-small" title="Import/update items from a CSV file (upserts by SKU)"
                            onClick={() => fileRef.current && fileRef.current.click()}>
                            <i className="fas fa-file-import"></i> Import</button>
                        <input ref={fileRef} type="file" accept=".csv,text/csv" style={{ display: 'none' }}
                            onChange={async (e) => {
                                const f = e.target.files[0]; e.target.value = '';
                                if (!f) return;
                                const lineErrs = (errs) => errs.slice(0, 3).map(x => `line ${x.line} (${x.error})`).join('; ')
                                    + (errs.length > 3 ? `; +${errs.length - 3} more` : '');
                                try {
                                    const out = await api.importProductsCsv(await f.text());
                                    setImportMsg(`Imported: ${out.created} new, ${out.updated} updated` +
                                        ((out.created_categories || []).length ? `. Added categories: ${out.created_categories.join(', ')}` : '') +
                                        ((out.created_tags || []).length ? `. Added tags: ${out.created_tags.join(', ')}` : '') +
                                        (out.errors.length ? `. ${out.errors.length} row error(s): ${lineErrs(out.errors)}` : ''));
                                    await load();
                                } catch (err) {
                                    // Total failure still carries per-line detail — show it, don't eat it.
                                    const errs = err.body?.errors || [];
                                    setImportMsg(`Import failed: ${err.message}` +
                                        (errs.length ? ` — ${lineErrs(errs)}` : ''));
                                }
                            }} />
                    </>}
                    {canEdit && <button className="btn btn-primary btn-small" onClick={() => startEdit(null)}><i className="fas fa-plus"></i> Add Item</button>}
                </div>
            </div>
            {importMsg && <div className="api-success" style={{ margin: '0.5rem 0' }}>{importMsg}</div>}

            {loadError && !loading && (
                <LoadErrorBanner what="inventory" hasData={products.length > 0} onRetry={load} />
            )}

            {loading ? <div className="loading-state"><i className="fas fa-spinner fa-spin"></i><p>Loading…</p></div> : (
                <table className="data-table">
                    <thead>
                        <tr>
                            <th>SKU</th><th>Name</th><th>Type</th><th>Category</th><th>Price</th><th>Cost</th><th>Stock</th><th>Status</th>
                            {canEdit && <th></th>}
                        </tr>
                    </thead>
                    <tbody>
                        {filtered.length === 0 ? (
                            <tr><td colSpan={canEdit ? 9 : 8} style={{ textAlign: 'center', color: '#6b7280', padding: '2rem' }}>No products yet</td></tr>
                        ) : filtered.map(p => (
                            <tr key={p.id}>
                                <td style={{ color: '#6b7280', fontSize: '0.8125rem' }}>{p.sku || '—'}</td>
                                                <td style={{ fontWeight: 500 }}>{p.name}
                                    {p.description && <div style={{ fontSize: '0.75rem', color: '#6b7280' }}>{p.description.slice(0, 60)}{p.description.length > 60 ? '…' : ''}</div>}</td>
                                <td style={{ color: '#6b7280', fontSize: '0.8125rem' }}>
                                    {typeLabel(p.item_type)}
                                    {p.item_type === 'subscription' && <span style={{ color: 'var(--accent, #3b82f6)' }}> / {p.billing_interval === 'year' ? 'yr' : 'mo'}</span>}
                                </td>
                                <td style={{ color: '#6b7280' }}>{p.category || '—'}</td>
                                <td>${parseFloat(p.unit_price).toFixed(2)}</td>
                                <td style={{ color: '#6b7280' }}>{p.unit_cost ? '$' + parseFloat(p.unit_cost).toFixed(2) : '—'}</td>
                                <td>
                                    <div style={{ display: 'flex', alignItems: 'center', gap: '0.375rem' }}>
                                        {canEdit && <button className="btn-icon-sm" onClick={() => handleStockAdj(p, -1)} title="Remove 1"><i className="fas fa-minus"></i></button>}
                                        <span style={{ fontWeight: 600, minWidth: '2rem', textAlign: 'center', color: p.stock_qty < 5 ? '#ef4444' : '#0f172a' }}>{p.stock_qty}</span>
                                        {canEdit && <button className="btn-icon-sm" onClick={() => handleStockAdj(p, 1)} title="Add 1"><i className="fas fa-plus"></i></button>}
                                    </div>
                                </td>
                                <td><span className={`status-badge ${p.is_active ? 'active' : 'inactive'}`}>{p.is_active ? 'Active' : 'Inactive'}</span></td>
                                {canEdit && (
                                    <td>
                                        <div style={{ display: 'flex', gap: '0.25rem' }}>
                                            <button className="btn-icon-sm" onClick={() => startEdit(p)} title="Edit"><i className="fas fa-pencil-alt"></i></button>
                                            <button className="btn-icon-sm danger" onClick={() => handleDelete(p)} title="Delete"><i className="fas fa-trash"></i></button>
                                        </div>
                                    </td>
                                )}
                            </tr>
                        ))}
                    </tbody>
                </table>
            )}

            {!loading && products.length < total && (
                <div style={{ textAlign: 'center', padding: '0.75rem' }}>
                    <button className="btn btn-secondary btn-small" onClick={() => load(true)}>
                        <i className="fas fa-angles-down"></i> Load more ({products.length} of {total})
                    </button>
                </div>
            )}

            {editing && (
                <div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && setEditing(null)}>
                    <div className="modal modal-medium">
                        <div className="modal-header">
                            <h2 className="modal-title">{editing === 'new' ? 'New Product' : `Edit: ${editing.name}`}</h2>
                            <button className="modal-close-btn" onClick={() => setEditing(null)}>&times;</button>
                        </div>
                        <div className="modal-body">
                            <form onSubmit={handleSave}>
                                {formErr && <div className="api-error">{formErr}</div>}
                                <div className="form-grid">
                                    <div className="form-group full-width"><label className="form-label">Name *</label><input className="form-input" value={form.name} onChange={set('name')} required /></div>
                                    <div className="form-group"><label className="form-label">SKU</label><input className="form-input" value={form.sku || ''} onChange={set('sku')} placeholder="Optional" /></div>
                                    <div className="form-group">
                                        <label className="form-label">Category</label>
                                        <select className="form-input" value={form.category || ''} onChange={set('category')}>
                                            <option value="">—</option>
                                            {/* An edited product may carry a label deleted from the vocabulary — keep it selectable so opening the form doesn't silently clear it. */}
                                            {form.category && !categories.some(c => c.name === form.category) && <option value={form.category}>{form.category}</option>}
                                            {categories.map(c => <option key={c.id} value={c.name}>{c.name}</option>)}
                                        </select>
                                        {categories.length === 0 && (
                                            <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', marginTop: '0.35rem' }}>
                                                Define categories in Settings → Product Categories.
                                            </p>
                                        )}
                                    </div>
                                    <div className="form-group"><label className="form-label">Unit Price</label><input type="number" step="0.01" className="form-input" value={form.unit_price} onChange={set('unit_price')} /></div>
                                    <div className="form-group"><label className="form-label">Unit Cost</label><input type="number" step="0.01" className="form-input" value={form.unit_cost || ''} onChange={set('unit_cost')} /></div>
                                    <div className="form-group"><label className="form-label">Stock Qty</label><input type="number" className="form-input" value={form.stock_qty} onChange={set('stock_qty')} /></div>
                                    <div className="form-group full-width">
                                        <label className="form-label">Type</label>
                                        {/* chips, not checkboxes (house rule) — subscription items mark every
                                            quote/invoice that carries them as a subscription doc */}
                                        <div className="tag-filter-row">
                                            {TYPES.map(([val, lbl, icon]) => (
                                                <span key={val} className="tag-pill tag-filter-chip"
                                                      style={form.item_type === val ? { background: 'var(--accent, #3b82f6)', color: '#fff' } : {}}
                                                      onClick={() => setForm(prev => ({ ...prev, item_type: val }))}>
                                                    <i className={`fas ${icon}`} style={{ marginRight: '0.3rem' }}></i>{lbl}
                                                </span>
                                            ))}
                                        </div>
                                    </div>
                                    {form.item_type === 'subscription' && (
                                        <div className="form-group">
                                            <label className="form-label">Billing interval</label>
                                            <div className="tag-filter-row">
                                                {[['month', 'Monthly'], ['year', 'Yearly']].map(([val, lbl]) => (
                                                    <span key={val} className="tag-pill tag-filter-chip"
                                                          style={(form.billing_interval || 'month') === val ? { background: 'var(--accent, #3b82f6)', color: '#fff' } : {}}
                                                          onClick={() => setForm(prev => ({ ...prev, billing_interval: val }))}>
                                                        {lbl}
                                                    </span>
                                                ))}
                                            </div>
                                        </div>
                                    )}
                                    <div className="form-group" style={{ justifyContent: 'flex-end' }}>
                                        <label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', marginTop: '1.5rem' }}>
                                            <input type="checkbox" checked={form.is_active} onChange={set('is_active')} /> Active
                                        </label>
                                    </div>
                                    <div className="form-group full-width">
                                        <label className="form-label">Tags applied when paid</label>
                                        <div className="tag-filter-row" style={{ alignItems: 'center' }}>
                                            {/* Vocabulary chips (0042 rule): pick from Settings → Tags, no free typing. A selected tag since deleted from the vocabulary still shows (form.tags_on_paid drives the render) so it can be unpicked. */}
                                            {[...allTags.map(t => t.name),
                                              ...(form.tags_on_paid || []).filter(t => !allTags.some(v => v.name.toLowerCase() === t.toLowerCase()))]
                                              .map(name => {
                                                const on = (form.tags_on_paid || []).some(t => t.toLowerCase() === name.toLowerCase());
                                                return (
                                                    <span key={name} className="tag-pill tag-filter-chip"
                                                          style={on ? { background: 'var(--accent, #3b82f6)', color: '#fff', cursor: 'pointer' }
                                                                    : { cursor: 'pointer', opacity: 0.75 }}
                                                          title={on ? 'Remove' : 'Apply on first payment'}
                                                          onClick={() => toggleTag(name)}>
                                                        {name}{on && <i className="fas fa-check" style={{ marginLeft: '0.3rem', fontSize: '0.65rem' }}></i>}
                                                    </span>
                                                );
                                            })}
                                            {allTags.length === 0 && (
                                                <span style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>
                                                    No tags defined yet — create them in Settings → Tags.
                                                </span>
                                            )}
                                        </div>
                                        <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', marginTop: '0.35rem' }}>
                                            When a customer pays for this item — including through a quote's accept
                                            link — the selected tags land on their account automatically. Up to 5.
                                        </p>
                                    </div>
                                    <div className="form-group full-width">
                                        <label className="form-label">Tasks opened on first payment</label>
                                        {(form.tasks_on_paid || []).map((t, i) => (
                                            <div key={i} style={{ display: 'flex', gap: '0.5rem', marginBottom: '0.4rem' }}>
                                                <input className="form-input" style={{ flex: '1 1 40%' }} maxLength={120}
                                                       value={t.title} placeholder="Task title — e.g. Deploy site and follow up"
                                                       onChange={e => setTaskField(i, 'title', e.target.value)} />
                                                <input className="form-input" style={{ flex: '1 1 50%' }} maxLength={500}
                                                       value={t.notes || ''} placeholder="Notes for the rep (optional)"
                                                       onChange={e => setTaskField(i, 'notes', e.target.value)} />
                                                <button type="button" className="btn btn-secondary btn-small" title="Remove task"
                                                        onClick={() => removeTask(i)}><i className="fas fa-times"></i></button>
                                            </div>
                                        ))}
                                        {(form.tasks_on_paid || []).length < 5 && (
                                            <button type="button" className="btn btn-secondary btn-small" onClick={addTask}>
                                                <i className="fas fa-plus"></i> Add task
                                            </button>
                                        )}
                                        <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', marginTop: '0.35rem' }}>
                                            The follow-up work a sale of this item creates. Each opens as an urgent,
                                            sign-off-gated task on the account's rep when the first payment lands.
                                            No tasks declared anywhere on the sale — a generic follow-up task opens instead.
                                        </p>
                                    </div>
                                    <div className="form-group full-width"><label className="form-label">Description</label><textarea className="form-input form-textarea" value={form.description || ''} onChange={set('description')} /></div>
                                </div>
                                <div className="btn-group">
                                    <button type="button" className="btn btn-secondary" onClick={() => setEditing(null)} disabled={saving}>Cancel</button>
                                    <button type="submit" className="btn btn-primary" disabled={saving}>{saving ? <><i className="fas fa-spinner fa-spin"></i> Saving…</> : <><i className="fas fa-check"></i> Save Product</>}</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            )}
        </div>
    );
};
