import { apiGet } from '../api.js';
import { homeNavButton, showToast } from '../app.js';
import { buildResultColumns, resultColumnCellValue } from '../test-data.js';
import { formatBerlinDateTimeShort } from '../datetime.js';

const PAGE_SIZE = 50;

let sortCol = null;
let sortDir = 'asc';
let allClients = [];
let questionsDef = [];
let resultColumns = [];
let scoringProfileCatalog = [];
let questionnaireMeta = null;
let filterCoach = '';
let filterSupervisor = '';
let filterStatus = '';
let filterDateFrom = '';
let filterDateTo = '';
let filterSearch = '';
let filterQuestion = '';
let page = 0;

export async function resultsPage(params) {
    const app = document.getElementById('app');
    sortCol = null;
    sortDir = 'asc';
    filterCoach = '';
    filterSupervisor = '';
    filterStatus = '';
    filterDateFrom = '';
    filterDateTo = '';
    filterSearch = '';
    filterQuestion = '';
    page = 0;

    app.innerHTML = `
        <div class="page-header">
            <div class="page-header-start">
                ${homeNavButton()}
                <div class="page-header-titles">
                    <h1 id="resultsTitle">Results</h1>
                </div>
            </div>
            <div class="actions">
                <a href="#/questionnaire/${params.id}" class="btn">Editor</a>
                <a href="#/questionnaires" class="btn">Questionnaires</a>
            </div>
        </div>
        <div id="resultsContent"><div class="spinner"></div></div>
    `;

    try {
        const data = await apiGet(`results.php?questionnaireID=${encodeURIComponent(params.id)}`);
        questionnaireMeta = data.questionnaire;
        questionsDef = data.questions || [];
        scoringProfileCatalog = data.scoringProfiles || [];
        allClients = data.clients || [];
        document.getElementById('resultsTitle').textContent = `Results: ${questionnaireMeta.name} v${questionnaireMeta.version}`;
        renderResults();
    } catch (e) {
        showToast(e.message, 'error');
        document.getElementById('resultsContent').innerHTML = `<p class="error-text">${esc(e.message)}</p>`;
    }
}

function renderResults() {
    const container = document.getElementById('resultsContent');
    resultColumns = buildResultColumns(questionsDef);

    // Collect unique coaches and statuses for filters
    const coachOptions = getCoachFilterOptions();
    const supervisorOptions = getSupervisorFilterOptions();
    const statuses = [...new Set(allClients.map(c => c.status))].filter(Boolean).sort();

    container.innerHTML = `
        <div class="card" style="margin-bottom:16px">
            <div class="filter-bar">
                <label style="font-size:.85rem;font-weight:500">Filter:</label>
                <select id="filterSupervisor">
                    <option value="">All supervisors</option>
                    ${supervisorOptions.map(name => `<option value="${esc(name)}" ${filterSupervisor === name ? 'selected' : ''}>${esc(name)}</option>`).join('')}
                </select>
                <select id="filterCoach">
                    <option value="">All counselors</option>
                    ${coachOptions.map(([id, label]) => `<option value="${esc(id)}" ${filterCoach === id ? 'selected' : ''}>${esc(label)}</option>`).join('')}
                </select>
                <select id="filterStatus">
                    <option value="">All statuses</option>
                    ${statuses.map(s => `<option value="${esc(s)}" ${filterStatus === s ? 'selected' : ''}>${esc(s)}</option>`).join('')}
                </select>
                <label style="font-size:.85rem;display:flex;align-items:center;gap:4px">
                    Completed from
                    <input type="date" id="filterDateFrom" value="${esc(filterDateFrom)}">
                </label>
                <label style="font-size:.85rem;display:flex;align-items:center;gap:4px">
                    to
                    <input type="date" id="filterDateTo" value="${esc(filterDateTo)}">
                </label>
                <input type="search" id="filterSearch" class="filter-search" placeholder="Search client, counselors, status…" value="${esc(filterSearch)}">
                <input type="search" id="filterQuestion" placeholder="Go to question key…" value="${esc(filterQuestion)}" style="min-width:160px" list="questionKeyList">
                <datalist id="questionKeyList"></datalist>
                <button type="button" class="btn btn-sm" id="gotoQuestionBtn">Go to column</button>
                <button type="button" class="btn btn-sm" id="clearFiltersBtn">Clear filters</button>
                <span style="margin-left:auto;font-size:.85rem;color:var(--text-secondary)" id="resultCount"></span>
                <a id="exportCsvLink" class="btn btn-sm" href="#">Export CSV</a>
            </div>
            <p class="data-toolbar-hint" style="margin-top:8px">Each question has its own column; glass-scale symptoms are separate columns. Hover headers for context.</p>
        </div>
        <div class="card">
            <div class="table-wrapper" id="resultsTableWrap">
                <table class="data-table" id="resultsTable">
                    <thead><tr id="resultsHead"></tr></thead>
                    <tbody id="resultsBody"></tbody>
                </table>
            </div>
            <div class="pagination-bar" id="paginationBar"></div>
        </div>
    `;

    const qKeyList = document.getElementById('questionKeyList');
    qKeyList.innerHTML = resultColumns
        .map(col => `<option value="${esc(col.label)}"></option>`)
        .join('');

    document.getElementById('filterSupervisor').addEventListener('change', (e) => {
        filterSupervisor = e.target.value;
        page = 0;
        renderTableRows();
    });
    document.getElementById('filterCoach').addEventListener('change', (e) => {
        filterCoach = e.target.value;
        page = 0;
        renderTableRows();
    });
    document.getElementById('filterStatus').addEventListener('change', (e) => {
        filterStatus = e.target.value;
        page = 0;
        renderTableRows();
    });
    document.getElementById('filterDateFrom').addEventListener('change', (e) => {
        filterDateFrom = e.target.value;
        page = 0;
        renderTableRows();
    });
    document.getElementById('filterDateTo').addEventListener('change', (e) => {
        filterDateTo = e.target.value;
        page = 0;
        renderTableRows();
    });
    document.getElementById('filterSearch').addEventListener('input', (e) => {
        filterSearch = e.target.value.trim();
        page = 0;
        renderTableRows();
    });
    document.getElementById('gotoQuestionBtn').addEventListener('click', () => {
        filterQuestion = document.getElementById('filterQuestion').value.trim();
        scrollToQuestionColumn(filterQuestion);
    });
    document.getElementById('filterQuestion').addEventListener('keydown', (e) => {
        if (e.key === 'Enter') {
            e.preventDefault();
            filterQuestion = e.target.value.trim();
            scrollToQuestionColumn(filterQuestion);
        }
    });
    document.getElementById('clearFiltersBtn').addEventListener('click', () => {
        filterCoach = '';
        filterSupervisor = '';
        filterStatus = '';
        filterDateFrom = '';
        filterDateTo = '';
        filterSearch = '';
        filterQuestion = '';
        page = 0;
        renderResults();
    });
    document.getElementById('exportCsvLink').addEventListener('click', (e) => {
        e.preventDefault();
        exportCSV();
    });

    renderTableHead();
    renderTableRows();
}

function scoringTableColumns() {
    const cols = [];
    for (const profile of scoringProfileCatalog) {
        const name = profile.name || profile.profileID;
        cols.push(
            { key: `score_${profile.profileID}_calc`, label: `${name} calculated`, profileID: profile.profileID, field: 'calculated', title: `${name} — server-calculated category` },
            { key: `score_${profile.profileID}_coach`, label: `${name} counselor`, profileID: profile.profileID, field: 'counselor', title: `${name} — counselor category` },
            { key: `score_${profile.profileID}_by`, label: `${name} override by`, profileID: profile.profileID, field: 'override_by', title: `${name} — who overrode the calculated category` },
            { key: `score_${profile.profileID}_at`, label: `${name} override at`, profileID: profile.profileID, field: 'override_at', title: `${name} — when the override was set` },
        );
    }
    return cols;
}

function scoringCellValue(client, profileID, field) {
    const p = (client.scoringProfiles || []).find(x => x.profileID === profileID);
    if (!p) return '';
    const calc = p.calculatedBand || p.band || '';
    const coach = p.coachBand || '';
    const differs = Boolean(p.coachOverride) || (coach && coach !== calc);
    switch (field) {
        case 'calculated':
            return calc;
        case 'counselor':
            return coach;
        case 'override_by':
            return differs ? (p.coachReviewedByUsername || '') : '';
        case 'override_at':
            return differs ? (p.coachReviewedAt || '') : '';
        default:
            return '';
    }
}

function renderTableHead() {
    const head = document.getElementById('resultsHead');
    const fixedCols = [
        { key: 'clientCode', label: 'Client' },
        { key: 'coachUsername', label: 'Counselor' },
        { key: 'supervisorUsername', label: 'Supervisor' },
        { key: 'status', label: 'Status' },
        { key: 'sumPoints', label: 'Score' },
        { key: 'completedAt', label: 'Completed' },
    ];
    const scoringCols = scoringTableColumns();
    const allCols = [...fixedCols, ...scoringCols, ...resultColumns.map(col => ({
        key: col.key,
        label: col.label,
        title: col.title,
    }))];

    head.innerHTML = allCols.map((col, idx) => {
        let cls = 'sortable';
        if (sortCol === col.key) cls += sortDir === 'asc' ? ' sort-asc' : ' sort-desc';
        if (idx === 0) cls += ' sticky-col';
        const title = col.title ? ` title="${esc(col.title)}"` : '';
        return `<th class="${cls}" data-key="${col.key}"${title}>${esc(col.label)}</th>`;
    }).join('');

    head.querySelectorAll('th.sortable').forEach(th => {
        th.addEventListener('click', () => {
            const key = th.dataset.key;
            if (sortCol === key) sortDir = sortDir === 'asc' ? 'desc' : 'asc';
            else { sortCol = key; sortDir = 'asc'; }
            page = 0;
            renderTableHead();
            renderTableRows();
        });
    });
}

function scrollToQuestionColumn(query) {
    if (!query) return;
    const q = query.toLowerCase();
    const th = [...document.querySelectorAll('#resultsHead th')].find(el => {
        const key = (el.dataset.key || '').toLowerCase();
        const text = (el.textContent || '').trim().toLowerCase();
        const title = (el.getAttribute('title') || '').toLowerCase();
        return text === q || title === q || key.endsWith(q) || text.includes(q);
    });
    if (!th) {
        showToast(`No column matching "${query}"`, 'error');
        return;
    }
    th.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
    th.style.outline = '2px solid var(--primary)';
    setTimeout(() => { th.style.outline = ''; }, 2000);
}

function getCoachFilterOptions() {
    const map = new Map();
    allClients.forEach(c => {
        if (!c.coachID || map.has(c.coachID)) return;
        map.set(c.coachID, c.coachUsername || c.coachID);
    });
    return [...map.entries()].sort((a, b) => a[1].localeCompare(b[1]));
}

function getSupervisorFilterOptions() {
    return [...new Set(allClients.map(c => c.supervisorUsername).filter(Boolean))].sort((a, b) =>
        a.localeCompare(b)
    );
}

function coachDisplayName(c) {
    return c.coachUsername || c.coachID || '—';
}

function supervisorDisplayName(c) {
    return c.supervisorUsername || '—';
}

function getFilteredClients() {
    let clients = allClients;
    if (filterSupervisor) clients = clients.filter(c => c.supervisorUsername === filterSupervisor);
    if (filterCoach) clients = clients.filter(c => c.coachID === filterCoach);
    if (filterStatus) clients = clients.filter(c => c.status === filterStatus);
    if (filterDateFrom || filterDateTo) {
        const fromTs = filterDateFrom ? dateInputToUnixStart(filterDateFrom) : null;
        const toTs = filterDateTo ? dateInputToUnixEnd(filterDateTo) : null;
        clients = clients.filter(c => {
            const ts = c.completedAt;
            if (!ts) return false;
            if (fromTs !== null && ts < fromTs) return false;
            if (toTs !== null && ts > toTs) return false;
            return true;
        });
    }
    if (filterSearch) {
        const q = filterSearch.toLowerCase();
        clients = clients.filter(c => {
            const hay = [
                c.clientCode,
                c.coachUsername,
                c.supervisorUsername,
                c.status,
            ].filter(Boolean).join(' ').toLowerCase();
            return hay.includes(q);
        });
    }
    return clients;
}

function renderPagination(totalRows) {
    const bar = document.getElementById('paginationBar');
    if (!bar) return;
    const totalPages = Math.max(1, Math.ceil(totalRows / PAGE_SIZE));
    if (page >= totalPages) page = totalPages - 1;
    if (page < 0) page = 0;

    if (totalRows <= PAGE_SIZE) {
        bar.innerHTML = totalRows
            ? `<span>${totalRows} row${totalRows === 1 ? '' : 's'}</span>`
            : '';
        return;
    }

    const from = page * PAGE_SIZE + 1;
    const to = Math.min((page + 1) * PAGE_SIZE, totalRows);
    bar.innerHTML = `
        <button type="button" class="btn btn-sm" id="pagePrev" ${page <= 0 ? 'disabled' : ''}>Prev</button>
        <span>Rows ${from}–${to} of ${totalRows} (page ${page + 1}/${totalPages})</span>
        <button type="button" class="btn btn-sm" id="pageNext" ${page >= totalPages - 1 ? 'disabled' : ''}>Next</button>
    `;
    document.getElementById('pagePrev')?.addEventListener('click', () => {
        page--;
        renderTableRows();
    });
    document.getElementById('pageNext')?.addEventListener('click', () => {
        page++;
        renderTableRows();
    });
}

function dateInputToUnixStart(yyyyMmDd) {
    const [y, m, d] = yyyyMmDd.split('-').map(Number);
    return Math.floor(new Date(y, m - 1, d).getTime() / 1000);
}

function dateInputToUnixEnd(yyyyMmDd) {
    const [y, m, d] = yyyyMmDd.split('-').map(Number);
    return Math.floor(new Date(y, m - 1, d, 23, 59, 59, 999).getTime() / 1000);
}

function renderTableRows() {
    const body = document.getElementById('resultsBody');
    let clients = getFilteredClients();

    // Sort
    if (sortCol) {
        clients = [...clients].sort((a, b) => {
            let va = getCellValue(a, sortCol);
            let vb = getCellValue(b, sortCol);
            if (va == null) va = '';
            if (vb == null) vb = '';
            if (typeof va === 'number' && typeof vb === 'number') {
                return sortDir === 'asc' ? va - vb : vb - va;
            }
            const cmp = String(va).localeCompare(String(vb), undefined, { numeric: true });
            return sortDir === 'asc' ? cmp : -cmp;
        });
    }

    document.getElementById('resultCount').textContent = `${clients.length} client${clients.length === 1 ? '' : 's'}`;

    renderPagination(clients.length);

    if (!clients.length) {
        body.innerHTML = `<tr><td colspan="99" style="text-align:center;color:var(--text-secondary);padding:30px">No results found</td></tr>`;
        return;
    }

    const totalPages = Math.max(1, Math.ceil(clients.length / PAGE_SIZE));
    if (page >= totalPages) page = totalPages - 1;
    clients = clients.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);

    // Build option text lookup
    const optionMap = {};
    questionsDef.forEach(q => {
        (q.answerOptions || []).forEach(o => {
            optionMap[o.answerOptionID] = o.defaultText;
        });
    });

    body.innerHTML = clients.map(c => {
        const completedDate = c.completedAt ? new Date(c.completedAt * 1000).toLocaleDateString() : '—';
        const statusBadge = c.status ? `<span class="badge badge-${c.status.toLowerCase().replace(/\s+/g,'_')}">${esc(c.status)}</span>` : '—';

        const questionCells = resultColumns.map(col => {
            const ans = c.answers && c.answers[col.questionID];
            const val = resultColumnCellValue(col, ans, optionMap);
            if (val == null || val === '') return '<td>—</td>';
            return `<td>${esc(String(val))}</td>`;
        }).join('');

        const scoringCells = scoringTableColumns().map(col => {
            const val = scoringCellValue(c, col.profileID, col.field);
            return `<td>${val ? esc(String(val)) : '—'}</td>`;
        }).join('');

        return `<tr>
            <td class="sticky-col">${esc(c.clientCode)}</td>
            <td>${esc(coachDisplayName(c))}</td>
            <td>${esc(supervisorDisplayName(c))}</td>
            <td>${statusBadge}</td>
            <td>${c.sumPoints !== null ? c.sumPoints : '—'}</td>
            <td>${completedDate}</td>
            ${scoringCells}
            ${questionCells}
        </tr>`;
    }).join('');
}

function getCellValue(client, key) {
    if (key === 'clientCode') return client.clientCode;
    if (key === 'coachUsername') return coachDisplayName(client);
    if (key === 'supervisorUsername') return supervisorDisplayName(client);
    if (key === 'status') return client.status;
    if (key === 'sumPoints') return client.sumPoints;
    if (key === 'completedAt') return client.completedAt;
    const scoringCol = scoringTableColumns().find(c => c.key === key);
    if (scoringCol) {
        return scoringCellValue(client, scoringCol.profileID, scoringCol.field);
    }
    const col = resultColumns.find(c => c.key === key);
    if (col) {
        const ans = client.answers && client.answers[col.questionID];
        const optionMap = {};
        questionsDef.forEach(q => {
            (q.answerOptions || []).forEach(o => {
                optionMap[o.answerOptionID] = o.defaultText;
            });
        });
        return resultColumnCellValue(col, ans, optionMap);
    }
    return null;
}

function exportCSV() {
    const clients = getFilteredClients();
    const optionMap = {};
    questionsDef.forEach(q => {
        (q.answerOptions || []).forEach(o => {
            optionMap[o.answerOptionID] = o.defaultText;
        });
    });

    const headers = ['clientCode', 'Counselor', 'supervisor', 'status', 'sumPoints', 'completedAt',
        ...scoringTableColumns().map(col => col.label),
        ...resultColumns.map(col => col.label)];

    const rows = clients.map(c => {
        const base = [
            c.clientCode, coachDisplayName(c), c.supervisorUsername || '', c.status, c.sumPoints ?? '',
            c.completedAt ? formatBerlinDateTimeShort(c.completedAt * 1000) : ''
        ];
        const scoringCols = scoringTableColumns().map(col =>
            scoringCellValue(c, col.profileID, col.field)
        );
        const answerCols = resultColumns.map(col => {
            const ans = c.answers && c.answers[col.questionID];
            const val = resultColumnCellValue(col, ans, optionMap);
            return val != null ? val : '';
        });
        return [...base, ...scoringCols, ...answerCols];
    });

    let csv = '\uFEFF'; // BOM
    csv += headers.map(csvEsc).join(',') + '\n';
    rows.forEach(r => { csv += r.map(csvEsc).join(',') + '\n'; });

    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${questionnaireMeta.name}_v${questionnaireMeta.version}_results.csv`;
    a.click();
    URL.revokeObjectURL(url);
    showToast('CSV exported', 'success');
}

function csvEsc(val) {
    const s = String(val ?? '');
    if (s.includes(',') || s.includes('"') || s.includes('\n')) {
        return '"' + s.replace(/"/g, '""') + '"';
    }
    return s;
}

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