// TaskListEditor — the ONE editor for a task list ([{ title, notes,
// due_in_days, auto_close }], the 0041 shape extended by 0063). Hosts: the
// product form's tasks_on_paid and Settings → Task Presets. Rows reorder
// with ↑/↓ buttons (deliberately not drag: rows hold text inputs, and drag
// handles on input-bearing rows fight text selection — PhotoGallery's
// caption trap).
//
// Per row (0063): WHEN — due offset from the spawning event (immediately,
// +1d … +1m); CLOSES — self-cancel rule ('reply' = an inbound reply gets
// logged, 'contact' = any comm logged either way). Follow-up noise kills
// trust in the list, so every "did they reply?" task should carry one.
//
// Props: tasks, onChange(nextTasks), max (default 15), presets (optional
// [{id,name,tasks}] — renders "Apply preset" chips that APPEND a copy of the
// preset's tasks; titles already present are skipped so combining Web + CRM
// never double-books a shared task).

const TASKS_ON_PAID_MAX = 15;
const DUE_OPTIONS = [
    { v: 0, label: 'Immediately' }, { v: 1, label: '+1 day' }, { v: 2, label: '+2 days' }, { v: 3, label: '+3 days' },
    { v: 7, label: '+1 week' }, { v: 14, label: '+2 weeks' }, { v: 30, label: '+1 month' },
];
const CLOSE_OPTIONS = [
    { v: '', label: 'Stays until done' }, { v: 'reply', label: 'Closes when they reply' }, { v: 'contact', label: 'Closes on any contact' },
];

const TaskListEditor = ({ tasks, onChange, max = TASKS_ON_PAID_MAX, presets = null }) => {
    const list = tasks || [];
    const update = (next) => onChange(next);

    const addRow    = () => update([...list, { title: '', notes: '', due_in_days: 0, auto_close: null }]);
    const removeRow = (i) => update(list.filter((_, x) => x !== i));
    const setField  = (i, key, val) => update(list.map((t, x) => x === i ? { ...t, [key]: val } : t));
    const move = (i, dir) => {
        const j = i + dir;
        if (j < 0 || j >= list.length) return;
        const next = [...list];
        [next[i], next[j]] = [next[j], next[i]];
        update(next);
    };

    // Apply = append a COPY (snapshot doctrine — later preset edits never
    // reach this record). Dedupe by title, case-insensitive, matching the
    // server normalizer so what the user sees is what the API keeps.
    const applyPreset = (p) => {
        const have = new Set(list.map(t => (t.title || '').trim().toLowerCase()).filter(Boolean));
        const fresh = (p.tasks || []).filter(t => !have.has(t.title.toLowerCase()));
        update([...list, ...fresh.map(t => ({ title: t.title, notes: t.notes || '', due_in_days: t.due_in_days || 0, auto_close: t.auto_close || null }))].slice(0, max));
    };
    // Toggle off = remove the tasks this preset contributed (by title).
    const removePreset = (p) => {
        const gone = new Set((p.tasks || []).map(t => t.title.toLowerCase()));
        update(list.filter(t => !gone.has((t.title || '').trim().toLowerCase())));
    };
    const presetApplied = (p) => {
        const have = new Set(list.map(t => (t.title || '').trim().toLowerCase()));
        return (p.tasks || []).length > 0 && p.tasks.every(t => have.has(t.title.toLowerCase()));
    };
    // A due offset outside the picker (API/CSV can send any 0–365) still
    // shows as itself rather than snapping to a wrong choice.
    const dueOptions = (v) => DUE_OPTIONS.some(o => o.v === v) ? DUE_OPTIONS : [...DUE_OPTIONS, { v, label: `+${v} days` }];

    return (
        <div>
            {presets && presets.length > 0 && (
                <div className="tag-filter-row" style={{ alignItems: 'center', marginBottom: '0.5rem' }}>
                    <span style={{ fontSize: '0.75rem', color: 'var(--text-3)' }}>Apply preset:</span>
                    {presets.map(p => {
                        const on = presetApplied(p);
                        return (
                            <span key={p.id} className="tag-pill tag-filter-chip"
                                  style={on ? { background: 'var(--accent, #3b82f6)', color: '#fff', cursor: 'pointer' }
                                            : { cursor: 'pointer', opacity: 0.85 }}
                                  title={on ? 'Click to remove this preset\'s tasks from the list'
                                            : `Add ${p.tasks.length} task${p.tasks.length === 1 ? '' : 's'}: ${p.tasks.map(t => t.title).join(', ')}`}
                                  onClick={() => on ? removePreset(p) : applyPreset(p)}>
                                {p.name}{on && <i className="fas fa-check" style={{ marginLeft: '0.3rem', fontSize: '0.65rem' }}></i>}
                            </span>
                        );
                    })}
                </div>
            )}
            {list.length > 0 && (
                <div style={{ display: 'flex', gap: '0.5rem', fontSize: '0.7rem', color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '0.25rem', paddingLeft: '1.7rem' }}>
                    <span style={{ flex: '1 1 34%' }}>Task</span>
                    <span style={{ flex: '1 1 30%' }}>Notes</span>
                    <span style={{ width: '8.2rem' }}>When</span>
                    <span style={{ width: '11rem' }}>Closes</span>
                    <span style={{ width: '7.4rem' }}></span>
                </div>
            )}
            {list.map((t, i) => {
                const due = Number(t.due_in_days) || 0;
                return (
                <div key={i} style={{ display: 'flex', gap: '0.5rem', marginBottom: '0.4rem', alignItems: 'center', flexWrap: 'wrap' }}>
                    <span style={{ fontSize: '0.75rem', color: 'var(--text-3)', width: '1.2rem', textAlign: 'right' }}>{i + 1}.</span>
                    <input className="form-input" style={{ flex: '1 1 12rem' }} maxLength={120}
                           value={t.title} placeholder="Task — e.g. Did they reply?"
                           onChange={e => setField(i, 'title', e.target.value)} />
                    <input className="form-input" style={{ flex: '1 1 10rem' }} maxLength={500}
                           value={t.notes || ''} placeholder="Notes for the rep (optional)"
                           onChange={e => setField(i, 'notes', e.target.value)} />
                    <select className="form-input" style={{ width: '8.2rem', flex: '0 0 auto' }} value={due} title="Due — relative to the moment the task is opened"
                            onChange={e => setField(i, 'due_in_days', parseInt(e.target.value, 10))}>
                        {dueOptions(due).map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
                    </select>
                    <select className="form-input" style={{ width: '11rem', flex: '0 0 auto' }} value={t.auto_close || ''} title="Self-cancel rule — closes the task when the thing it waits for happens"
                            onChange={e => setField(i, 'auto_close', e.target.value || null)}>
                        {CLOSE_OPTIONS.map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
                    </select>
                    <button type="button" className="btn btn-secondary btn-small" title="Move up"
                            disabled={i === 0} onClick={() => move(i, -1)}><i className="fas fa-arrow-up"></i></button>
                    <button type="button" className="btn btn-secondary btn-small" title="Move down"
                            disabled={i === list.length - 1} onClick={() => move(i, 1)}><i className="fas fa-arrow-down"></i></button>
                    <button type="button" className="btn btn-secondary btn-small" title="Remove task"
                            onClick={() => removeRow(i)}><i className="fas fa-times"></i></button>
                </div>
                );
            })}
            {list.length < max && (
                <button type="button" className="btn btn-secondary btn-small" onClick={addRow}>
                    <i className="fas fa-plus"></i> Add task
                </button>
            )}
        </div>
    );
};
