{% extends 'mastery/base.html' %}
{% load i18n %}
{% load humanize %}
{% load l10n %}
{% load static %}
{% load skill_render %}
{% translate "Unable to determine the form action." as msg_unable_form_action %}
{% translate "Unable to update the fitting skills." as msg_unable_update_skills %}
{% translate "No recommended plan available to copy." as msg_no_plan_to_copy %}
{% translate "Recommended plan copied to clipboard." as msg_plan_copied %}
{% translate "Unable to copy plan to clipboard." as msg_copy_failed %}
{% translate "Copied!" as msg_copied_short %}
{% translate "Close" as close_label %}

{% block details %}
<div class="container mt-4" id="mastery-skills-page">
    <div
        id="mastery-skills-messages"
        class="position-fixed bottom-0 end-0 p-3 d-flex flex-column gap-2"
        style="z-index: 1080; width: min(26rem, calc(100vw - 1rem));"
        aria-live="polite"
        aria-atomic="true"
    ></div>
    <div id="mastery-skills-editor">
        {% include "mastery/partials/fitting_skills_editor.html" %}
    </div>
</div>

<style>
    .mastery-editor-tab-layout {
        align-items: stretch;
    }

    .mastery-editor-tab-nav {
        width: 100%;
        min-width: 0;
    }

    .mastery-editor-tab-content {
        min-width: 0;
    }

    .mastery-tabs-scroll {
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: thin;
        padding-bottom: 0.15rem;
        margin-bottom: 0.5rem;
    }

    .mastery-group-nav {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        flex-wrap: nowrap;
        width: max-content;
        min-width: 100%;
        gap: 0.5rem;
    }

    .mastery-group-pill {
        display: inline-flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 0.75rem;
        white-space: normal;
        text-align: left;
        border: 1px solid var(--bs-border-color, #dee2e6);
        color: var(--bs-body-color, #212529);
        background-color: var(--bs-body-bg, #fff);
        min-width: 220px;
    }

    .mastery-group-pill .badge {
        flex-shrink: 0;
        margin-top: 0.1rem;
    }

    .mastery-group-pill-label {
        line-height: 1.2;
        overflow-wrap: anywhere;
    }

    .mastery-group-pill.active {
        box-shadow: inset 0 0 0 1px rgba(var(--bs-primary-rgb, 13, 110, 253), 0.25);
    }

    @media (min-width: 992px) {
        .mastery-editor-tab-nav {
            flex: 0 0 280px;
            max-width: 280px;
        }

        .mastery-tabs-scroll {
            overflow: visible;
            margin-bottom: 0;
            height: 100%;
        }

        .mastery-group-nav {
            flex-direction: column;
            width: 100%;
        }

        .mastery-group-pill {
            width: 100%;
            min-width: 0;
        }
    }

    .skill-group-card {
        transition: transform 0.12s ease, box-shadow 0.12s ease;
    }

    .skill-group-card:hover {
        transform: translateY(-1px);
        box-shadow: var(--bs-box-shadow-sm);
    }

    .skill-group-card .group-skills-table th {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .skill-group-card .group-skills-table .edit-rec-col {
        width: 190px;
        white-space: nowrap;
    }

    .skill-group-card .card-body {
        padding-top: 1rem;
    }

    .skill-group-card .group-skills-table td,
    .skill-group-card .group-skills-table th {
        vertical-align: middle;
    }

    .skill-group-card .group-skills-table {
        table-layout: fixed;
    }

    .skill-group-card .group-skills-table tbody td {
        padding-top: 0.6rem;
        padding-bottom: 0.6rem;
    }

    .skill-group-card .group-skills-table tbody tr:last-child td {
        border-bottom: 0;
    }

    .skill-group-card .group-skills-table .text-end {
        width: 136px;
        white-space: nowrap;
    }

    .rec-edit-form {
        display: flex;
        align-items: center;
        gap: 0.35rem;
        flex-wrap: nowrap;
    }

    .rec-level-select {
        min-width: 108px;
        max-width: 108px;
    }

    .rec-set-btn {
        white-space: nowrap;
    }

    .skill-group-card .group-skills-table .is-blacklisted-row td {
        padding-top: 0.28rem;
        padding-bottom: 0.28rem;
    }

    .skill-group-card .group-skills-table .is-blacklisted-row .small {
        font-size: 0.76rem;
    }

    .skill-group-card .group-skills-table .skill-name-text {
        font-size: 0.88rem;
        line-height: 1.15;
    }

    .skill-group-card .group-skills-table .skill-title-row {
        margin-bottom: 0.2rem !important;
    }

    .skill-group-card .group-skills-table .skill-meta-row {
        font-size: 0.74rem;
        line-height: 1.1;
    }

    .skill-group-card .group-skills-table .skill-meta-badge {
        font-size: 0.68rem;
        font-weight: 600;
        padding: 0.22rem 0.4rem;
    }

    .skill-group-card .group-skills-table .skill-help-badge {
        font-size: 0.68rem;
        padding: 0.18rem 0.38rem;
    }

    .skill-group-card .card-body > .small.text-muted {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.35rem;
    }

    .btn-icon {
        width: 2rem;
        height: 2rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0;
    }

    .mastery-approval-avatar {
        border: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.14));
    }

    @keyframes group-card-flash {
        0% {
            box-shadow: 0 0 0 0 rgba(13, 110, 253, 0.45);
            transform: translateY(-1px);
        }
        100% {
            box-shadow: 0 0 0 0 rgba(13, 110, 253, 0);
            transform: translateY(0);
        }
    }

    .skill-group-card.is-updated {
        animation: group-card-flash 0.9s ease-out;
    }

</style>

<script>
    (() => {
        const page = document.getElementById("mastery-skills-page");
        const editor = document.getElementById("mastery-skills-editor");
        const messages = document.getElementById("mastery-skills-messages");

        if (!page || !editor || !messages) {
            return;
        }

        const initTooltips = (root) => {
            if (!window.jQuery || !window.jQuery.fn || !window.jQuery.fn.tooltip) {
                return false;
            }

            const $root = window.jQuery(root || document);
            const $targets = $root.find('[data-bs-tooltip="aa-mastery"]');

            if ($root.is('[data-bs-tooltip="aa-mastery"]')) {
                $targets.add($root).tooltip();
                return true;
            }

            $targets.tooltip();
            return true;
        };

        const initTooltipsWhenReady = (root) => {
            if (initTooltips(root)) {
                return;
            }

            let attempts = 0;
            const maxAttempts = 20;

            const retry = () => {
                attempts += 1;
                if (initTooltips(root) || attempts >= maxAttempts) {
                    return;
                }

                window.setTimeout(retry, 100);
            };

            retry();
        };

        const ACTIVE_GROUP_QUERY_PARAM = "active_group";

        const asString = (value) => (typeof value === "string" ? value : "");

        const escapeCssValue = (value) => {
            if (window.CSS && typeof window.CSS.escape === "function") {
                return window.CSS.escape(value);
            }

            return String(value).replace(/(["'`.\[\]():,#=\s>+~\\])/g, "\\$1");
        };

        const getRequestedGroupKeyFromUrl = () => {
            try {
                const url = new URL(window.location.href);
                return (url.searchParams.get(ACTIVE_GROUP_QUERY_PARAM) || "").trim();
            } catch (_error) {
                return "";
            }
        };

        const getActiveGroupKey = () => {
            const activeButton = editor.querySelector(".mastery-group-pill.active");
            return (activeButton && activeButton.dataset ? activeButton.dataset.groupKey : "") || "";
        };

        const updateActiveGroupInUrl = (groupKey) => {
            try {
                const url = new URL(window.location.href);
                if (groupKey) {
                    url.searchParams.set(ACTIVE_GROUP_QUERY_PARAM, groupKey);
                } else {
                    url.searchParams.delete(ACTIVE_GROUP_QUERY_PARAM);
                }
                window.history.replaceState({}, "", `${url.pathname}${url.search}${url.hash}`);
            } catch (_error) {
                // Ignore URL API edge cases and keep current URL untouched.
            }
        };

        const editorUrlWithGroup = (groupKey) => {
            try {
                const url = new URL(window.location.href);
                if (groupKey) {
                    url.searchParams.set(ACTIVE_GROUP_QUERY_PARAM, groupKey);
                }
                return `${url.pathname}${url.search}`;
            } catch (_error) {
                return window.location.pathname + window.location.search;
            }
        };

        const syncFormTabState = (form, groupKey) => {
            if (!groupKey || !(form instanceof HTMLFormElement)) {
                return;
            }

            let activeGroupInput = form.querySelector('input[name="active_group"]');
            if (!activeGroupInput) {
                activeGroupInput = document.createElement("input");
                activeGroupInput.type = "hidden";
                activeGroupInput.name = "active_group";
                form.appendChild(activeGroupInput);
            }
            activeGroupInput.value = groupKey;

            const nextInput = form.querySelector('input[name="next"]');
            if (nextInput) {
                nextInput.value = editorUrlWithGroup(groupKey);
            }
        };

        const syncEditorFormsTabState = (groupKey) => {
            if (!groupKey) {
                return;
            }

            editor.querySelectorAll("form").forEach((form) => syncFormTabState(form, groupKey));
        };

        const activateGroupTab = (groupKey) => {
            if (!groupKey) {
                return false;
            }

            const selector = `.mastery-group-pill[data-group-key="${escapeCssValue(groupKey)}"]`;
            const button = editor.querySelector(selector);
            if (!button) {
                return false;
            }

            if (window.bootstrap && typeof window.bootstrap.Tab === "function") {
                window.bootstrap.Tab.getOrCreateInstance(button).show();
            } else {
                button.click();
            }
            return true;
        };

        const renderFallbackMessage = (message, level = "danger") => {
            if (!message) {
                messages.innerHTML = "";
                return;
            }

            messages.innerHTML = `
                <div class="alert alert-${level} alert-dismissible fade show shadow-sm" role="alert">
                    ${message}
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{{ close_label }}"></button>
                </div>
            `;
        };

        const setFormBusy = (form, isBusy) => {
            form.classList.toggle("opacity-75", isBusy);
            form.querySelectorAll("button, select, input, textarea").forEach((element) => {
                if (element.type === "hidden") {
                    return;
                }

                if (isBusy) {
                    element.dataset.ajaxWasDisabled = element.disabled ? "1" : "0";
                    element.disabled = true;
                    return;
                }

                const wasDisabled = element.dataset.ajaxWasDisabled === "1";
                if (!wasDisabled) {
                    element.disabled = false;
                }
                delete element.dataset.ajaxWasDisabled;
            });
        };

        const closeParentModal = (form) => {
            const modal = form.closest(".modal");
            if (!modal) {
                return;
            }

            modal.querySelector('[data-bs-dismiss="modal"]')?.click();
        };

        const dismissAlert = (alertElement) => {
            if (window.bootstrap && typeof window.bootstrap.Alert === "function") {
                window.bootstrap.Alert.getOrCreateInstance(alertElement).close();
                return;
            }
            alertElement.querySelector(".btn-close")?.click();
        };

        const copyWithExecCommand = (text) => {
            const temp = document.createElement("textarea");
            temp.value = text;
            temp.setAttribute("readonly", "readonly");
            temp.style.position = "fixed";
            temp.style.top = "-9999px";
            temp.style.left = "-9999px";
            document.body.appendChild(temp);
            temp.focus();
            temp.select();
            temp.setSelectionRange(0, temp.value.length);
            const copied = document.execCommand("copy");
            document.body.removeChild(temp);
            return copied;
        };

        const scheduleAlertsDismiss = () => {
            messages.querySelectorAll(".alert").forEach((alertElement) => {
                window.setTimeout(() => {
                    if (messages.contains(alertElement)) {
                        dismissAlert(alertElement);
                    }
                }, 5000);
            });
        };

        const flashCopyButtonSuccess = (button) => {
            if (!(button instanceof HTMLElement)) {
                return;
            }

            const label = button.dataset.copySuccessLabel || "{{ msg_copied_short|escapejs }}" || "Copied!";
            const defaultLabel = (button.dataset.copyDefaultLabel || "").trim();
            const computedLabel = (button.dataset.copyOriginalLabel || button.textContent || "").trim();
            const originalLabel = computedLabel || defaultLabel || "Copy recommended plan";
            button.dataset.copyOriginalLabel = originalLabel;

            const wasDisabled = button.disabled;
            button.disabled = true;
            button.textContent = label;
            button.classList.remove("btn-outline-primary");
            button.classList.add("btn-success");

            window.setTimeout(() => {
                button.textContent = button.dataset.copyOriginalLabel || originalLabel;
                button.classList.remove("btn-success");
                button.classList.add("btn-outline-primary");
                button.disabled = wasDisabled;
            }, 1800);
        };

        const animateGroupCard = (groupKey) => {
            if (!groupKey) {
                return;
            }

            const groupContainer = editor.querySelector(`[data-group-key="${groupKey}"]`);
            const card = groupContainer ? groupContainer.querySelector(".skill-group-card") : null;
            if (!card) {
                return;
            }

            card.classList.remove("is-updated");
            // Force a reflow so the animation can replay after each refresh.
            void card.offsetWidth;
            card.classList.add("is-updated");
        };

        const submitForm = async (form) => {
            const formData = new FormData(form);
            const actionUrl = form.getAttribute("action") || form.action;
            const method = (form.getAttribute("method") || form.method || "POST").toUpperCase();
            const activeGroupKey = getActiveGroupKey();
            if (activeGroupKey) {
                formData.set("active_group", activeGroupKey);
                syncFormTabState(form, activeGroupKey);
            }
            const groupKey = asString(formData.get("_group_key")) || activeGroupKey;

            if (!actionUrl) {
                renderFallbackMessage("{{ msg_unable_form_action|escapejs }}", "danger");
                return;
            }

            setFormBusy(form, true);

            try {
                const response = await fetch(actionUrl, {
                    method,
                    body: formData,
                    credentials: "same-origin",
                    headers: {
                        "X-Requested-With": "XMLHttpRequest",
                        "Accept": "application/json",
                    },
                });

                const contentType = response.headers.get("content-type") || "";
                const payload = contentType.includes("application/json")
                    ? await response.json()
                    : null;

                if (!response.ok) {
                    renderFallbackMessage(
                        payload && payload.message ? payload.message : "{{ msg_unable_update_skills|escapejs }}",
                        "danger",
                    );
                    return;
                }

                closeParentModal(form);

                if (payload && typeof payload.html === "string") {
                    editor.innerHTML = payload.html;
                    const requestedGroupKey = getRequestedGroupKeyFromUrl();
                    const targetGroupKey = groupKey || requestedGroupKey;
                    if (targetGroupKey) {
                        activateGroupTab(targetGroupKey);
                    }
                    const resolvedGroupKey = getActiveGroupKey() || targetGroupKey;
                    if (resolvedGroupKey) {
                        updateActiveGroupInUrl(resolvedGroupKey);
                        syncEditorFormsTabState(resolvedGroupKey);
                    }
                    initTooltipsWhenReady(editor);
                    animateGroupCard(resolvedGroupKey || groupKey);
                }

                if (payload && typeof payload.messages_html === "string") {
                    messages.innerHTML = payload.messages_html;
                    scheduleAlertsDismiss();
                } else if (payload && payload.message) {
                    renderFallbackMessage(payload.message, payload.message_level || "success");
                    scheduleAlertsDismiss();
                } else {
                    messages.innerHTML = "";
                }
            } catch (_error) {
                renderFallbackMessage("{{ msg_unable_update_skills|escapejs }}", "danger");
                scheduleAlertsDismiss();
            } finally {
                setFormBusy(form, false);
            }
        };

        page.addEventListener("submit", (event) => {
            const form = event.target;

            if (!(form instanceof HTMLFormElement)) {
                return;
            }

            if (!editor.contains(form)) {
                return;
            }

            const method = (form.getAttribute("method") || form.method || "GET").toUpperCase();
            if (method !== "POST") {
                return;
            }

            event.preventDefault();
            submitForm(form);
        });

        page.addEventListener("click", async (event) => {
            const button = event.target.closest(".mastery-copy-plan-btn");
            if (!button) {
                return;
            }

            let copyText = "";
            const copyTargetId = button.dataset.copyTarget || "";
            if (copyTargetId) {
                const copyTarget = document.getElementById(copyTargetId);
                if (copyTarget) {
                    if ("value" in copyTarget) {
                        copyText = String(copyTarget.value || "");
                    } else {
                        copyText = String(copyTarget.textContent || "");
                    }
                }
            }
            if (!copyText) {
                copyText = button.dataset.copyText || "";
            }
            if (!copyText) {
                renderFallbackMessage("{{ msg_no_plan_to_copy|escapejs }}", "warning");
                scheduleAlertsDismiss();
                return;
            }

            try {
                if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
                    await navigator.clipboard.writeText(copyText);
                } else if (!copyWithExecCommand(copyText)) {
                    throw new Error("Legacy copy command failed");
                }
                flashCopyButtonSuccess(button);
                renderFallbackMessage("{{ msg_plan_copied|escapejs }}", "success");
                scheduleAlertsDismiss();
            } catch (_error) {
                try {
                    if (!copyWithExecCommand(copyText)) {
                        throw new Error("Legacy copy command failed");
                    }
                    flashCopyButtonSuccess(button);
                    renderFallbackMessage("{{ msg_plan_copied|escapejs }}", "success");
                    scheduleAlertsDismiss();
                } catch (_fallbackError) {
                    renderFallbackMessage("{{ msg_copy_failed|escapejs }}", "danger");
                    scheduleAlertsDismiss();
                }
            }
        });

        page.addEventListener("shown.bs.tab", (event) => {
            const tabButton = event.target instanceof HTMLElement
                ? event.target.closest(".mastery-group-pill")
                : null;
            if (!tabButton || !editor.contains(tabButton)) {
                return;
            }

            const groupKey = (tabButton.dataset.groupKey || "").trim();
            if (!groupKey) {
                return;
            }

            updateActiveGroupInUrl(groupKey);
            syncEditorFormsTabState(groupKey);
        });

        const requestedGroupKey = getRequestedGroupKeyFromUrl();
        if (requestedGroupKey) {
            activateGroupTab(requestedGroupKey);
        }
        const initialGroupKey = getActiveGroupKey();
        if (initialGroupKey) {
            updateActiveGroupInUrl(initialGroupKey);
            syncEditorFormsTabState(initialGroupKey);
        }

        initTooltipsWhenReady(page);
    })();
</script>

{% endblock %}