function qaEscapeHtml(value) {
    return String(value ?? "")
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;");
}

function qaSafeUrl(url) {
    const v = String(url ?? "").trim();
    return /^(https?:|data:image\/)/i.test(v) ? qaEscapeHtml(v) : "";
}

function qaEscapeJsArg(value) {
    return qaEscapeHtml(JSON.stringify(String(value ?? "")));
}

let sdkReadyPromise = null;
let licenseReadyPromise = null;
let activeScreenName = null;
let workItemPoller = null;

const productTypeRequests = new Map();
const screenHtmlRequests = new Map();

function stopWorkItemPoller() {
    if (workItemPoller) {
        clearInterval(workItemPoller);
        workItemPoller = null;
    }
}

function startWorkItemPoller() {
    if (workItemPoller) return;
    workItemPoller = setInterval(async () => {
        try {
            const id = await IndexLibrary.CurrentWorkItem().catch(() => "");
            if (id && id !== window.QAContext?.workItemId) {
                stopWorkItemPoller();
                if (window.QAContext) window.QAContext.workItemId = id;
                if (activeScreenName) loadScreenHtml(activeScreenName);
            }
        } catch (e) { /* still not ready */ }
    }, 1500);
}

const PRODUCT_LICENSE_MAP = {
    cleo: "clUserType",
    summary: "tsUserType",
    evolve: "eaUserType",
    groom: "gaUserType",
    releases: "rmUserType",
    timesheet: "ptUserType"
};

const SCREEN_LICENSE_KEYS = {
    cleo: ["cleo", "summary"],
    summary: ["summary"],
    evolve: ["evolve"],
    groom: ["groom"],
    releases: ["releases"],
    timesheet: ["timesheet"]
};

function applyFeatureVisibility(features) {
    const screenToFeatureMap = {
        cleo: 'cleo',
        evolve: 'evolve',
        groom: 'groom',
        releases: 'release',
        timesheet: 'timesheet'
    };

    const isFeatureOn = (key) => features[key] === 'enable' || features[key] === true;

    document.querySelectorAll('.qa-tab').forEach(tab => {
        const screen = tab.dataset.screen;

        let isEnabled;
        if (screen === 'cleo') {
            isEnabled = isFeatureOn('cleo') || isFeatureOn('summary');
        } else {
            const featureKey = screenToFeatureMap[screen];
            isEnabled = featureKey ? isFeatureOn(featureKey) : true;
        }

        tab.style.display = isEnabled ? '' : 'none';
    });
}

async function ensureApplyFeatureVisibility() {
    try {
        if (window.QAContext?.features) {
            applyFeatureVisibility(window.QAContext.features);
            return window.QAContext.features;
        }

        const cfg = await IndexLibrary.GetExtensionConfig();
        if (cfg && cfg.features) {
            applyFeatureVisibility(cfg.features);
            return cfg.features;
        }
    } catch (e) { /* ignore */ }
    return null;
}

function ensureSDKReady() {
    if (!sdkReadyPromise) {
        sdkReadyPromise = (async () => {
            const [, config] = await Promise.all([
                IndexLibrary.InitializeSDK(),
                IndexLibrary.GetExtensionConfig()
            ]);

            if (!config) {
                throw new Error("Failed to load config.json, Please reload the extension.");
            }

            const [organizationName, project, accessToken, workItemId] = await Promise.all([
                IndexLibrary.GetAccountNameAsync(),
                IndexLibrary.GetCurrentProject(),
                IndexLibrary.GetAccessToken(),
                IndexLibrary.CurrentWorkItem().catch(() => "")
            ]);

            window.QAContext = {
                organizationName,
                organizationId: IndexLibrary.GetAccountId(),
                projectId: project?.id,
                projectName: project?.name,
                userEmail: IndexLibrary.GetUserEmail?.(),
                accessToken,
                workItemId,
                baseAPIUrl: config.apiBaseUrl,
                publisherId: config.publisherId,
                extensionId: config.extensionId,
                features: config.features || {},
                userDisplayName: IndexLibrary.GetUserDisplayName?.(),
                userId: IndexLibrary.GetUserId?.()
            };

            await ensureApplyFeatureVisibility().catch(() => { });
        })();

        sdkReadyPromise.catch(() => { sdkReadyPromise = null; });
    }

    return sdkReadyPromise;
}

function initLicenseContext() {
    if (window.QALicenseContext) return;

    window.QALicenseContext = {
        isUserLicensed: false,
        isOrgExists: false,
        isOrgLicenseValid: false,
        orgLicenseDetails: null,
        productUserTypes: {}
    };
}

function ensureLicenseReady(productKeys) {
    initLicenseContext();

    if (!licenseReadyPromise) {
        licenseReadyPromise = loadLicenseContext(window.QAContext);
        licenseReadyPromise.catch(() => { licenseReadyPromise = null; });
    }

    prefetchProductLicenseTypes(window.QAContext, productKeys);

    return licenseReadyPromise;
}

function prefetchProductLicenseTypes(ctx, productKeys) {
    (productKeys || []).forEach(productKey => {
        const fieldName = PRODUCT_LICENSE_MAP[productKey];
        if (fieldName) {
            loadProductLicenseType(ctx, productKey, fieldName).catch(() => { });
        }
    });
}

function resetProductLicenseCache() {
    productTypeRequests.clear();
    if (window.QALicenseContext) {
        window.QALicenseContext.productUserTypes = {};
    }
}

function fetchScreenHtml(name) {
    if (!screenHtmlRequests.has(name)) {
        const request = fetch(`${name}.html`).then(r => r.text());
        request.catch(() => screenHtmlRequests.delete(name));
        screenHtmlRequests.set(name, request);
    }

    return screenHtmlRequests.get(name);
}

async function loadScreenHtml(name) {
    activeScreenName = name;

    // Cleo lays itself out full height (pinned input), so the shell drops its
    // padding and scrolling for that screen only.
    const root = document.getElementById("screen-root");
    if (root) {
        root.classList.toggle("qa-content--flush", name === "cleo");
    }

    try {
        const html = await fetchScreenHtml(name);
        if (activeScreenName !== name) return;

        ScreenManager.activate(name, html);
    } catch (err) {
        console.error(err);
        if (activeScreenName === name && root) {
            root.innerHTML = `<div class="alert alert-danger" style="margin:8px">Failed to load this screen. Please reload the page.</div>`;
        }
    }
}

window.addEventListener('qa-workitem-saved', (e) => {
    const newId = e.detail?.id;
    if (!newId || !window.QAContext || newId === window.QAContext.workItemId) return;
    stopWorkItemPoller();
    window.QAContext.workItemId = newId;
    if (activeScreenName) {
        loadScreenHtml(activeScreenName);
    }
});

async function loadLicenseContext(ctx) {
    initLicenseContext();

    const userEndpoint =
        `/api/License/IsUserLicensed` +
        `?organizationName=${encodeURIComponent(ctx.organizationName)}` +
        `&email=${encodeURIComponent(ctx.userEmail)}`;

    const orgEndpoint = `/api/License/GetLicense`;

    const [userRes, orgRes] = await Promise.all([
        IndexLibrary.GetRequest({
            baseAPIUrl: ctx.baseAPIUrl,
            endpoint: userEndpoint,
            azureAuthenticationHeader: ctx.accessToken,
            organizationName: ctx.organizationName,
            organizationId: ctx.organizationId,
            headers: {
                "Content-Type": "application/json"
            }
        }),
        IndexLibrary.PostRequest({
            baseAPIUrl: ctx.baseAPIUrl,
            endpoint: orgEndpoint,
            azureAuthenticationHeader: ctx.accessToken,
            organizationName: ctx.organizationName,
            organizationId: ctx.organizationId,
            body: {
                organizationName: ctx.organizationName
            }
        })
    ]);

    const isUserLicensed =
        userRes.ok && await userRes.json();

    let isOrgExists = false;
    let isOrgLicenseValid = false;
    let orgLicenseDetails = null;

    if (orgRes.ok) {
        const orgJson = await orgRes.json();
        orgLicenseDetails = orgJson;
        isOrgExists = orgJson && !orgJson.isDeleted;

        if (isOrgExists && orgJson.expiryDateTimeUtc) {
            const now = new Date();
            const expiry = new Date(orgJson.expiryDateTimeUtc);
            isOrgLicenseValid = expiry > now;
        }
    }
    else {
        isOrgExists = false;
        isOrgLicenseValid = false;
    }

    Object.assign(window.QALicenseContext, {
        isUserLicensed,
        isOrgExists,
        isOrgLicenseValid,
        orgLicenseDetails
    });
}


function disableAllTabs() {
    document.querySelectorAll(".qa-tab").forEach(tab => {
        tab.classList.add("qa-tab-disabled");
        tab.style.pointerEvents = "none";
        tab.style.opacity = "0.5";
    });
}

function enableAllTabs() {
    document.querySelectorAll(".qa-tab").forEach(tab => {
        tab.classList.remove("qa-tab-disabled");
        tab.style.pointerEvents = "auto";
        tab.style.opacity = "1";
    });
}

function showLicenseScreen(type) {
    const root = document.getElementById("screen-root");

    if (type === "org-not-exists") {
        // root.innerHTML = `
        // <div class="alert alert-info" style="margin:8px">
        //     Your organization does not have a Devops Assist AI license.
        //     <div style="margin-top:10px;">
        //         <button id="start-trial-btn" class="btn btn-primary btn-sm">
        //             Start Trial
        //         </button>
        //     </div>
        // </div>
        // `;
        // document
        //     .getElementById("start-trial-btn")
        //     ?.addEventListener("click", startTrial);

        IndexLibrary.AutoCreateTrialLicense();
        return;
    }

    if (type === "unauthorized") {
        root.innerHTML = `
            <div class="alert alert-danger" style="margin:8px">
                You are not authorized to perform this action.
                Please contact your organization administrator.
            </div>
        `;
        return;
    }

    if (type === "license-expired") {
        root.innerHTML = `
            <div class="alert alert-info" style="margin:8px">
                Your license is invalid or expired. Please contact your organization administrator.
            </div>
        `;
        return;
    }

    if (type === "license-unavailable") {
        root.innerHTML = `
            <div class="alert alert-warning" style="margin:8px">
                We could not verify your license right now. Please reload the page.
            </div>
        `;
        return;
    }
}

function loadProductLicenseType(ctx, productKey, fieldName) {
    initLicenseContext();

    const cache = window.QALicenseContext.productUserTypes;

    if (productKey in cache) {
        return Promise.resolve(cache[productKey]);
    }

    const inFlight = productTypeRequests.get(productKey);
    if (inFlight) return inFlight;

    const endpoint =
        `/api/License/GetUserLicenseType` +
        `?organizationName=${encodeURIComponent(ctx.organizationName)}` +
        `&email=${encodeURIComponent(ctx.userEmail)}` +
        `&fieldName=${encodeURIComponent(fieldName)}`;

    const request = (async () => {
        const res = await IndexLibrary.GetRequest({
            baseAPIUrl: ctx.baseAPIUrl,
            endpoint,
            azureAuthenticationHeader: ctx.accessToken,
            organizationName: ctx.organizationName,
            organizationId: ctx.organizationId
        });

        let userType = null;

        if (res.ok) {
            const text = await res.text();
            if (text && text.trim() !== "") {
                userType = JSON.parse(text);
            }
            cache[productKey] = userType;
        } else if (res.status === 404 || res.status === 204) {
            console.warn(`License type not found for ${productKey}`);
            cache[productKey] = null;
        } else {
            console.warn(`License type lookup failed for ${productKey} (${res.status})`);
        }

        productTypeRequests.delete(productKey);
        return userType;
    })();

    request.catch(() => productTypeRequests.delete(productKey));
    productTypeRequests.set(productKey, request);

    return request;
}

function showToast({ title, icon }) {
    Swal.fire({
        toast: true,
        position: "top-end",
        icon,
        title,
        showConfirmButton: false,
        timer: 2200,
        timerProgressBar: false,
    });
}

function showSuccess(message) {
    showToast({ title: message, icon: "success" });
}

function showWarning(message) {
    showToast({ title: message, icon: "warning" });
}

function showError(message) {
    showToast({ title: message, icon: "error" });
}

function handleApiFailure(res, options = {}) {
    const {
        unauthorizedMessage = "Your session expired. Please reload the page.",
        genericMessage = "Something went wrong. Please try again."
    } = options;

    if (!res) {
        showError(genericMessage);
        return false;
    }

    if (res.status === 401 || res.status === 403) {
        showError(unauthorizedMessage);
        return false;
    }

    if (!res.ok) {
        showError(genericMessage);
        return false;
    }

    return true;
}

async function confirmAction({
    text = "",
    confirmText = "Confirm",
    cancelText = "Cancel",
} = {}) {
    const result = await Swal.fire({
        text,
        width: "300px",
        padding: "10px",
        showCancelButton: true,
        confirmButtonText: confirmText,
        cancelButtonText: cancelText,
        reverseButtons: true,
        focusCancel: true,
        buttonsStyling: true,

    });

    return result.isConfirmed === true;
}

async function startTrial() {
    renderTrialModal();
}

function renderTrialModal() {

    const existing = document.getElementById("qa-trial-modal");
    if (existing) existing.remove();

    const modal = document.createElement("div");
    modal.id = "qa-trial-modal";
    modal.innerHTML = `
        <div class="qa-modal-backdrop"></div>
        <div class="qa-modal">
            <h3>Subscription Details</h3>

            <div class="qa-modal-row">
                <label>Organization Name:</label>
                <span>${qaEscapeHtml(window.QAContext.organizationName)}</span>
            </div>

            <div class="qa-modal-row">
                <label>Account Owner Name:</label>
                <span>${qaEscapeHtml(window.QAContext.userDisplayName)}</span>
            </div>

            <div class="qa-modal-row">
                <label>Account Owner Email:</label>
                <span>${qaEscapeHtml(window.QAContext.userEmail)}</span>
            </div>

            <div class="qa-modal-row">
                <label>Subscription Type:</label>
                <span>Trial</span>
            </div>

            <div class="qa-modal-row">
                <label>Number of Licenses:</label>
                <input id="qa-trial-licenses" type="number" value="5" min="1" />
            </div>

            <div class="qa-modal-row">
                <label>Number of Tokens:</label>
                <input id="qa-trial-tokens" type="number" value="100000" min="1" />
            </div>

            <div class="qa-modal-actions">
                <button id="qa-confirm-trial" class="btn btn-primary btn-sm">
                    Start Trial
                </button>
                <button id="qa-cancel-trial" class="btn btn-secondary btn-sm">
                    Cancel
                </button>
            </div>
        </div>
    `;

    document.body.appendChild(modal);

    document.getElementById("qa-cancel-trial")
        .addEventListener("click", closeTrialModal);

    document.getElementById("qa-confirm-trial")
        .addEventListener("click", confirmTrialStart);
}

function closeTrialModal() {
    const modal = document.getElementById("qa-trial-modal");
    if (modal) modal.remove();
}

async function confirmTrialStart() {

    const ctx = window.QAContext;

    const numberOfLicenses =
        parseInt(document.getElementById("qa-trial-licenses").value, 10);

    const numberOfTokens =
        parseInt(document.getElementById("qa-trial-tokens").value, 10);

    const userName =
        ctx.userDisplayName || ctx.userEmail?.split('@')[0] || "";

    const userEmail =
        ctx.userEmail || "";

    const userId =
        ctx.userId || "";

    try {
        const res = await IndexLibrary.PostRequest({
            baseAPIUrl: ctx.baseAPIUrl,
            endpoint: `/api/License/CreateTrialLicense` +
                `?numberOfLicenses=${numberOfLicenses}` +
                `&numberOfTokens=${numberOfTokens}` +
                `&name=${encodeURIComponent(userName)}` +
                `&email=${encodeURIComponent(userEmail)}` +
                `&userId=${userId}`,
            azureAuthenticationHeader: ctx.accessToken,
            organizationName: ctx.organizationName,
            organizationId: ctx.organizationId
        });

        if (!res.ok) {
            const error = await res.json();
            console.error(error);
            showError("Failed to start trial.");
            return;
        }

        closeTrialModal();

        showSuccess("Trial started successfully!");

        resetProductLicenseCache();
        await loadLicenseContext(ctx);
        enableAllTabs();

        const activeTab = document.querySelector(".qa-tab.active");
        if (activeTab) activeTab.click();

    } catch (err) {
        console.error(err);
        showError("Something went wrong while starting trial.");
    }
}



async function activateTab(name) {
    await ensureSDKReady();

    fetchScreenHtml(name).catch(() => { });

    try {
        await ensureLicenseReady(SCREEN_LICENSE_KEYS[name]);
    } catch (err) {
        console.error(err);
        showLicenseScreen("license-unavailable");
        return;
    }

    const license = window.QALicenseContext;

    if (license.isOrgExists && !license.isOrgLicenseValid && !license.isUserLicensed) {
        disableAllTabs();
        showLicenseScreen("unauthorized");
        return;
    }
    if (!license.isOrgExists) {
        disableAllTabs();
        showLicenseScreen("org-not-exists");
        return;
    }
    if (!license.isOrgLicenseValid) {
        disableAllTabs();
        showLicenseScreen("license-expired");
        return;
    }

    if (!license.isUserLicensed) {
        disableAllTabs();
        showLicenseScreen("unauthorized");
        return;
    }

    let screenToLoad = name;

    if (name === "cleo") {
        const cleoType = await loadProductLicenseType(
            window.QAContext, "cleo", PRODUCT_LICENSE_MAP.cleo);

        if (cleoType === null) {
            const summaryType = await loadProductLicenseType(
                window.QAContext, "summary", PRODUCT_LICENSE_MAP.summary);
            if (summaryType === null) {
                showLicenseScreen("unauthorized");
                return;
            }
            screenToLoad = "summary";
        }
    } else {
        const fieldName = PRODUCT_LICENSE_MAP[name];
        if (fieldName === undefined) {
            console.error(`No license mapping found for screen: ${name}`);
            showLicenseScreen("unauthorized");
            return;
        }

        const userType = await loadProductLicenseType(
            window.QAContext,
            name,
            fieldName
        );
        if (userType === null && fieldName !== "ptUserType") {
            showLicenseScreen("unauthorized");
            return;
        }
    }

    if (!window.QAContext.workItemId) {
        activeScreenName = screenToLoad;
        const root = document.getElementById("screen-root");
        if (root) {
            root.classList.remove("qa-content--flush");
            root.innerHTML = `<div class="qa-summary-loading"><div class="qa-spinner"></div></div>`;
        }
        startWorkItemPoller();
        return;
    }

    loadScreenHtml(screenToLoad);
}

document.addEventListener("DOMContentLoaded", () => {
    const tabs = document.querySelectorAll(".qa-tab");

    tabs.forEach(t => {
        t.addEventListener("click", () => {
            tabs.forEach(x => x.classList.remove("active"));
            t.classList.add("active");
            activateTab(t.dataset.screen);
        });
    });

    ensureSDKReady().then(() => {
        const firstVisible = Array.from(tabs).find(t => window.getComputedStyle(t).display !== 'none');
        if (!firstVisible) return;

        tabs.forEach(x => x.classList.remove("active"));
        firstVisible.classList.add("active");
        activateTab(firstVisible.dataset.screen);
    }).catch(err => {
        console.error(err);
        const root = document.getElementById("screen-root");
        if (root) {
            root.innerHTML = `<div class="alert alert-danger" style="margin:8px">${qaEscapeHtml(err?.message || "Failed to initialize the Quick Access widget.")}</div>`;
        }
    });
});
