document.addEventListener('DOMContentLoaded', () => {
    projectTreePromise = loadProjectTree();
    populateTaskOptionSelects();
    applyPermissionVisibility();
    initTaskInlineEditing();
    initVersionInlineEditing();
    initProjectInlineEditing();

    loadRouteFromUrl();

    window.addEventListener('popstate', () => {
        loadRouteFromUrl();
    });

    document.querySelectorAll('[data-view="dashboard"]').forEach((button) => {
        button.addEventListener('click', () => {
            loadDashboard();
        });
    });

    document.getElementById('adminMenuButton')?.addEventListener('click', () => {
        loadAdmin('workflows');
    });

    document.querySelectorAll('[data-admin-section]').forEach((button) => {
        button.addEventListener('click', () => {
            loadAdmin(button.dataset.adminSection);
        });
    });

    document.getElementById('workflowRefreshButton')?.addEventListener('click', () => {
        loadWorkflowEditor();
    });

    document.getElementById('workflowTaskTypeSelect')?.addEventListener('change', (event) => {
        selectedWorkflowTaskType = event.target.value || null;
        renderWorkflowEditor();
    });

    document.getElementById('workflowDefaultStateSelect')?.addEventListener('change', (event) => {
        if (!selectedWorkflowTaskType) return;

        saveWorkflowAction('SetDefaultState', {
            task_type: selectedWorkflowTaskType,
            state: event.target.value
        });
    });

    document.getElementById('workflowStateForm')?.addEventListener('submit', async (event) => {
        event.preventDefault();

        const form = event.currentTarget;
        const data = Object.fromEntries(new FormData(form));
        const saved = await saveWorkflowAction('CreateState', data);

        if (saved) form.reset();
    });

    document.getElementById('workflowTransitionForm')?.addEventListener('submit', async (event) => {
        event.preventDefault();

        const form = event.currentTarget;
        const data = Object.fromEntries(new FormData(form));
        const saved = await saveWorkflowAction('CreateTransition', data);

        if (saved) form.reset();
    });

    document.getElementById('workflowAssignmentForm')?.addEventListener('submit', async (event) => {
        event.preventDefault();

        const form = event.currentTarget;
        const data = Object.fromEntries(new FormData(form));
        data.task_type = selectedWorkflowTaskType;

        if (!data.task_type) {
            alert('Select a task type first.');
            return;
        }

        const saved = await saveWorkflowAction('AssignState', data);

        if (saved) form.reset();
    });

    document.getElementById('adminWorkflowsPanel')?.addEventListener('click', (event) => {
        const stateButton = event.target.closest('[data-workflow-delete-state]');
        const transitionButton = event.target.closest('[data-workflow-delete-transition]');
        const assignmentButton = event.target.closest('[data-workflow-remove-assignment]');

        if (stateButton) {
            if (!window.confirm('Delete this state and related transitions/assignments?')) return;

            saveWorkflowAction('DeleteState', {}, {
                state_id: stateButton.dataset.workflowDeleteState
            });
        }

        if (transitionButton) {
            saveWorkflowAction('DeleteTransition', {}, {
                transition_id: transitionButton.dataset.workflowDeleteTransition
            });
        }

        if (assignmentButton) {
            saveWorkflowAction('RemoveAssignedState', {}, {
                assignment_id: assignmentButton.dataset.workflowRemoveAssignment
            });
        }
    });

    document.querySelectorAll('[data-admin-option-form]').forEach((form) => {
        form.addEventListener('submit', async (event) => {
            event.preventDefault();

            const saved = await saveAdminOptionForm(form.dataset.adminOptionForm, form);

            if (saved) form.reset();
        });
    });

    document.getElementById('adminTaskTypeSelect')?.addEventListener('change', (event) => {
        selectedAdminTaskType = event.target.value || null;
        renderAdminOptions();
    });

    document.getElementById('adminUserSelect')?.addEventListener('change', (event) => {
        selectedAdminUser = event.target.value || null;
        renderAdminOptions();
    });

    document.getElementById('adminCustomFieldForm')?.addEventListener('submit', async (event) => {
        event.preventDefault();

        const saved = await saveAdminCustomFieldForm(event.currentTarget);

        if (saved) event.currentTarget.reset();
    });

    document.getElementById('adminOptionsPanel')?.addEventListener('submit', async (event) => {
        const form = event.target.closest('[data-admin-option-edit]');

        if (!form) return;

        event.preventDefault();
        await saveAdminOptionForm(form.dataset.adminOptionEdit, form, form.dataset.optionId);
    });

    document.getElementById('adminOptionsPanel')?.addEventListener('submit', async (event) => {
        const form = event.target.closest('[data-admin-custom-field-edit]');

        if (!form) return;

        event.preventDefault();
        await saveAdminCustomFieldForm(form, form.dataset.adminCustomFieldEdit);
    });

    document.getElementById('adminOptionsPanel')?.addEventListener('click', (event) => {
        const deleteButton = event.target.closest('[data-admin-option-delete]');

        if (!deleteButton) return;

        if (!window.confirm('Delete this option?')) return;

        deleteAdminOption(deleteButton.dataset.adminOptionDelete, deleteButton.dataset.optionId);
    });

    document.getElementById('adminOptionsPanel')?.addEventListener('click', (event) => {
        const deleteButton = event.target.closest('[data-admin-custom-field-delete]');

        if (!deleteButton) return;

        if (!window.confirm('Delete this custom field?')) return;

        deleteAdminCustomField(deleteButton.dataset.adminCustomFieldDelete);
    });

    document.getElementById('adminUsersPanel')?.addEventListener('change', async (event) => {
        const checkbox = event.target.closest('[data-admin-user-right]');

        if (!checkbox) return;

        checkbox.disabled = true;
        const saved = await setAdminUserRight(
            checkbox.dataset.userId,
            checkbox.dataset.rightId,
            checkbox.checked
        );

        if (!saved) {
            checkbox.checked = !checkbox.checked;
            checkbox.disabled = false;
        }
    });

    document.getElementById('adminUsersPanel')?.addEventListener('submit', async (event) => {
        const form = event.target.closest('#adminProjectAccessForm');

        if (!form) return;

        event.preventDefault();

        if (!selectedAdminUser) return;

        const data = Object.fromEntries(new FormData(form));
        if (!data.project_id) return;

        await grantAdminProjectAccess(selectedAdminUser, data.project_id);
    });

    document.getElementById('adminUsersPanel')?.addEventListener('click', async (event) => {
        const deleteButton = event.target.closest('[data-admin-project-access-delete]');

        if (!deleteButton) return;

        await revokeAdminProjectAccess(deleteButton.dataset.adminProjectAccessDelete);
    });

    document.getElementById('profileMenuButton')?.addEventListener('click', () => {
        loadProfile();
    });

    document.getElementById('taskEditButton')?.addEventListener('click', () => {
        if (!canEditTasks()) return;
        openTaskEditPopup();
    });

    document.getElementById('taskView')?.addEventListener('click', (event) => {
        const customField = event.target.closest('[data-custom-field-id]');

        if (customField) {
            if (!canEditTasks()) return;
            openCustomFieldInlineEditor(customField);
            return;
        }

        const statusButton = event.target.closest('#taskStatusButton');

        if (statusButton) {
            const menu = document.getElementById('taskStatusMenu');
            if (menu) menu.hidden = !menu.hidden;
            return;
        }

        const transitionButton = event.target.closest('[data-task-transition]');

        if (transitionButton) {
            transitionCurrentTask(transitionButton.dataset.taskTransition);
        }
    });

    document.getElementById('taskView')?.addEventListener('keydown', (event) => {
        if (['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'].includes(event.target.tagName)) return;

        const customField = event.target.closest('[data-custom-field-id]');

        if (!customField || !['Enter', ' '].includes(event.key)) return;

        event.preventDefault();
        if (!canEditTasks()) return;
        openCustomFieldInlineEditor(customField);
    });

    document.getElementById('taskCommentButton')?.addEventListener('click', () => {
        document.getElementById('taskCommentInput')?.focus();
    });

    document.getElementById('versionEditButton')?.addEventListener('click', () => {
        if (!canEditVersions()) return;
        openVersionEditPopup();
    });

    document.getElementById('projectEditButton')?.addEventListener('click', () => {
        if (!canEditProjects()) return;
        openProjectEditPopup();
    });

    document.querySelectorAll('[data-version-task-sort]').forEach((button) => {
        button.addEventListener('click', () => {
            const field = button.dataset.versionTaskSort;

            if (versionTaskSort.field === field) {
                versionTaskSort.direction = versionTaskSort.direction === 'asc' ? 'desc' : 'asc';
            } else {
                versionTaskSort.field = field;
                versionTaskSort.direction = 'asc';
            }

            if (currentVersion) {
                loadVersionTasks(currentVersion.id, 1);
            }
        });
    });

    document.querySelectorAll('[data-project-task-sort]').forEach((button) => {
        button.addEventListener('click', () => {
            const field = button.dataset.projectTaskSort;

            if (projectTaskSort.field === field) {
                projectTaskSort.direction = projectTaskSort.direction === 'asc' ? 'desc' : 'asc';
            } else {
                projectTaskSort.field = field;
                projectTaskSort.direction = 'asc';
            }

            if (currentProjectTaskProject) {
                loadProjectTasks(currentProjectTaskProject, 1);
            }
        });
    });

    document.addEventListener('click', (event) => {
        const pageButton = event.target.closest('[data-task-page]');

        if (!pageButton || pageButton.disabled) return;

        const page = Number(pageButton.dataset.page);

        if (!Number.isFinite(page) || page < 1) return;

        if (pageButton.dataset.taskPage === 'version' && currentVersion) {
            loadVersionTasks(currentVersion.id, page);
        }

        if (pageButton.dataset.taskPage === 'project' && currentProjectTaskProject) {
            loadProjectTasks(currentProjectTaskProject, page);
        }
    });

    const createProjectForm = document.getElementById('createProjectForm');

    if (createProjectForm) {
        createProjectForm.addEventListener('submit', async (event) => {
            event.preventDefault();

            const data = Object.fromEntries(new FormData(createProjectForm));
            const mode = createProjectForm.dataset.mode ?? 'create';
            const projectId = document.getElementById('projectFormId').value;

            const result = await apiPost('/api/project.php', {
                api: mode === 'edit' ? 'Edit' : 'Create',
                project_id: mode === 'edit' ? projectId : undefined
            }, data);

            if (result.success) {
                taskLookupCache.projectsById.delete(result.project_id);
                closePopups();
                createProjectForm.reset();
                projectTreePromise = loadProjectTree();

                if (mode === 'edit') {
                    await loadProject(projectId, false);
                }
            } else {
                alert(result.error || 'Could not create project.');
            }
        });
    }

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

    if (createVersionForm) {
        createVersionForm.addEventListener('submit', async (event) => {
            event.preventDefault();

            const data = Object.fromEntries(new FormData(createVersionForm));
            const mode = createVersionForm.dataset.mode ?? 'create';
            const versionId = data.version_id;
            const projectId = data.project_id;
            delete data.version_id;

            if (mode === 'edit') {
                delete data.project_id;
            }

            const result = await apiPost('/api/version.php', {
                api: mode === 'edit' ? 'Edit' : 'Create',
                version_id: mode === 'edit' ? versionId : undefined
            }, data);

            if (result.success) {
                taskLookupCache.versionsByProject.delete(projectId);
                closePopups();
                projectTreePromise = loadProjectTree();

                if (mode === 'edit') {
                    await loadVersion(versionId, false);
                }
            } else {
                alert(result.error || 'Could not save version.');
            }
        });
    }

    const profileForm = document.getElementById('profileForm');

    if (profileForm) {
        document.getElementById('profilePictureInput')?.addEventListener('change', (event) => {
            const file = event.target.files?.[0];

            if (!file) {
                renderProfileAvatar(currentProfileUser?.picture ?? null);
                return;
            }

            document.getElementById('profileRemovePicture').checked = false;

            const reader = new FileReader();
            reader.addEventListener('load', () => renderProfileAvatar(reader.result));
            reader.readAsDataURL(file);
        });

        document.getElementById('profileRemovePicture')?.addEventListener('change', (event) => {
            if (event.target.checked) {
                document.getElementById('profilePictureInput').value = '';
                renderProfileAvatar(null);
            } else {
                renderProfileAvatar(currentProfileUser?.picture ?? null);
            }
        });

        profileForm.addEventListener('submit', async (event) => {
            event.preventDefault();

            const password = document.getElementById('profilePassword').value;
            const passwordConfirm = document.getElementById('profilePasswordConfirm').value;
            const status = document.getElementById('profileStatus');
            const submitButton = document.getElementById('profileSubmitButton');

            if (password !== passwordConfirm) {
                status.textContent = 'Passwords do not match.';
                return;
            }

            const data = new FormData(profileForm);

            if (!password) {
                data.delete('password');
            }

            submitButton.disabled = true;
            status.textContent = 'Saving...';

            const result = await apiPostForm('/api/user.php', {
                api: 'Edit',
                user_id: getCurrentUserId()
            }, data);

            submitButton.disabled = false;

            if (!result.success) {
                status.textContent = result.error || 'Could not save profile.';
                return;
            }

            const userResult = await apiGet('/api/user.php', {
                api: 'UserInfo',
                user_id: getCurrentUserId(),
                _: Date.now()
            });

            if (userResult.success) {
                taskLookupCache.users = null;
                updateAccountProfile(userResult.user);
                applyTheme(userResult.user.settings?.theme ?? 'dark');
                renderProfile(userResult.user);
                status.textContent = 'Saved.';
            } else {
                status.textContent = 'Saved. Refresh to see all changes.';
            }
        });
    }

    const createTaskForm = document.getElementById('createTaskForm');

    if (createTaskForm) {
        document.getElementById('taskFormProjectId')?.addEventListener('change', (event) => {
            populateTaskRelationSelects(event.target.value.trim());
        });

        createTaskForm.addEventListener('submit', async (event) => {
            event.preventDefault();

            const data = Object.fromEntries(new FormData(createTaskForm));
            const mode = createTaskForm.dataset.mode ?? 'create';
            const taskId = data.task_id;
            delete data.task_id;

            if (mode === 'edit') {
                delete data.project_id;
            }

            const result = await apiPost('/api/task.php', {
                api: mode === 'edit' ? 'Edit' : 'Create',
                task_id: mode === 'edit' ? taskId : undefined
            }, data);

            if (result.success) {
                closePopups();
                projectTreePromise = loadProjectTree();
                loadTask(mode === 'edit' ? taskId : result.task_id, mode !== 'edit');
            } else {
                alert(result.error || 'Could not save task.');
            }
        });
    }

    const taskCommentForm = document.getElementById('taskCommentForm');

    if (taskCommentForm) {
        taskCommentForm.addEventListener('submit', async (event) => {
            event.preventDefault();

            const input = document.getElementById('taskCommentInput');
            const status = document.getElementById('taskCommentStatus');
            const comment = input.value.trim();

            if (!comment) {
                status.textContent = 'Comment cannot be empty.';
                return;
            }

            status.textContent = 'Saving...';

            try {
                await submitTaskComment(comment);
                input.value = '';
                status.textContent = 'Saved.';
            } catch (error) {
                status.textContent = error.message;
            }
        });
    }

    document.getElementById('taskCommentList')?.addEventListener('click', (event) => {
        const replyButton = event.target.closest('[data-comment-reply]');
        const editButton = event.target.closest('[data-comment-edit]');
        const deleteButton = event.target.closest('[data-comment-delete]');
        const cancelButton = event.target.closest('[data-comment-reply-cancel]');
        const editCancelButton = event.target.closest('[data-comment-edit-cancel]');

        if (replyButton) {
            const commentCard = replyButton.closest('.task-comment');
            const slot = commentCard?.querySelector('.task-comment-reply-slot');

            if (!slot || slot.querySelector('form')) return;

            slot.innerHTML = `
                <form class="task-comment-reply-form" data-comment-reply-form="${replyButton.dataset.commentReply}">
                    <textarea class="form-control" name="comment" rows="2" placeholder="Write a reply..."></textarea>
                    <div class="task-comment-reply-actions">
                        <button class="btn btn-sm btn-primary" type="submit">Reply</button>
                        <button class="btn btn-sm btn-outline-secondary" type="button" data-comment-reply-cancel>Cancel</button>
                    </div>
                </form>
            `;
            slot.querySelector('textarea')?.focus();
        }

        if (editButton) {
            const commentCard = editButton.closest('.task-comment');
            const slot = commentCard?.querySelector('.task-comment-edit-slot');

            if (!slot || slot.querySelector('form')) return;

            slot.innerHTML = `
                <form class="task-comment-edit-form" data-comment-edit-form="${editButton.dataset.commentEdit}">
                    <textarea class="form-control" name="comment" rows="3">${escapeHtml(commentCard.dataset.commentText ?? '')}</textarea>
                    <div class="task-comment-reply-actions">
                        <button class="btn btn-sm btn-primary" type="submit">Save</button>
                        <button class="btn btn-sm btn-outline-secondary" type="button" data-comment-edit-cancel>Cancel</button>
                    </div>
                </form>
            `;
            slot.querySelector('textarea')?.focus();
        }

        if (deleteButton) {
            if (!window.confirm('Delete this comment?')) return;

            deleteTaskComment(deleteButton.dataset.commentDelete).catch((error) => {
                alert(error.message);
            });
        }

        if (cancelButton) {
            cancelButton.closest('.task-comment-reply-slot').innerHTML = '';
        }

        if (editCancelButton) {
            editCancelButton.closest('.task-comment-edit-slot').innerHTML = '';
        }
    });

    document.getElementById('taskCommentList')?.addEventListener('submit', async (event) => {
        const form = event.target.closest('[data-comment-reply-form], [data-comment-edit-form]');

        if (!form) return;

        event.preventDefault();

        const textarea = form.querySelector('textarea');
        const button = form.querySelector('button[type="submit"]');
        const comment = textarea.value.trim();
        const responseTo = form.dataset.commentReplyForm;
        const editCommentId = form.dataset.commentEditForm;

        if (!comment) return;

        button.disabled = true;

        try {
            if (editCommentId) {
                await updateTaskComment(editCommentId, comment);
            } else {
                await submitTaskComment(comment, responseTo);
            }
        } catch (error) {
            alert(error.message);
            button.disabled = false;
        }
    });
});
