// Quote / Invoice detail modal — open an existing document, edit its line
// items, change status per the never-delete lifecycle, download the PDF,
// and email it to the customer. One component for both doc kinds: they
// differ only in labels, status vocabulary, and the payments panel.
//
// Lifecycle rules enforced here (mirror the backend):
//   - Quotes: items editable while draft or sent (a quote is a negotiation
//     document); issued quotes are cancelled, never deleted.
//   - Invoices: items editable only in draft — an issued invoice is a
//     financial record; fix mistakes by voiding and reissuing.
//   - paid/partial are ledger-derived, never set by hand.

const DOC_KIND = {
    quote: {
        noun: 'Quote', numberKey: 'quote_number', dateKey: 'expiry_date', dateLabel: 'Valid until',
        manualStatuses: ['draft', 'sent', 'accepted', 'declined', 'expired', 'cancelled'],
        deadStatus: 'cancelled', deadVerb: 'Cancel',
        canEditItems: (s) => s === 'draft' || s === 'sent',
    },
    invoice: {
        noun: 'Invoice', numberKey: 'invoice_number', dateKey: 'due_date', dateLabel: 'Due date',
        manualStatuses: ['draft', 'sent', 'overdue', 'void'],
        deadStatus: 'void', deadVerb: 'Void',
        canEditItems: (s) => s === 'draft',
    },
};

const DocDetailModal = ({ kind, docId, currentUser, onClose, onChanged }) => {
    const K = DOC_KIND[kind];
    const [doc, setDoc]         = React.useState(null);
    const [products, setProducts] = React.useState([]);
    const [err, setErr]         = React.useState('');
    const [busy, setBusy]       = React.useState(false);

    // Line-item editing: local draft rows keyed by item id ('new' = the add row).
    const [editRows, setEditRows] = React.useState({});
    const [notesDraft, setNotesDraft] = React.useState(null); // null = not editing

    // Send panel
    const [showSend, setShowSend]   = React.useState(false);
    const [sendTo, setSendTo]       = React.useState('');
    const [sendMsg, setSendMsg]     = React.useState('');
    const [sendResult, setSendResult] = React.useState(null);

    const getDoc = kind === 'quote' ? api.getQuote : api.getInvoice;

    const load = async () => {
        try {
            const d = await getDoc(docId);
            setDoc(d);
            // Prefill the send recipient from the doc's contact, best-effort.
            if (d.contact_id && !sendTo) {
                api.getContacts({ account_id: d.account_id }).then(cs => {
                    const c = cs.find(x => x.id === d.contact_id);
                    const email = c?.emails?.find(e => e.is_primary)?.value || c?.emails?.[0]?.value;
                    if (email) setSendTo(prev => prev || email);
                }).catch(() => {});
            }
        } catch (e) { setErr(e.message); }
    };

    React.useEffect(() => {
        load();
        api.getProducts({ active: 'true' }).then(setProducts).catch(() => {});
    }, [docId]);

    if (!doc) {
        return (
            <div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
                <div className="modal builder-modal"><div className="modal-body">
                    {err ? <div className="api-error">{err}</div>
                         : <div className="loading-state"><i className="fas fa-spinner fa-spin"></i><p>Loading…</p></div>}
                </div></div>
            </div>
        );
    }

    const number   = doc[K.numberKey];
    const isDead   = doc.status === 'void' || doc.status === 'cancelled';
    const editable = !isDead && K.canEditItems(doc.status);
    const money    = (v) => '$' + Number(v || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    const balance  = kind === 'invoice' ? Number(doc.total) - Number(doc.amount_paid || 0) : 0;

    const run = async (fn) => {
        setBusy(true); setErr('');
        try { await fn(); await load(); onChanged && onChanged(); }
        catch (e) { setErr(e.message); }
        finally { setBusy(false); }
    };

    // ── Handlers ─────────────────────────────────────────────────

    const handleStatus = (status) => {
        if (status === K.deadStatus && !window.confirm(
            `${K.deadVerb} ${number}? This can't be undone — the ${kind} stays on record as ${K.deadStatus}.`)) return;
        run(() => (kind === 'quote' ? api.updateQuote : api.updateInvoice)(doc.id, { status }));
    };

    const handleTax = (tax_rate) =>
        run(() => (kind === 'quote' ? api.updateQuote : api.updateInvoice)(doc.id, { tax_rate }));

    const handleNotesSave = () =>
        run(async () => {
            await (kind === 'quote' ? api.updateQuote : api.updateInvoice)(doc.id, { notes: notesDraft });
            setNotesDraft(null);
        });

    const itemApi = kind === 'quote'
        ? { add: api.addQuoteItem, update: api.updateQuoteItem, remove: api.deleteQuoteItem }
        : { add: api.addInvoiceItem, update: api.updateInvoiceItem, remove: api.deleteInvoiceItem };

    const startEdit = (item) => setEditRows(p => ({ ...p, [item.id]: {
        description: item.description, quantity: item.quantity, unit_price: item.unit_price, product_id: item.product_id,
    }}));
    const cancelEdit = (id) => setEditRows(p => { const n = { ...p }; delete n[id]; return n; });
    const setEditField = (id, key, val) => setEditRows(p => {
        const row = { ...p[id], [key]: val };
        if (key === 'product_id' && val) {
            const prod = products.find(x => x.id === parseInt(val));
            if (prod) { row.description = prod.name; row.unit_price = prod.unit_price; }
        }
        return { ...p, [id]: row };
    });
    const saveEdit = (id) => run(async () => {
        const row = editRows[id];
        const payload = {
            description: row.description,
            quantity: parseFloat(row.quantity || 0),
            unit_price: parseFloat(row.unit_price || 0),
            product_id: row.product_id ? parseInt(row.product_id) : null,
        };
        if (id === 'new') await itemApi.add(doc.id, payload);
        else await itemApi.update(doc.id, id, payload);
        cancelEdit(id);
    });
    const removeItem = (item) => {
        if (!window.confirm(`Remove "${item.description}" from ${number}?`)) return;
        run(() => itemApi.remove(doc.id, item.id));
    };

    const handleDownload = () =>
        run(() => api.downloadDocPdf(kind, doc.id, `${number}.pdf`));

    const handleSend = () => run(async () => {
        const result = await api.sendDoc(kind, doc.id, { to: sendTo, message: sendMsg });
        setSendResult(result);
        if (result.sent) { setShowSend(false); setSendMsg(''); }
    });

    // ── Row renderers ────────────────────────────────────────────

    const renderItemRow = (item) => {
        const edit = editRows[item.id];
        if (!edit) return (
            <tr key={item.id}>
                <td>{item.description}{item.product_sku ? <span style={{ color: 'var(--text-3)', fontSize: '0.75rem' }}> ({item.product_sku})</span> : null}</td>
                <td style={{ textAlign: 'right' }}>{Number(item.quantity)}</td>
                <td style={{ textAlign: 'right' }}>{money(item.unit_price)}</td>
                <td style={{ textAlign: 'right', fontWeight: 500 }}>{money(item.total)}</td>
                <td>
                    {editable && (
                        <div style={{ display: 'flex', gap: '0.25rem', justifyContent: 'flex-end' }}>
                            <button className="btn-icon-sm" title="Edit item" onClick={() => startEdit(item)}><i className="fas fa-pen"></i></button>
                            <button className="btn-icon-sm danger" title="Remove item" onClick={() => removeItem(item)}><i className="fas fa-times"></i></button>
                        </div>
                    )}
                </td>
            </tr>
        );
        return (
            <tr key={item.id}>
                <td>
                    <div style={{ display: 'flex', gap: '0.25rem' }}>
                        <select value={edit.product_id || ''} onChange={e => setEditField(item.id, 'product_id', e.target.value || null)} style={{ maxWidth: '40%' }}>
                            <option value="">Custom</option>
                            {products.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                        </select>
                        <input value={edit.description} onChange={e => setEditField(item.id, 'description', e.target.value)} placeholder="Description" />
                    </div>
                </td>
                <td><input type="number" min="0" step="any" value={edit.quantity} onChange={e => setEditField(item.id, 'quantity', e.target.value)} style={{ textAlign: 'right' }} /></td>
                <td><input type="number" min="0" step="0.01" value={edit.unit_price} onChange={e => setEditField(item.id, 'unit_price', e.target.value)} style={{ textAlign: 'right' }} /></td>
                <td style={{ textAlign: 'right' }}>{money(parseFloat(edit.quantity || 0) * parseFloat(edit.unit_price || 0))}</td>
                <td>
                    <div style={{ display: 'flex', gap: '0.25rem', justifyContent: 'flex-end' }}>
                        <button className="btn-icon-sm" title="Save" disabled={busy || !edit.description} onClick={() => saveEdit(item.id)}><i className="fas fa-check"></i></button>
                        <button className="btn-icon-sm" title="Cancel" onClick={() => cancelEdit(item.id)}><i className="fas fa-undo"></i></button>
                    </div>
                </td>
            </tr>
        );
    };

    const statusOptions = K.manualStatuses.includes(doc.status)
        ? K.manualStatuses
        : [doc.status, ...K.manualStatuses]; // ledger-derived (paid/partial) shows but stays reachable-only-by-ledger

    return (
        <div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
            <div className="modal builder-modal">
                <div className="modal-header">
                    <h2 className="modal-title" style={{ display: 'flex', alignItems: 'center', gap: '0.6rem' }}>
                        <span style={{ fontFamily: 'monospace' }}>{number}</span>
                        <span className={`badge ${isDead ? 'secondary' : 'success'}`} style={{ textTransform: 'uppercase', fontSize: '0.65rem' }}>{doc.status}</span>
                    </h2>
                    <button className="modal-close-btn" onClick={onClose}>&times;</button>
                </div>
                <div className="modal-body">
                    {err && <div className="api-error">{err}</div>}
                    {sendResult && !sendResult.sent && (
                        <div className="api-error">
                            {sendResult.reason === 'no_mailbox'
                                ? 'No connected mailbox — connect one in Email Settings (envelope icon, top right), or download the PDF and send it yourself.'
                                : 'Sending failed — check Email Settings for the mailbox status, or download the PDF and send it yourself.'}
                        </div>
                    )}
                    {sendResult && sendResult.sent && (
                        <div className="api-success" style={{ marginBottom: '0.75rem' }}>
                            Accepted for delivery from {sendResult.from}.
                        </div>
                    )}

                    {/* Header block: who + when + status */}
                    <div className="form-grid" style={{ marginBottom: '1rem' }}>
                        <div className="form-group">
                            <label className="form-label">Account</label>
                            <div style={{ fontWeight: 600 }}>{doc.account_name}</div>
                            {doc.contact_name && doc.contact_name.trim() && <div style={{ fontSize: '0.8125rem', color: 'var(--text-3)' }}>Attn: {doc.contact_name}</div>}
                        </div>
                        <div className="form-group">
                            <label className="form-label">Status</label>
                            <select className="form-input" value={doc.status} disabled={busy || isDead} onChange={e => handleStatus(e.target.value)}>
                                {statusOptions.map(s => (
                                    <option key={s} value={s} disabled={(s === 'paid' || s === 'partial') && s !== doc.status}>
                                        {s.charAt(0).toUpperCase() + s.slice(1)}
                                    </option>
                                ))}
                            </select>
                        </div>
                        <div className="form-group">
                            <label className="form-label">Issued</label>
                            <div>{formatDate(doc.issue_date || doc.created_at)}</div>
                        </div>
                        <div className="form-group">
                            <label className="form-label">{K.dateLabel}</label>
                            <input type="date" className="form-input" disabled={busy || isDead}
                                value={doc[K.dateKey] ? String(doc[K.dateKey]).slice(0, 10) : ''}
                                onChange={e => run(() => (kind === 'quote' ? api.updateQuote : api.updateInvoice)(doc.id, { [K.dateKey]: e.target.value || null }))} />
                        </div>
                    </div>

                    {/* Line items */}
                    <h4 style={{ margin: '0 0 0.5rem', fontSize: '0.9375rem' }}>Line Items
                        {!editable && !isDead && <span style={{ fontWeight: 400, fontSize: '0.75rem', color: 'var(--text-3)', marginLeft: '0.5rem' }}>
                            (locked — {kind === 'invoice' ? 'issued invoices are financial records; void and reissue to change them' : 'reopen by setting status back'})
                        </span>}
                    </h4>
                    <table className="line-items-table">
                        <thead><tr>
                            <th style={{ width: '45%' }}>Description</th>
                            <th style={{ width: '12%', textAlign: 'right' }}>Qty</th>
                            <th style={{ width: '16%', textAlign: 'right' }}>Unit Price</th>
                            <th style={{ width: '16%', textAlign: 'right' }}>Total</th>
                            <th style={{ width: '11%' }}></th>
                        </tr></thead>
                        <tbody>
                            {doc.items.length === 0 && !editRows.new
                                ? <tr><td colSpan={5} style={{ textAlign: 'center', color: 'var(--text-3)', padding: '1rem' }}>No line items</td></tr>
                                : doc.items.map(renderItemRow)}
                            {editRows.new && renderItemRow({ id: 'new', description: '', quantity: 1, unit_price: 0 })}
                        </tbody>
                    </table>
                    {editable && !editRows.new && (
                        <button className="btn btn-secondary btn-small" onClick={() => setEditRows(p => ({ ...p, new: { description: '', quantity: 1, unit_price: 0, product_id: null } }))}>
                            <i className="fas fa-plus"></i> Add Line Item
                        </button>
                    )}

                    {/* Totals (server-computed — the numbers on record) */}
                    <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '1rem' }}>
                        <div className="totals-block">
                            <div className="totals-row"><span>Subtotal</span><span>{money(doc.subtotal)}</span></div>
                            <div className="totals-row">
                                <span>Tax {editable
                                    ? <input type="number" min="0" max="100" step="0.1" defaultValue={doc.tax_rate}
                                        onBlur={e => parseFloat(e.target.value) !== parseFloat(doc.tax_rate) && handleTax(e.target.value)}
                                        style={{ width: '4rem', marginLeft: '0.5rem' }} />
                                    : `(${Number(doc.tax_rate)}%)`}{editable ? '%' : ''}</span>
                                <span>{money(doc.tax_amount)}</span>
                            </div>
                            <div className="totals-row total-final"><span>Total</span><span>{money(doc.total)}</span></div>
                            {kind === 'invoice' && <div className="totals-row"><span>Paid</span><span>{money(doc.amount_paid)}</span></div>}
                            {kind === 'invoice' && <div className="totals-row" style={{ fontWeight: 600 }}><span>Balance</span><span>{money(balance)}</span></div>}
                        </div>
                    </div>

                    {/* Payment history (invoices) */}
                    {kind === 'invoice' && doc.payments && doc.payments.length > 0 && (
                        <div style={{ marginTop: '1rem' }}>
                            <h4 style={{ margin: '0 0 0.5rem', fontSize: '0.9375rem' }}>Payments</h4>
                            <table className="data-table">
                                <thead><tr><th>Date</th><th>Amount</th><th>Method</th><th>Reference</th><th>Recorded by</th></tr></thead>
                                <tbody>
                                    {doc.payments.map(p => (
                                        <tr key={p.id}>
                                            <td>{formatDate(p.paid_at)}</td>
                                            <td style={{ fontWeight: 500 }}>{money(p.amount)}</td>
                                            <td>{p.method || '—'}</td>
                                            <td>{p.reference || '—'}</td>
                                            <td>{p.recorded_by_name || '—'}</td>
                                        </tr>
                                    ))}
                                </tbody>
                            </table>
                        </div>
                    )}

                    {/* Notes */}
                    <div style={{ marginTop: '1rem' }}>
                        <h4 style={{ margin: '0 0 0.5rem', fontSize: '0.9375rem' }}>Notes
                            {!isDead && notesDraft === null && (
                                <button className="btn-icon-sm" style={{ marginLeft: '0.5rem' }} title="Edit notes" onClick={() => setNotesDraft(doc.notes || '')}><i className="fas fa-pen"></i></button>
                            )}
                        </h4>
                        {notesDraft === null
                            ? <div style={{ whiteSpace: 'pre-line', color: doc.notes ? 'inherit' : 'var(--text-3)' }}>{doc.notes || 'No notes'}</div>
                            : (
                                <div>
                                    <textarea className="form-input" style={{ minHeight: 60, width: '100%' }} value={notesDraft} onChange={e => setNotesDraft(e.target.value)} />
                                    <div style={{ display: 'flex', gap: '0.5rem', marginTop: '0.5rem' }}>
                                        <button className="btn btn-primary btn-small" disabled={busy} onClick={handleNotesSave}><i className="fas fa-check"></i> Save</button>
                                        <button className="btn btn-secondary btn-small" onClick={() => setNotesDraft(null)}>Cancel</button>
                                    </div>
                                </div>
                            )}
                    </div>

                    {/* Send panel */}
                    {showSend && !isDead && (
                        <div style={{ marginTop: '1rem', padding: '0.75rem', border: '1px solid var(--border)', borderRadius: '0.5rem' }}>
                            <h4 style={{ margin: '0 0 0.5rem', fontSize: '0.9375rem' }}>Email this {kind}</h4>
                            <div className="form-group" style={{ marginBottom: '0.5rem' }}>
                                <label className="form-label">To</label>
                                <input type="email" className="form-input" value={sendTo} onChange={e => setSendTo(e.target.value)} placeholder="customer@example.com" />
                            </div>
                            <div className="form-group" style={{ marginBottom: '0.5rem' }}>
                                <label className="form-label">Personal message (optional)</label>
                                <textarea className="form-input" style={{ minHeight: 50 }} value={sendMsg} onChange={e => setSendMsg(e.target.value)} placeholder="A short note above the attached PDF…" />
                            </div>
                            <div style={{ display: 'flex', gap: '0.5rem' }}>
                                <button className="btn btn-primary btn-small" disabled={busy || !sendTo} onClick={handleSend}>
                                    {busy ? <><i className="fas fa-spinner fa-spin"></i> Sending…</> : <><i className="fas fa-paper-plane"></i> Send with PDF</>}
                                </button>
                                <button className="btn btn-secondary btn-small" onClick={() => setShowSend(false)}>Cancel</button>
                            </div>
                            <div style={{ fontSize: '0.75rem', color: 'var(--text-3)', marginTop: '0.5rem' }}>
                                Sends from your connected mailbox and logs to the account's communications.
                            </div>
                        </div>
                    )}

                    {/* Footer actions */}
                    <div className="btn-group" style={{ marginTop: '1.25rem' }}>
                        <button className="btn btn-secondary" disabled={busy} onClick={handleDownload}><i className="fas fa-file-pdf"></i> Download PDF</button>
                        {!isDead && <button className="btn btn-primary" disabled={busy} onClick={() => setShowSend(s => !s)}><i className="fas fa-paper-plane"></i> Email…</button>}
                        {kind === 'quote' && !isDead && (doc.status === 'draft' || doc.status === 'sent' || doc.status === 'accepted') && currentUser.role !== 'rep' && (
                            <button className="btn btn-secondary" disabled={busy} onClick={() => {
                                if (window.confirm(`Convert ${number} to an invoice?`)) run(() => api.convertQuote(doc.id, {}));
                            }}><i className="fas fa-file-invoice"></i> Convert to Invoice</button>
                        )}
                        {!isDead && doc.status !== 'draft' && (
                            <button className="btn btn-secondary" disabled={busy} style={{ color: '#ef4444' }} onClick={() => handleStatus(K.deadStatus)}>
                                <i className="fas fa-ban"></i> {K.deadVerb}
                            </button>
                        )}
                        <button className="btn btn-secondary" onClick={onClose} style={{ marginLeft: 'auto' }}>Close</button>
                    </div>
                </div>
            </div>
        </div>
    );
};
