async function loadProjectTasks(projectId, page = 1, pushHistory = true) {
    const view = showView('taskListView');

    if (!view) return;

    if (pushHistory) {
        const url = new URL(window.location.href);
        url.searchParams.set('page', 'home');
        url.searchParams.set('project', projectId);
        url.searchParams.set('tasks', '1');
        url.searchParams.delete('task');
        url.searchParams.delete('version');
        url.searchParams.delete('profile');
        url.searchParams.delete('admin');
        window.history.pushState({}, '', url);
    }

    currentProjectTaskProject = projectId;
    setText('taskListProjectKey', projectId);
    setText('taskListTitle', `${projectId} Tasks`);

    const container = document.getElementById('taskListContainer');
    const empty = document.getElementById('taskListEmpty');

    container.innerHTML = '<div class="version-task-loading">Loading tasks...</div>';
    empty.hidden = true;
    currentProjectTasks = [];
    projectTaskPagination = null;

    const result = await apiGet('/api/task.php', {
        api: 'ListTasksByProject',
        project_id: projectId,
        page,
        per_page: taskTablePageSize,
        sort: projectTaskSort.field,
        direction: projectTaskSort.direction
    });

    if (!result.success) {
        container.innerHTML = '<div class="alert alert-danger mb-0">Could not load tasks.</div>';
        return;
    }

    if (!result.tasks.length) {
        container.innerHTML = '';
        empty.hidden = false;
        renderTaskTablePagination('project');
        return;
    }

    currentProjectTasks = await normalizeTaskTableRows(result.tasks);
    projectTaskPagination = result.pagination ?? null;
    renderTaskTable('project');
}

async function normalizeTaskTableRows(tasks) {
    const [types, priorities] = await Promise.all([
        getTaskTypes(),
        getTaskPriorities()
    ]);

    return tasks.map((task) => {
        const normalizedTask = typeof task === 'string'
            ? { id: task, title: '', type: null, priority: null }
            : task;

        const type = types.find((item) => String(item.id) === String(normalizedTask.type)) ?? null;
        const priority = priorities.find((item) => String(item.id) === String(normalizedTask.priority)) ?? null;

        return {
            ...normalizedTask,
            typeOption: type,
            priorityOption: priority,
            typeName: type?.name ?? '',
            priorityName: priority?.name ?? '',
            statusName: normalizedTask.status_state?.name ?? '',
            statusColor: normalizedTask.status_state?.color ?? '',
            assigneeUser: normalizedTask.assignee
                ? {
                    id: normalizedTask.assignee,
                    name: normalizedTask.assignee_name ?? `User ${normalizedTask.assignee}`,
                    picture: normalizedTask.assignee_picture ?? null
                }
                : null,
            assigneeName: normalizedTask.assignee_name ?? ''
        };
    });
}

function renderTaskTable(kind) {
    const isVersion = kind === 'version';
    const list = document.getElementById(isVersion ? 'versionTaskList' : 'taskListContainer');
    const empty = document.getElementById(isVersion ? 'versionTaskEmpty' : 'taskListEmpty');
    const tasks = isVersion ? currentVersionTasks : currentProjectTasks;

    if (!list || !empty) return;

    updateTaskTableSortButtons(kind);

    list.innerHTML = '';
    empty.hidden = tasks.length > 0;

    tasks.forEach((task) => {
        const button = document.createElement('button');
        button.type = 'button';
        button.className = 'version-task-row version-task-item';
        button.innerHTML = `
            <span class="version-task-id">${escapeHtml(task.id)}</span>
            <span class="version-task-title">${escapeHtml(task.title || '-')}</span>
            <span>${renderMetaBadge(task.typeOption)}</span>
            <span>${renderMetaBadge(task.priorityOption)}</span>
            <span>${renderUser(task.assigneeUser)}</span>
            <span>${renderTaskTableStatus(task)}</span>
        `;
        button.addEventListener('click', () => loadTask(task.id));

        list.appendChild(button);
    });

    renderTaskTablePagination(kind);
}

function renderTaskTableStatus(task) {
    if (!task.statusName) return '-';

    const color = task.statusColor || '#6c757d';

    return `
        <span class="version-task-status" style="--task-status-color: ${escapeHtml(color)}">
            ${escapeHtml(task.statusName)}
        </span>
    `;
}

function renderTaskTablePagination(kind) {
    const isVersion = kind === 'version';
    const pagination = isVersion ? versionTaskPagination : projectTaskPagination;
    const container = document.getElementById(isVersion ? 'versionTaskPagination' : 'projectTaskPagination');

    if (!container) return;

    if (!pagination || pagination.total <= pagination.per_page) {
        container.innerHTML = '';
        return;
    }

    const start = ((pagination.page - 1) * pagination.per_page) + 1;
    const end = Math.min(pagination.total, pagination.page * pagination.per_page);

    container.innerHTML = `
        <span>${escapeHtml(start)}-${escapeHtml(end)} of ${escapeHtml(pagination.total)}</span>
        <div class="version-task-page-actions">
            <button class="btn btn-sm btn-outline-secondary" type="button" data-task-page="${escapeHtml(kind)}" data-page="${escapeHtml(pagination.page - 1)}" ${pagination.page <= 1 ? 'disabled' : ''}>
                <i class="fa-solid fa-chevron-left"></i>
            </button>
            <button class="btn btn-sm btn-outline-secondary" type="button" data-task-page="${escapeHtml(kind)}" data-page="${escapeHtml(pagination.page + 1)}" ${pagination.page >= pagination.total_pages ? 'disabled' : ''}>
                <i class="fa-solid fa-chevron-right"></i>
            </button>
        </div>
    `;
}

function updateTaskTableSortButtons(kind) {
    const isVersion = kind === 'version';
    const selector = isVersion ? '[data-version-task-sort]' : '[data-project-task-sort]';
    const state = isVersion ? versionTaskSort : projectTaskSort;

    document.querySelectorAll(selector).forEach((button) => {
        const field = isVersion ? button.dataset.versionTaskSort : button.dataset.projectTaskSort;
        const isActive = field === state.field;
        const icon = button.querySelector('i');

        button.classList.toggle('is-active', isActive);

        if (!icon) return;

        icon.className = isActive
            ? `fa-solid ${state.direction === 'asc' ? 'fa-sort-up' : 'fa-sort-down'}`
            : 'fa-solid fa-sort';
    });
}
