function openVersionCreatePopup(projectId) {
    resetVersionPopup();
    document.getElementById('versionFormProjectId').value = projectId;
    openPopup('createVersion');
}

function openVersionEditPopup() {
    if (!currentVersion) return;

    resetVersionPopup();

    const form = document.getElementById('createVersionForm');

    if (!form) return;

    form.dataset.mode = 'edit';
    document.getElementById('versionPopupTitle').textContent = `Edit ${currentVersion.name}`;
    document.getElementById('versionPopupSubmit').textContent = 'Update Version';
    document.getElementById('versionFormVersionId').value = currentVersion.id;
    document.getElementById('versionFormProjectId').value = currentVersion.project;
    document.getElementById('versionFormName').value = currentVersion.name ?? '';
    document.getElementById('versionFormDescription').value = currentVersion.description ?? '';
    document.getElementById('versionFormDueDate').value = currentVersion.due_date ?? '';
    document.getElementById('versionFormReleasedDate').value = currentVersion.released_date ?? '';

    openPopup('createVersion');
}

async function loadVersion(versionId, pushHistory = true) {
    const view = showView('versionView');

    if (!view) return;

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

    const result = await apiGet('/api/version.php', {
        api: 'VersionInfo',
        version_id: versionId
    });

    if (!result.success) {
        setText('versionName', 'Version not found');
        setText('versionDescription', '');
        return;
    }

    await renderVersion(result.version);
    await loadVersionTasks(versionId);
    await ensureProjectOpen(result.version.project);
}

async function renderVersion(version) {
    currentVersion = version;

    setVersionEditableText('versionKey', `Version ${version.id}`);
    setVersionEditableText('versionName', version.name, version.name);
    setVersionEditableText('versionDescription', version.description, version.description, 'No description provided.');
    setText('versionProject', version.project);
    setText('versionCreated', version.created_date || '-');
    setVersionEditableText('versionDueDate', version.due_date, version.due_date, 'No due date');
    setVersionEditableText('versionReleasedDate', version.released_date, version.released_date, 'Not released');
}

async function loadVersionTasks(versionId, page = 1) {
    const list = document.getElementById('versionTaskList');
    const empty = document.getElementById('versionTaskEmpty');

    if (!list || !empty) return;

    list.innerHTML = '<div class="version-task-loading">Loading tasks...</div>';
    empty.hidden = true;
    currentVersionTasks = [];
    versionTaskPagination = null;

    const result = await apiGet('/api/task.php', {
        api: 'ListTasksByVersion',
        version_id: versionId,
        page,
        per_page: taskTablePageSize,
        sort: versionTaskSort.field,
        direction: versionTaskSort.direction
    });

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

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

    currentVersionTasks = await normalizeTaskTableRows(result.tasks);
    versionTaskPagination = result.pagination ?? null;
    renderTaskTable('version');
}

function initVersionInlineEditing() {
    if (!canEditVersions()) return;

    document.querySelectorAll('.version-editable').forEach((element) => {
        if (element.dataset.inlineReady === 'true') return;

        element.dataset.inlineReady = 'true';
        element.title = 'Click to edit';

        element.addEventListener('click', () => openVersionInlineEditor(element));
        element.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                openVersionInlineEditor(element);
            }
        });
    });
}

async function openVersionInlineEditor(element) {
    if (!canEditVersions() || !currentVersion || element.querySelector('.version-inline-form')) return;

    const field = element.dataset.versionField;
    const currentValue = element.dataset.currentValue ?? '';
    const originalHtml = element.innerHTML;
    const originalClasses = Array.from(element.classList);

    element.classList.remove('is-empty');
    element.innerHTML = '';

    const form = document.createElement('form');
    form.className = 'version-inline-form';

    const input = createVersionInlineInput(field, currentValue);
    form.appendChild(input);

    const actions = document.createElement('div');
    actions.className = 'version-inline-actions';
    actions.innerHTML = `
        <button class="btn btn-sm btn-primary" type="submit">
            <i class="fa-solid fa-check"></i>
        </button>
        <button class="btn btn-sm btn-outline-secondary" type="button" data-version-inline-cancel>
            <i class="fa-solid fa-xmark"></i>
        </button>
    `;
    form.appendChild(actions);

    element.appendChild(form);
    input.focus();

    if (input.select && input.type !== 'date') {
        input.select();
    }

    let editorClosed = false;

    const restore = () => {
        if (editorClosed) return;

        editorClosed = true;
        element.innerHTML = originalHtml;
        element.className = originalClasses.join(' ');
    };

    let saving = false;

    const save = async () => {
        if (saving) return;

        const nextValue = input.value;

        if (String(nextValue) === String(currentValue)) {
            restore();
            return;
        }

        saving = true;
        element.classList.add('is-saving');

        const result = await apiPost('/api/version.php', {
            api: 'Edit',
            version_id: currentVersion.id
        }, {
            [field]: nextValue
        });

        if (!result.success) {
            alert(result.error || 'Could not update version.');
            saving = false;
            restore();
            return;
        }

        editorClosed = true;
        element.classList.remove('is-saving');
        currentVersion = {
            ...currentVersion,
            [field]: nextValue === '' ? null : nextValue
        };

        taskLookupCache.versionsByProject.delete(currentVersion.project);
        await renderVersion(currentVersion);
        projectTreePromise = loadProjectTree();
        await projectTreePromise;
    };

    form.addEventListener('submit', async (event) => {
        event.preventDefault();
        await save();
    });

    form.querySelector('[data-version-inline-cancel]')?.addEventListener('click', (event) => {
        event.preventDefault();
        event.stopPropagation();
        restore();
    });

    input.addEventListener('keydown', async (event) => {
        if (event.key === 'Escape') {
            event.preventDefault();
            restore();
        }

        if (event.key === 'Enter' && input.tagName === 'TEXTAREA' && (event.ctrlKey || event.metaKey)) {
            event.preventDefault();
            await save();
        }
    });
}

function createVersionInlineInput(field, currentValue) {
    if (field === 'description') {
        const textarea = document.createElement('textarea');
        textarea.className = 'form-control version-inline-input';
        textarea.rows = 5;
        textarea.value = currentValue;
        return textarea;
    }

    const input = document.createElement('input');
    input.className = 'form-control version-inline-input';
    input.type = field === 'due_date' || field === 'released_date' ? 'date' : 'text';
    input.value = currentValue;
    input.required = field === 'name';
    return input;
}

