const ContactEditModal = ({ contact, accountId, onSave, onClose }) => {
    const isNew = !contact;
    const [form, setForm] = React.useState({
        first_name:  contact?.first_name  || '',
        last_name:   contact?.last_name   || '',
        title:       contact?.title       || '',
        role:        contact?.role        || '',
        department:  contact?.department  || '',
        location:    contact?.location    || '',
        notes:       contact?.notes       || '',
        is_primary:  contact?.is_primary  || false,
    });
    const [saving, setSaving] = React.useState(false);
    const [error,  setError]  = React.useState('');

    const set = k => e => setForm(p => ({ ...p, [k]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }));

    // Emails/phones for an existing contact autosave per-row via
    // ContactEmailPhoneEditor (below) — nothing to batch here. A brand-new
    // contact has no id yet to hang emails/phones off of, so it's saved
    // name-first; the card's inline editor handles email/phone right after.
    const handleSave = async (e) => {
        e.preventDefault();
        if (!form.first_name.trim()) { setError('First name is required.'); return; }
        setSaving(true); setError('');
        try {
            if (isNew) {
                await api.createContact({ ...form, account_id: accountId });
            } else {
                await api.updateContact(contact.id, form);
            }
            await onSave();
            onClose();
        } catch (err) {
            setError(err.message);
        } finally {
            setSaving(false);
        }
    };

    return (
        <div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
            <div className="modal modal-medium">
                <div className="modal-header">
                    <h2 className="modal-title">{isNew ? 'New Contact' : `Edit: ${contact.first_name} ${contact.last_name || ''}`}</h2>
                    <button className="modal-close-btn" onClick={onClose}>&times;</button>
                </div>
                <div className="modal-body">
                    <form onSubmit={handleSave}>
                        {error && <div className="api-error">{error}</div>}

                        <div className="form-section">
                            <h4>Contact Info</h4>
                            <div className="form-grid">
                                <div className="form-group">
                                    <label className="form-label">First Name *</label>
                                    <input className="form-input" value={form.first_name} onChange={set('first_name')} required autoFocus />
                                </div>
                                <div className="form-group">
                                    <label className="form-label">Last Name</label>
                                    <input className="form-input" value={form.last_name} onChange={set('last_name')} />
                                </div>
                                <div className="form-group">
                                    <label className="form-label">Title</label>
                                    <input className="form-input" value={form.title} onChange={set('title')} placeholder="e.g. Pastor, Principal" />
                                </div>
                                <div className="form-group">
                                    <label className="form-label">Role</label>
                                    <input className="form-input" value={form.role} onChange={set('role')} placeholder="e.g. treasurer, coordinator" />
                                </div>
                                <div className="form-group">
                                    <label className="form-label">Department</label>
                                    <input className="form-input" value={form.department} onChange={set('department')} />
                                </div>
                                <div className="form-group">
                                    <label className="form-label">Location / Office</label>
                                    <input className="form-input" value={form.location} onChange={set('location')} />
                                </div>
                                <div className="form-group full-width">
                                    <label className="form-label">Notes</label>
                                    <textarea className="form-input form-textarea" value={form.notes} onChange={set('notes')} style={{ minHeight: 60 }} />
                                </div>
                                <div className="form-group">
                                    <label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', marginTop: '0.25rem' }}>
                                        <input type="checkbox" checked={form.is_primary} onChange={set('is_primary')} /> Primary Contact
                                    </label>
                                </div>
                            </div>
                        </div>

                        {!isNew && (
                            <div className="form-section">
                                <h4>Email &amp; Phone</h4>
                                <p style={{ fontSize: '0.75rem', color: 'var(--text-3)', marginTop: '-0.5rem', marginBottom: '0.5rem' }}>
                                    Saved instantly as you edit — also editable straight from the contact card.
                                </p>
                                <ContactEmailPhoneEditor contact={contact} onChanged={onSave} />
                            </div>
                        )}

                        <div className="btn-group">
                            <button type="button" className="btn btn-secondary" onClick={onClose} 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> {isNew ? 'Create Contact' : 'Save Changes'}</>}
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    );
};

// Inline, per-row autosave editor for a contact's emails/phones — no modal,
// no "Add" click, no batch Save. Each row PATCHes/POSTs/DELETEs on blur or
// on the type/primary control changing. Used on the contact card directly
// AND inside ContactEditModal (the modal keeps name/title/notes as a batch
// form since those don't need per-keystroke saves).
const ContactEmailPhoneEditor = ({ contact, onChanged, onEmailClick }) => {
    const clone = (list) => (list || []).map(x => ({ ...x }));
    const [emails, setEmails] = React.useState(clone(contact.emails));
    const [phones, setPhones] = React.useState(clone(contact.phones));
    const [busy, setBusy] = React.useState(false);

    // Contact identity or its rows changed under us (e.g. the batch form's
    // own Save landed) — resync local rows to match.
    React.useEffect(() => {
        setEmails(clone(contact.emails));
        setPhones(clone(contact.phones));
    }, [contact.id, contact.emails, contact.phones]);

    const rowKey = (row, i) => row.id ? `r${row.id}` : `n${i}`;

    // No per-contact GET wrapper existed for this until now (list-only) — the
    // server route was already there (contacts.js `GET /:id`), api.js just
    // never called it. Needed here because after a mutation this component
    // must resync ITS OWN rows (esp. the server-assigned id on a just-created
    // row) independent of whatever the parent's onChanged does with the list.
    const resync = async () => {
        const fresh = await api.getContact(contact.id);
        setEmails(clone(fresh.emails));
        setPhones(clone(fresh.phones));
    };

    // The blank "+ add" row is synthesized at render time (below) and is
    // never part of the `emails`/`phones` state — so its type choice needs
    // somewhere to live until the value is actually typed and creates it.
    const [pendingType, setPendingType] = React.useState({ email: 'work', phone: 'work' });

    // value blur: create (blank→text), update (text→different text), or
    // delete (text→blank) depending on what changed. type/primary changes
    // fire immediately since they're discrete choices, not free typing.
    // Takes the row itself (not an index) — the synthetic blank row has no
    // stable index into `emails`/`phones`, since it isn't in that state.
    const saveField = async (kind, row, patch) => {
        const isEmail = kind === 'email';
        const rows = isEmail ? emails : phones;
        const next = { ...row, ...patch };
        const v = (next.value || '').trim();

        try {
            setBusy(true);
            if (!row.id) {
                if (!v) return; // still-blank new row, nothing to do
                await (isEmail
                    ? api.addContactEmail(contact.id, { value: v, type: next.type || 'work', is_primary: rows.filter(r => r.id).length === 0 })
                    : api.addContactPhone(contact.id, { value: v, type: next.type || 'work', is_primary: rows.filter(r => r.id).length === 0 }));
                setPendingType(p => ({ ...p, [kind]: 'work' })); // reset for the NEXT blank row
            } else if (!v) {
                // Cleared an existing row's value = delete it.
                await (isEmail ? api.deleteContactEmail(contact.id, row.id) : api.deleteContactPhone(contact.id, row.id));
            } else if (v === (row.value || '') && next.type === row.type && next.is_primary === row.is_primary) {
                return; // no-op, nothing actually changed
            } else {
                await (isEmail
                    ? api.updateContactEmail(contact.id, row.id, { value: v, type: next.type, is_primary: next.is_primary })
                    : api.updateContactPhone(contact.id, row.id, { value: v, type: next.type, is_primary: next.is_primary }));
            }
            await resync();
            await onChanged();
        } catch (err) {
            alert(err.message);
        } finally {
            setBusy(false);
        }
    };

    const remove = async (kind, row) => {
        const isEmail = kind === 'email';
        try {
            setBusy(true);
            await (isEmail ? api.deleteContactEmail(contact.id, row.id) : api.deleteContactPhone(contact.id, row.id));
            await resync();
            await onChanged();
        } catch (err) { alert(err.message); }
        finally { setBusy(false); }
    };

    const renderRows = (kind, rows, typeOptions) => {
        const isEmail = kind === 'email';
        const blankRow = { value: '', type: pendingType[kind], is_primary: false };
        const withBlank = rows.some(r => !r.id) ? rows : [...rows, blankRow];
        return withBlank.map((row, i) => (
            <div key={rowKey(row, i)} className="ep-row">
                <span className="ep-row-icon">
                    {isEmail
                        ? (row.id
                            ? <a href={`mailto:${row.value}`} title="Email" onClick={(e) => { if (onEmailClick && onEmailClick(row.value)) e.preventDefault(); }}><i className="fas fa-envelope"></i></a>
                            : <i className="fas fa-envelope"></i>)
                        : (row.id
                            ? <a href={`tel:${row.value}`} title="Call"><i className="fas fa-phone"></i></a>
                            : <i className="fas fa-phone"></i>)}
                </span>
                <input
                    defaultValue={row.value}
                    key={`${rowKey(row, i)}-${row.value}`}   // resync uncontrolled input after a save
                    placeholder={isEmail ? `+ add email` : `+ add phone`}
                    type={isEmail ? 'email' : 'tel'}
                    disabled={busy}
                    onBlur={(e) => saveField(kind, row, { value: e.target.value })}
                    onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur(); }}
                />
                <select value={row.type} disabled={busy}
                        onChange={(e) => {
                            const t = e.target.value;
                            if (row.id) { saveField(kind, row, { type: t }); return; }
                            setPendingType(p => ({ ...p, [kind]: t })); // blank row: buffer until it's created
                        }}>
                    {typeOptions.map(t => <option key={t} value={t}>{t[0].toUpperCase() + t.slice(1)}</option>)}
                </select>
                {row.id && (
                    <label style={{ display: 'flex', alignItems: 'center', gap: '0.25rem', fontSize: '0.8125rem', whiteSpace: 'nowrap', cursor: 'pointer' }}>
                        <input type="checkbox" checked={!!row.is_primary} disabled={busy}
                               onChange={(e) => saveField(kind, row, { is_primary: e.target.checked })} /> Primary
                    </label>
                )}
                {row.id && (
                    <button type="button" className="btn-icon-sm danger" disabled={busy} onClick={() => remove(kind, row)}>
                        <i className="fas fa-times"></i>
                    </button>
                )}
            </div>
        ));
    };

    return (
        <div className="ep-editor">
            {renderRows('email', emails, ['work', 'personal', 'other'])}
            {renderRows('phone', phones, ['work', 'mobile', 'home', 'other'])}
        </div>
    );
};
