import { fetchEndpoint } from "./_global--endpoint.js";
import { extractJson } from "./_global--extract-json.js";
import { jsVar } from "./_global--enqueue-loader.js";
import { neoError } from "./_global--log.js";
import { removeAllQueryParams, stripProtocol } from "./_global--url-helper.js";
import { neo__ } from "./_global--translation.js";
import { pricingUrl } from "./_global-pricing-url.js";
import { pluginUrl } from "./_global-plugin-and-uploads-url.js";
import { getFileType } from "./_global-media-file-type.js";
import { DomNodeHelper, escapeHtml } from "./_global--dom-node-helper.js";
import Swal from "./_global-sweetalert2.js";

const generatedImageTexts = new Map();
let lowestRemainingRequests = null;
const contextRequestTimeoutSeconds = 12; const pageContextTimeoutSeconds = 5; const generationRequestTimeoutSeconds = 145;
function getGenerationStateKey(imageUrl, textType) { return `${textType}|${removeAllQueryParams(imageUrl).split("#")[0]}`; }

async function showAiSetupMissingDialog(message, swalContainerClass) {
    const aiSettingsUrl = jsVar("neoAiSettingsSectionUrl");
    const result = await Swal.fire({ customClass: { container: swalContainerClass }, icon: "warning", title: neo__("AI setup missing", "AI-Einrichtung fehlt"), text: message || neo__("Add an OpenAI API key or configure a WordPress AI provider.", "Hinterlege einen OpenAI API-Key oder konfiguriere einen WordPress-AI-Provider."), showCancelButton: !!aiSettingsUrl, confirmButtonText: aiSettingsUrl ? neo__("Open neoAI settings", "neoAI-Einstellungen öffnen") : neo__("OK", "OK"), cancelButtonText: neo__("OK", "OK") });
    if (aiSettingsUrl && result.isConfirmed) { window.open(aiSettingsUrl, "_blank", "noopener"); }
}

export function interfaceClearGeneratedImageTexts20260713({ imageUrl = "", textType = "" } = {}) {
    if (imageUrl === "" || !["title", "alt"].includes(textType)) { throw new Error("imageUrl and textType title or alt are required."); }
    generatedImageTexts.delete(getGenerationStateKey(imageUrl, textType));
}

export async function interfaceGenerateImageText20260713({ imageUrl = "", textType = "", swalContainerClass = "", nearbyTitles = [], imageTitle = null, bulkConfirmationState = null, errorHandler = null } = {}) {
    if (imageUrl === "" || !["title", "alt"].includes(textType)) { throw new Error("imageUrl and textType title or alt are required."); }
    if (getFileType(imageUrl) !== "image") { await Swal.fire({ customClass: { container: swalContainerClass }, icon: "error", title: neo__("Not an image", "Kein Bild"), text: textType === "title" ? neo__("AI title generation is only available for images.", "AI-Titel kann nur für Bilder generiert werden.") : neo__("AI alt text generation is only available for images.", "AI-Alt-Text kann nur für Bilder generiert werden.") }); return null; }

    const getImageContextSnippets = async () => {
        const contextBudget = 60000; const pageBudget = 30000; const snippets = []; const seenSnippets = new Set();
        const normalizedImageUrl = removeAllQueryParams(imageUrl).split("#")[0];
        const imagePath = new URL(normalizedImageUrl, location.origin).pathname;
        const imageUrlNeedles = [...new Set([stripProtocol(normalizedImageUrl), imagePath, encodeURI(stripProtocol(normalizedImageUrl)), encodeURI(imagePath)].filter(Boolean))];
        let targetsResponse = null; try { targetsResponse = await fetchEndpoint("/wp-json/neo/ai-image-usage-context-targets", { method: "GET", query: { "image-url": normalizedImageUrl }, timeout: contextRequestTimeoutSeconds, timeoutMessage: "neoAI context lookup timed out." }).then(extractJson); } catch (error) { neoError("neoAI context lookup failed:", error); }
        for (const target of targetsResponse?.targets ?? []) {
            if (snippets.join("").length >= contextBudget) { break; }
            let htmlText = ""; const abortController = new AbortController(); const timeoutId = setTimeout(() => abortController.abort(), pageContextTimeoutSeconds * 1000);
            try { htmlText = await fetch(target.url, { credentials: "same-origin", signal: abortController.signal }).then(response => response.ok ? response.text() : ""); } catch (error) { neoError("neoAI page HTML fetch failed:", abortController.signal.aborted ? new Error("neoAI page context request timed out.") : error); continue; } finally { clearTimeout(timeoutId); }
            const bodyNode = new DOMParser().parseFromString(htmlText, "text/html").body;
            bodyNode.querySelectorAll("img").forEach(imgNode => { if ([...imgNode.attributes].some(attribute => imageUrlNeedles.some(imageUrlNeedle => attribute.value.includes(imageUrlNeedle)))) { imgNode.replaceWith(document.createTextNode(" [[THE IMAGE IS HERE]] ")); } });
            bodyNode.querySelectorAll("script, style, img, header, footer, nav, aside, [role=\"banner\"], [role=\"contentinfo\"], [role=\"navigation\"], [role=\"complementary\"], .head, .site-head, .page-head, .masthead, .site-header, .page-header, .topbar, .navbar, .menu, .breadcrumb, .sidebar, .widget, .cookie, .popup, .modal, .newsletter, .social, .share, .pagination, .related, .comments, #wpadminbar, #header, #footer, #sidebar, #comments").forEach(node => node.remove());
            const snippet = (bodyNode.innerText || "").replace(/\s+/g, " ").trim().slice(0, pageBudget);
            if (snippet === "" || seenSnippets.has(snippet)) { continue; }
            seenSnippets.add(snippet); snippets.push(snippet);
        }
        let usedChars = 0; return snippets.filter(snippet => { usedChars += snippet.length; return usedChars <= contextBudget; });
    };

    const confirmFreeProviderRequest = async ({ prompt, confirmedImageUrl }) => {
        if (!bulkConfirmationState && localStorage.getItem("neoAiFreeProviderConfirmationHidden") === "1") { return true; }
        if (bulkConfirmationState?.hidden) { return true; }
        const previousBulkConfirmation = bulkConfirmationState?.confirmationQueue; let resolveBulkConfirmation = null;
        if (bulkConfirmationState) { bulkConfirmationState.confirmationQueue = new Promise(resolve => resolveBulkConfirmation = resolve); }
        if (previousBulkConfirmation && !await previousBulkConfirmation) { resolveBulkConfirmation(false); return false; }
        if (bulkConfirmationState?.hidden) { resolveBulkConfirmation(true); return true; }
        try {
            if (bulkConfirmationState && localStorage.getItem("neoAiFreeProviderConfirmationHidden") === "1") { bulkConfirmationState.hidden = true; resolveBulkConfirmation(true); return true; }
            if (!document.querySelector("link[data-neo-ai--css]")) { const linkNode = new DomNodeHelper(`<link rel="stylesheet" href="${escapeHtml(pluginUrl() + "/neo-ai.css")}" data-neo-ai--css>`).getNode(); document.head.append(linkNode); await new Promise((resolve) => { linkNode.addEventListener("load", resolve, { once: true }); linkNode.addEventListener("error", resolve, { once: true }); }); }
            const bulkRequestCountText = bulkConfirmationState ? `<strong>${escapeHtml(neo__("Planned free AI requests for this bulk generation: %s", "Geplante kostenfreie AI-Anfragen für diese Bulk-Generierung: %s").replace("%s", bulkConfirmationState.requestCount.toLocaleString()))}</strong>` : "";
            const exampleImageLabel = bulkConfirmationState ? `<small class="neo-ai--free-provider-example-label">${escapeHtml(neo__("Example image", "Beispielbild"))}</small>` : ""; const examplePromptLabel = bulkConfirmationState ? `<small class="neo-ai--free-provider-example-label">${escapeHtml(neo__("Example prompt", "Beispiel-Prompt"))}</small>` : "";
            const contentNode = new DomNodeHelper(`<div class="neo-ai--free-provider-popup">${bulkRequestCountText}<div class="neo-ai--free-provider-example">${exampleImageLabel}<img src="${escapeHtml(confirmedImageUrl)}" alt=""></div><div class="neo-ai--free-provider-example">${examplePromptLabel}<details><summary>${escapeHtml(neo__("Prompt to be sent", "Gesendeten Prompt anzeigen"))}</summary><pre>${escapeHtml(prompt)}</pre></details></div><small>${escapeHtml(neo__("Image, prompt, and page context are sent through neoAI to OpenAI in the USA. Do not send personal or confidential data.", "Bild, Prompt und Seitenkontext werden über neoAI an OpenAI in den USA gesendet. Sende keine personenbezogenen oder vertraulichen Daten."))} <a href="${escapeHtml(neo__("https://neo-wp.com/privacy-policy-plugins/?ref=neo-ai--consent", "https://neo-wp.com/de/privacy-policy-plugins/?ref=neo-ai--consent"))}" target="_blank" rel="noopener">${escapeHtml(neo__("Privacy details", "Datenschutzdetails"))}</a></small><label><input type="checkbox" data-neo-ai--hide-permanently><span>${escapeHtml(neo__("Do not show again", "Nicht mehr anzeigen"))}</span></label></div>`).getNode();
            const hideCheckboxNode = contentNode.querySelector("[data-neo-ai--hide-permanently]");
            const result = await Swal.fire({ title: neo__("Confirm free AI request", "Kostenfreie AI-Anfrage bestätigen"), html: contentNode, showCancelButton: true, confirmButtonText: bulkConfirmationState ? neo__("Send %s free AI requests", "%s kostenfreie AI-Anfragen senden").replace("%s", bulkConfirmationState.requestCount.toLocaleString()) : neo__("Send free AI request", "Kostenfreie AI-Anfrage senden"), cancelButtonText: neo__("Cancel", "Abbrechen"), customClass: { container: `neo-ai--free-provider-swal ${swalContainerClass}` } });
            if (!result.isConfirmed) { if (bulkConfirmationState) { bulkConfirmationState.cancelled = true; } resolveBulkConfirmation?.(false); return false; }
            if (hideCheckboxNode.checked) { localStorage.setItem("neoAiFreeProviderConfirmationHidden", "1"); }
            if (bulkConfirmationState) { bulkConfirmationState.hidden = true; }
            resolveBulkConfirmation?.(true); return true;
        } catch (error) {
            resolveBulkConfirmation?.(false); throw error;
        }
    };

    const showAiErrorDialog = async (error) => {
        if (error?.data?.code === "neo-ai__quota-exhausted") { const result = await Swal.fire({ customClass: { container: swalContainerClass }, icon: "error", title: neo__("Free quota exhausted", "Kostenfreies Kontingent ausgeschöpft"), text: bulkConfirmationState ? neo__("Bulk generation was stopped because the free neoAI quota for this domain is exhausted. Suggestions generated so far remain available for review. Get neoMedia Pro for a higher quota, or configure your own API key.", "Die Bulk-Generierung wurde beendet, weil das kostenfreie neoAI Kontingent dieser Domain ausgeschöpft ist. Bereits generierte Vorschläge bleiben zur Prüfung erhalten. Mit neoMedia Pro erhältst du ein höheres Kontingent; alternativ kannst du einen eigenen API-Key hinterlegen.") : neo__("The free neoAI quota for this domain is exhausted. Get neoMedia Pro for a higher quota, or you can configure your own API key.", "Das kostenfreie neoAI Kontingent dieser Domain ist ausgeschöpft. Mit neoMedia Pro erhältst du ein höheres Kontingent; alternativ kannst du einen eigenen API-Key hinterlegen."), showDenyButton: true, confirmButtonText: neo__("View Pro pricing", "Pro-Preise ansehen"), denyButtonText: neo__("Open neoAI settings", "neoAI-Einstellungen öffnen"), denyButtonColor: "var(--wp-admin-theme-color, #2271b1)" }); if (result.isConfirmed) { window.open(pricingUrl("neo-media"), "_blank", "noopener"); } if (result.isDenied) { window.open(jsVar("neoAiSettingsSectionUrl"), "_blank", "noopener"); } return; }
        if (error?.data?.code === "ai-setup-missing") { await showAiSetupMissingDialog(error.message, swalContainerClass); return; }
        const endpointErrorMessage = String(error?.message ?? "").trim();
        let errorMessage = textType === "title" ? neo__("Could not generate title.", "Titel konnte nicht generiert werden.") : neo__("Could not generate alt text.", "Alt-Text konnte nicht generiert werden.");
        if (endpointErrorMessage !== "") { errorMessage += " " + endpointErrorMessage; }
        if (error.message?.includes("The image data you provided does not represent a valid image")) { errorMessage = neo__("OpenAI could not read this image. Please try a valid JPG, PNG, GIF or WebP image.", "OpenAI konnte dieses Bild nicht lesen. Bitte nutze ein gültiges JPG-, PNG-, GIF- oder WebP-Bild."); }
        await Swal.fire({ customClass: { container: swalContainerClass }, icon: "error", title: neo__("AI error", "AI-Fehler"), text: errorMessage, confirmButtonText: neo__("OK", "OK") });
    };
    const stateKey = getGenerationStateKey(imageUrl, textType);
    try {
        const requestBody = { "image-url": imageUrl, "text-type": textType, "nearby-titles": nearbyTitles, "image-title": imageTitle, "context-snippets": await getImageContextSnippets(), "previous-generations": generatedImageTexts.get(stateKey) ?? [] };
        let response = await fetchEndpoint("/wp-json/neo/ai-generate-image-text", { method: "POST", body: requestBody, timeout: generationRequestTimeoutSeconds, timeoutMessage: neo__("AI generation timed out. Please try again.", "Die AI-Generierung hat zu lange gedauert. Bitte versuche es erneut.") }).then(extractJson);
        if (response.confirmationRequired) { if (!await confirmFreeProviderRequest({ prompt: response.prompt, confirmedImageUrl: response.imageUrl })) { return null; } response = await fetchEndpoint("/wp-json/neo/ai-generate-image-text", { method: "POST", body: { ...requestBody, "free-provider-confirmed": true }, timeout: generationRequestTimeoutSeconds, timeoutMessage: neo__("AI generation timed out. Please try again.", "Die AI-Generierung hat zu lange gedauert. Bitte versuche es erneut.") }).then(extractJson); }
        if (response.ok === false) { if (errorHandler) { errorHandler(new Error(response.warning || "No AI connection available.")); } else { await showAiSetupMissingDialog(response.warning, swalContainerClass); } return null; }
        if (typeof response.text !== "string" || response.text === "") { throw new Error("neoAI returned no generated image text."); }
        generatedImageTexts.set(stateKey, [...(generatedImageTexts.get(stateKey) ?? []), response.text]);
        const remainingRequests = response.remaining_requests === undefined || response.remaining_requests === null ? null : Number(response.remaining_requests);
        const hasOpenSwalDialog = Swal.isVisible() && !document.querySelector(".swal2-popup")?.classList.contains("swal2-toast");
        if (Number.isFinite(remainingRequests) && (lowestRemainingRequests === null || remainingRequests < lowestRemainingRequests)) { lowestRemainingRequests = remainingRequests; if (!hasOpenSwalDialog) { Swal.fire({ toast: true, position: "bottom-start", icon: "info", title: neo__("You have %s free image generations left", "Dir stehen noch %s kostenfreie Bildgenerierungen zur Verfügung").replace("%s", remainingRequests.toLocaleString()), showConfirmButton: false, timer: 5000, timerProgressBar: true, customClass: { container: swalContainerClass } }); } }
        return response.text;
    } catch (error) { neoError(error); if (errorHandler) { errorHandler(error); if (error?.data?.code === "neo-ai__quota-exhausted" && bulkConfirmationState && !bulkConfirmationState.quotaErrorDialogShown) { bulkConfirmationState.quotaErrorDialogShown = true; await showAiErrorDialog(error); } } else { await showAiErrorDialog(error); } return null; }
}
