import { apiGet, apiPost, apiPut, apiDelete, apiPatch } from '../api.js';
import { canEdit, pageHeaderHTML, showToast } from '../app.js';
import { confirmAction } from '../confirm-modal.js';

export async function sessionsPage() {
    const app = document.getElementById('app');
    app.innerHTML = `
        ${pageHeaderHTML('Sessions', '<span id="sessionHeaderActions"></span>', {
            subtitle: 'Define which session measures belong to each program session',
        })}
        <div id="sessionsContent"><div class="spinner"></div></div>
    `;

    if (canEdit()) {
        document.getElementById('sessionHeaderActions').innerHTML =
            '<button type="button" class="btn btn-primary" id="newSessionBtn">+ New session</button>';
    }

    try {
        const [sessionsData, questionnairesData] = await Promise.all([
            apiGet('program_sessions'),
            apiGet('questionnaires'),
        ]);
        renderSessions(
            sessionsData.sessions || [],
            questionnairesData.questionnaires || [],
            sessionsData.settings || {},
        );
    } catch (e) {
        showToast(e.message, 'error');
        document.getElementById('sessionsContent').innerHTML =
            `<p class="error-text">${esc(e.message)}</p>`;
    }
}

function renderSessions(sessions, questionnaires, settings) {
    const el = document.getElementById('sessionsContent');
    const sorted = [...sessions].sort((a, b) =>
        effectiveSessionNumber(a) - effectiveSessionNumber(b)
        || String(a.name).localeCompare(String(b.name)),
    );
    const autoRepeat = !!settings.autoRepeatSessions;

    el.innerHTML = `
        <div class="card scoring-profiles-card" style="margin-bottom:16px">
            <div class="scoring-profile-header">
                <div>
                    <h3 class="scoring-section-title">Cycle behavior</h3>
                    <p class="scoring-section-desc">
                        When enabled, completing every active session starts a new cycle at session 1.
                        Counselors re-complete the assigned session measures for the next cycle.
                    </p>
                </div>
            </div>
            ${canEdit() ? `
                <label class="checkbox-inline scoring-profile-active-row">
                    <input type="checkbox" id="autoRepeatSessionsToggle" ${autoRepeat ? 'checked' : ''}>
                    Automatically repeat sessions when the last session is completed
                </label>
            ` : `
                <p class="data-toolbar-hint" style="margin:0">
                    Auto-repeat is ${autoRepeat ? 'enabled' : 'disabled'}.
                </p>
            `}
        </div>
        <div class="scoring-profiles-section">
            <div class="card scoring-profiles-card">
                <div class="scoring-profile-header">
                    <div>
                        <h3 class="scoring-section-title">Program sessions</h3>
                        <p class="scoring-section-desc">
                            Counselors see these sessions in the app. Assign one or more session measures to each visit slot.
                        </p>
                    </div>
                </div>
                <div id="sessionsList" class="scoring-profiles-list">
                    ${sorted.length
                        ? sorted.map(s => sessionCardHTML(s, questionnaires)).join('')
                        : '<p class="scoring-empty-hint">No sessions defined yet. Create one to group session measures by visit.</p>'}
                </div>
            </div>
        </div>`;

    if (!canEdit()) return;

    document.getElementById('autoRepeatSessionsToggle')?.addEventListener('change', async (e) => {
        const enabled = e.target.checked;
        try {
            await apiPatch('program_sessions', { autoRepeatSessions: enabled });
            showToast(enabled ? 'Auto-repeat enabled' : 'Auto-repeat disabled', 'success');
        } catch (err) {
            e.target.checked = !enabled;
            showToast(err.message, 'error');
        }
    });

    document.getElementById('newSessionBtn')?.addEventListener('click', () => {
        openSessionModal(null, questionnaires, sorted);
    });

    el.querySelectorAll('.edit-session-btn').forEach(btn => {
        btn.addEventListener('click', () => {
            const session = sorted.find(x => x.sessionID === btn.dataset.id);
            openSessionModal(session, questionnaires, sorted);
        });
    });

    el.querySelectorAll('.delete-session-btn').forEach(btn => {
        btn.addEventListener('click', async () => {
            if (!(await confirmAction({
                title: 'Delete session',
                message: `Delete session "${btn.dataset.name}"?`,
                confirmLabel: 'Delete',
                variant: 'danger',
            }))) return;
            try {
                await apiDelete('program_sessions', { sessionID: btn.dataset.id });
                showToast('Session deleted', 'success');
                await sessionsPage();
            } catch (err) {
                showToast(err.message, 'error');
            }
        });
    });
}

function sessionCardHTML(session, questionnaires) {
    const qnById = Object.fromEntries((questionnaires || []).map(q => [q.questionnaireID, q]));
    const members = session.questionnaires || [];
    const activeBadge = session.isActive
        ? '<span class="badge badge-active">Active</span>'
        : '<span class="badge badge-draft">Inactive</span>';
    const memberRows = members.map(m => {
        const q = qnById[m.questionnaireID];
        const name = q?.name || m.name || m.questionnaireID;
        return `<div class="scoring-profile-q-row"><span class="scoring-profile-q-name">${esc(name)}</span></div>`;
    }).join('');

    return `
        <div class="scoring-profile-card">
            <div class="scoring-profile-card-top">
                <div class="scoring-profile-card-main">
                    <div class="scoring-profile-name-row">
                        <strong>${esc(session.name)}</strong>
                        ${activeBadge}
                    </div>
                    <p class="scoring-profile-bands">Session ${effectiveSessionNumber(session)}</p>
                    ${session.description
                        ? `<p class="scoring-profile-desc">${esc(session.description)}</p>`
                        : ''}
                </div>
                ${canEdit() ? `
                    <div class="scoring-profile-card-actions">
                        <button type="button" class="btn btn-sm edit-session-btn"
                            data-id="${esc(session.sessionID)}">Edit</button>
                        <button type="button" class="btn btn-sm btn-danger delete-session-btn"
                            data-id="${esc(session.sessionID)}"
                            data-name="${esc(session.name)}">Delete</button>
                    </div>` : ''}
            </div>
            <p class="scoring-profile-member-count">${members.length} session measure(s)</p>
            <div class="scoring-profile-members">${memberRows
                || '<p class="scoring-empty-hint">No session measures assigned</p>'}</div>
        </div>`;
}

function openSessionModal(session, questionnaires, allSessions) {
    const isEdit = !!session;
    const members = session?.questionnaires?.length
        ? session.questionnaires.map(m => ({
            questionnaireID: m.questionnaireID,
            orderIndex: m.orderIndex ?? 0,
        }))
        : [];
    const selectedIds = new Set(members.map(m => m.questionnaireID));
    const defaultSessionNumber = (allSessions?.length ?? 0) + 1;

    const overlay = document.createElement('div');
    overlay.className = 'modal-overlay';
    overlay.innerHTML = `
        <div class="modal-dialog modal-dialog-wide">
            <h2>${isEdit ? 'Edit session' : 'New session'}</h2>
            <p class="modal-subtitle">Name the visit slot and choose which session measures counselors complete during it.</p>
            <div class="form-row" style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
                <div class="form-group">
                    <label for="sessName">Name</label>
                    <input type="text" id="sessName" value="${esc(session?.name || '')}" placeholder="e.g. Baseline visit">
                </div>
                <div class="form-group">
                    <label for="sessNumber">Session number</label>
                    <input type="number" id="sessNumber" min="1" value="${session ? effectiveSessionNumber(session) : defaultSessionNumber}">
                </div>
            </div>
            <div class="form-group scoring-profile-active-row">
                <label class="checkbox-inline">
                    <input type="checkbox" id="sessActive" ${session?.isActive !== 0 ? 'checked' : ''}>
                    Active (visible in app)
                </label>
            </div>
            <div class="form-group">
                <label for="sessDesc">Description</label>
                <textarea id="sessDesc" rows="2" placeholder="Optional note for counselors">${esc(session?.description || '')}</textarea>
            </div>
            <h4 class="scoring-modal-section-title">Session measures</h4>
            <p class="data-toolbar-hint" style="margin:0 0 10px">Add questionnaires in the order they should appear for this session.</p>
            <div id="sessQnPicker" class="scoring-profile-picker"></div>
            <div class="modal-actions">
                <button type="button" class="btn btn-sm" id="sessCancel">Cancel</button>
                <button type="button" class="btn btn-primary btn-sm" id="sessSave">${isEdit ? 'Save' : 'Create'}</button>
            </div>
        </div>`;
    document.body.appendChild(overlay);
    document.body.classList.add('modal-open');

    const picker = overlay.querySelector('#sessQnPicker');
    const sortedQn = [...(questionnaires || [])].sort((a, b) =>
        (a.orderIndex ?? 0) - (b.orderIndex ?? 0),
    );

    function renderPicker() {
        const ordered = members.map(m => ({
            ...m,
            q: sortedQn.find(q => q.questionnaireID === m.questionnaireID),
        }));
        const available = sortedQn.filter(q => !selectedIds.has(q.questionnaireID));

        picker.innerHTML = `
            ${ordered.map((m, idx) => `
                <div class="scoring-profile-q-row" data-qn="${esc(m.questionnaireID)}">
                    <span class="scoring-profile-q-name">${esc(m.q?.name || m.questionnaireID)}</span>
                    <span class="scoring-profile-q-actions">
                        <button type="button" class="btn btn-sm sess-move-up" ${idx === 0 ? 'disabled' : ''} title="Move up">↑</button>
                        <button type="button" class="btn btn-sm sess-move-down" ${idx === ordered.length - 1 ? 'disabled' : ''} title="Move down">↓</button>
                        <button type="button" class="btn btn-sm btn-danger sess-remove" title="Remove">Remove</button>
                    </span>
                </div>
            `).join('')}
            ${available.length ? `
                <div class="scoring-profile-add-row">
                    <select id="sessAddSelect">
                        <option value="">Add session measure…</option>
                        ${available.map(q => `<option value="${esc(q.questionnaireID)}">${esc(q.name)}</option>`).join('')}
                    </select>
                    <button type="button" class="btn btn-sm" id="sessAddBtn">Add</button>
                </div>` : ''}`;

        picker.querySelectorAll('.sess-remove').forEach(btn => {
            btn.addEventListener('click', () => {
                const row = btn.closest('.scoring-profile-q-row');
                const id = row?.dataset.qn;
                if (!id) return;
                selectedIds.delete(id);
                const i = members.findIndex(m => m.questionnaireID === id);
                if (i >= 0) members.splice(i, 1);
                renderPicker();
            });
        });
        picker.querySelectorAll('.sess-move-up').forEach(btn => {
            btn.addEventListener('click', () => {
                const row = btn.closest('.scoring-profile-q-row');
                const id = row?.dataset.qn;
                const i = members.findIndex(m => m.questionnaireID === id);
                if (i > 0) {
                    [members[i - 1], members[i]] = [members[i], members[i - 1]];
                    renderPicker();
                }
            });
        });
        picker.querySelectorAll('.sess-move-down').forEach(btn => {
            btn.addEventListener('click', () => {
                const row = btn.closest('.scoring-profile-q-row');
                const id = row?.dataset.qn;
                const i = members.findIndex(m => m.questionnaireID === id);
                if (i >= 0 && i < members.length - 1) {
                    [members[i], members[i + 1]] = [members[i + 1], members[i]];
                    renderPicker();
                }
            });
        });
        const addBtn = overlay.querySelector('#sessAddBtn');
        if (addBtn) {
            const freshAddBtn = addBtn.cloneNode(true);
            addBtn.replaceWith(freshAddBtn);
            freshAddBtn.addEventListener('click', () => {
                const sel = overlay.querySelector('#sessAddSelect');
                const id = sel?.value;
                if (!id || selectedIds.has(id)) return;
                selectedIds.add(id);
                members.push({ questionnaireID: id, orderIndex: members.length });
                renderPicker();
            });
        }
    }

    renderPicker();

    const close = () => {
        overlay.remove();
        document.body.classList.remove('modal-open');
    };
    overlay.querySelector('#sessCancel')?.addEventListener('click', close);
    overlay.addEventListener('click', (e) => { if (e.target === overlay) close(); });

    overlay.querySelector('#sessSave')?.addEventListener('click', async () => {
        const name = overlay.querySelector('#sessName')?.value.trim();
        const description = overlay.querySelector('#sessDesc')?.value.trim() || '';
        const sessionNumber = parseInt(overlay.querySelector('#sessNumber')?.value || '1', 10);
        const isActive = overlay.querySelector('#sessActive')?.checked;
        if (!name) {
            showToast('Session name is required', 'error');
            return;
        }
        const payload = {
            name,
            description,
            sessionNumber: Number.isFinite(sessionNumber) ? Math.max(1, sessionNumber) : 1,
            isActive,
            questionnaires: members.map((m, idx) => ({
                questionnaireID: m.questionnaireID,
                orderIndex: idx,
            })),
        };
        try {
            if (isEdit) {
                await apiPut('program_sessions', { sessionID: session.sessionID, ...payload });
                showToast('Session saved', 'success');
            } else {
                await apiPost('program_sessions', payload);
                showToast('Session created', 'success');
            }
            close();
            await sessionsPage();
        } catch (err) {
            showToast(err.message, 'error');
        }
    });
}

function effectiveSessionNumber(session) {
    if (!session) return 1;
    return Math.max(session.sessionNumber ?? 1, (session.orderIndex ?? 0) + 1);
}

function esc(s) {
    const d = document.createElement('div');
    d.textContent = s ?? '';
    return d.innerHTML;
}
