// Embedded stuff data from graph (all formats)
const stuffDataJson = {{ stuff_data_json | escape_script_tag | safe }};
const stuffDataText = {{ stuff_data_text_json | escape_script_tag | safe }};
const stuffDataHtml = {{ stuff_data_html_json | escape_script_tag | safe }};
const stuffMetadata = {{ stuff_metadata_json | escape_script_tag | safe }};
const stuffContentType = {{ stuff_content_type_json | escape_script_tag | safe }};
const mermaidCode = {{ mermaid_code | tojson }};

// Track current state
let currentStuffId = null;
let currentFormat = 'html';
let currentTheme = {{ theme | tojson }};

// Include shared utility functions
{% include 'stuff/_stuff_utils.js.jinja2' %}

// Theme-specific color palettes for custom node styling
const themePalettes = {
    default: {
        page: { bg: '#f8fafc', text: '#1e293b', label: '#64748b', border: '#cbd5e1',
                borderHover: '#94a3b8', selectBg: 'white', containerBg: 'white' },
        failed: { fill: '#fee2e2', stroke: '#dc2626' },
        controller: { fill: '#dbeafe', stroke: '#2563eb' },
        pipe: { fill: '#dbeafe', stroke: '#2563eb' },
        stuff: { fill: '#fef3c7', stroke: '#d97706' },
        subgraph: ['#eff6ff', '#ecfdf5', '#fefce8', '#fdf4ff', '#f0fdfa']
    },
    dark: {
        page: { bg: '#1a1a2e', text: '#e0f7fa', label: '#80deea', border: '#2d4a5a',
                borderHover: '#00bcd4', selectBg: '#2d4a5a', containerBg: '#16213e' },
        failed: { fill: '#3a1a1a', stroke: '#ff5252' },
        controller: { fill: '#1a3a4a', stroke: '#00e5ff' },
        pipe: { fill: '#1a3a4a', stroke: '#00e5ff' },
        stuff: { fill: '#2a1a3a', stroke: '#ff4081' },
        subgraph: ['#1e3a4a', '#1a3a3a', '#2a3a4a', '#1a2a4a', '#2a4a4a']
    },
    forest: {
        page: { bg: '#f0fdf4', text: '#14532d', label: '#166534', border: '#86efac',
                borderHover: '#4ade80', selectBg: 'white', containerBg: '#fafffe' },
        failed: { fill: '#fecaca', stroke: '#b91c1c' },
        controller: { fill: '#dcfce7', stroke: '#16a34a' },
        pipe: { fill: '#dcfce7', stroke: '#16a34a' },
        stuff: { fill: '#fef9c3', stroke: '#ca8a04' },
        subgraph: ['#d1fae5', '#bbf7d0', '#d9f99d', '#fef08a', '#a7f3d0']
    },
    neutral: {
        page: { bg: '#fafafa', text: '#171717', label: '#525252', border: '#d4d4d4',
                borderHover: '#a3a3a3', selectBg: 'white', containerBg: 'white' },
        failed: { fill: '#fecaca', stroke: '#991b1b' },
        controller: { fill: '#e5e5e5', stroke: '#525252' },
        pipe: { fill: '#e5e5e5', stroke: '#525252' },
        stuff: { fill: '#fef3c7', stroke: '#92400e' },
        subgraph: ['#f5f5f5', '#e5e5e5', '#fafaf9', '#f5f5f4', '#fafafa']
    },
    base: {
        page: { bg: '#fff', text: '#18181b', label: '#52525b', border: '#e4e4e7',
                borderHover: '#a1a1aa', selectBg: 'white', containerBg: '#fafafa' },
        failed: { fill: '#ffe4e6', stroke: '#e11d48' },
        controller: { fill: '#e0f2fe', stroke: '#0284c7' },
        pipe: { fill: '#e0f2fe', stroke: '#0284c7' },
        stuff: { fill: '#ffedd5', stroke: '#ea580c' },
        subgraph: ['#f0f9ff', '#f0fdf4', '#fffbeb', '#fdf4ff', '#ecfeff']
    }
};

function applyPageTheme(theme) {
    const palette = themePalettes[theme]?.page || themePalettes.default.page;
    document.documentElement.style.setProperty('--bg-color', palette.bg);
    document.documentElement.style.setProperty('--text-color', palette.text);
    document.documentElement.style.setProperty('--label-color', palette.label);
    document.documentElement.style.setProperty('--border-color', palette.border);
    document.documentElement.style.setProperty('--border-hover', palette.borderHover);
    document.documentElement.style.setProperty('--select-bg', palette.selectBg);
    document.documentElement.style.setProperty('--container-bg', palette.containerBg);
}

function applyThemeColors(code, theme) {
    const palette = themePalettes[theme] || themePalettes.default;
    let result = code;

    // Replace classDef colors
    result = result.replace(
        /classDef\s+failed\s+fill:[^,]+,stroke:[^\s\n]+/g,
        `classDef failed fill:${palette.failed.fill},stroke:${palette.failed.stroke}`
    );
    result = result.replace(
        /classDef\s+controller\s+fill:[^,]+,stroke:[^\s\n]+/g,
        `classDef controller fill:${palette.controller.fill},stroke:${palette.controller.stroke}`
    );
    result = result.replace(
        /classDef\s+pipe\s+fill:[^,]+,stroke:[^\s\n]+/g,
        `classDef pipe fill:${palette.pipe.fill},stroke:${palette.pipe.stroke}`
    );
    result = result.replace(
        /classDef\s+pipe_failed\s+fill:[^,]+,stroke:[^\s\n]+/g,
        `classDef pipe_failed fill:${palette.failed.fill},stroke:${palette.failed.stroke}`
    );
    result = result.replace(
        /classDef\s+stuff\s+fill:[^,]+,stroke:[^,]+/g,
        `classDef stuff fill:${palette.stuff.fill},stroke:${palette.stuff.stroke}`
    );

    // Replace subgraph fill colors (style sg_xxx fill:#xxx)
    const subgraphColors = palette.subgraph;
    let colorIndex = 0;
    result = result.replace(
        /style\s+(sg_[^\s]+)\s+fill:#[a-fA-F0-9]+/g,
        (match, subgraphId) => {
            const color = subgraphColors[colorIndex % subgraphColors.length];
            colorIndex++;
            return `style ${subgraphId} fill:${color}`;
        }
    );

    return result;
}

function initMermaid(theme) {
    mermaid.initialize({
        startOnLoad: false,
        theme: theme,
        flowchart: {
            useMaxWidth: true,
            htmlLabels: true,
            curve: 'basis'
        }
    });
}

function attachClickHandlers() {
    // Wait for mermaid to render, then attach click handlers
    setTimeout(() => {
        const svgContainer = document.querySelector('.mermaid svg');
        if (!svgContainer) return;

        // Find nodes by their flowchart IDs - use any available data source
        const allStuffIds = new Set([
            ...Object.keys(stuffDataJson || {}),
            ...Object.keys(stuffDataText || {}),
            ...Object.keys(stuffDataHtml || {})
        ]);

        for (const stuffId of allStuffIds) {
            // Mermaid generates IDs like 'flowchart-s_xxx-123'
            const nodes = svgContainer.querySelectorAll(`[id^="flowchart-${stuffId}"]`);
            nodes.forEach(node => {
                node.classList.add('clickable-stuff');
                node.addEventListener('click', (e) => {
                    e.stopPropagation();
                    showModal(stuffId);
                });
            });
        }
    }, 500);
}

async function renderDiagram(theme) {
    const container = document.getElementById('mermaid-diagram');
    const themedCode = applyThemeColors(mermaidCode, theme);
    container.innerHTML = themedCode;
    container.removeAttribute('data-processed');
    applyPageTheme(theme);
    initMermaid(theme);
    await mermaid.run({ nodes: [container] });
    attachClickHandlers();
}

// Set initial theme in dropdown
document.getElementById('theme-select').value = currentTheme;

// Handle theme change
document.getElementById('theme-select').addEventListener('change', async (e) => {
    currentTheme = e.target.value;
    await renderDiagram(currentTheme);
});

// Initial render on page load
renderDiagram(currentTheme);

// Set up format tab handlers
document.querySelectorAll('.format-tab').forEach(tab => {
    tab.addEventListener('click', () => {
        if (tab.disabled) return;
        const format = tab.dataset.format;
        setFormat(format);
    });
});

function setFormat(format) {
    currentFormat = format;
    // Update tab styling
    document.querySelectorAll('.format-tab').forEach(t => t.classList.remove('active'));
    document.getElementById(`tab-${format}`).classList.add('active');
    // Re-render content if modal is open
    if (currentStuffId) {
        renderContent(currentStuffId, format);
    }
}

function renderContent(stuffId, format) {
    const content = document.getElementById('modal-content');
    content.classList.remove('html-content', 'text-content', 'pdf-content', 'image-content');

    // Handle PDF content type with embedded viewer
    const contentType = stuffContentType?.[stuffId];
    const jsonData = stuffDataJson?.[stuffId];

    if (format === 'html' && contentType === 'application/pdf') {
        const pdfUrl = extractUrl(jsonData);
        if (pdfUrl) {
            content.classList.add('pdf-content');
            content.innerHTML = '';
            const embed = document.createElement('embed');
            embed.src = pdfUrl;
            embed.type = 'application/pdf';
            embed.style.cssText = 'width:100%; height:100%; border:none; min-height:500px;';
            content.appendChild(embed);
            updateOpenExternalButton(stuffId, contentType, jsonData);
            return;
        }
    }

    // Handle image content type
    if (format === 'html' && contentType?.startsWith('image/')) {
        const imageUrl = extractUrl(jsonData);
        if (imageUrl) {
            content.classList.add('image-content');
            content.innerHTML = '';
            const img = document.createElement('img');
            img.src = imageUrl;
            img.style.cssText = 'max-width:100%; max-height:100%; object-fit:contain;';
            img.alt = 'Image content';
            content.appendChild(img);
            updateOpenExternalButton(stuffId, contentType, jsonData);
            return;
        }
    }

    if (format === 'json') {
        const data = stuffDataJson?.[stuffId];
        content.innerHTML = '';
        content.textContent = data ? JSON.stringify(data, null, 2) : 'No JSON data available';
    } else if (format === 'text') {
        const data = stuffDataText?.[stuffId];
        content.classList.add('text-content');
        content.innerHTML = '';
        content.textContent = data || 'No text data available';
    } else if (format === 'html') {
        const data = stuffDataHtml?.[stuffId];
        if (data) {
            content.classList.add('html-content');
            content.innerHTML = DOMPurify.sanitize(data);
            makeLinksOpenInNewWindow(content);
        } else {
            content.innerHTML = '';
            content.textContent = 'No HTML data available';
        }
    }

    updateOpenExternalButton(stuffId, contentType, jsonData);
}

// Update visibility of the "open in new window" button (PDF only)
function updateOpenExternalButton(stuffId, contentType, jsonData) {
    const openExternalBtn = document.getElementById('open-external-btn');
    if (!openExternalBtn) return;

    const url = extractUrl(jsonData);
    // Only show for PDFs (images are handled by the download button)
    const shouldShow = contentType === 'application/pdf' && !!url;
    openExternalBtn.style.display = shouldShow ? '' : 'none';
}

function updateTabAvailability(stuffId) {
    const jsonTab = document.getElementById('tab-json');
    const textTab = document.getElementById('tab-text');
    const htmlTab = document.getElementById('tab-html');

    jsonTab.disabled = !stuffDataJson?.[stuffId];
    textTab.disabled = !stuffDataText?.[stuffId];

    // For PDF and image content types, the tab can render from JSON data via extractUrl()
    const contentType = stuffContentType?.[stuffId];
    const jsonData = stuffDataJson?.[stuffId];
    const canRenderFromJson = (contentType === 'application/pdf' || contentType?.startsWith('image/')) && extractUrl(jsonData);
    htmlTab.disabled = !stuffDataHtml?.[stuffId] && !canRenderFromJson;

    // Update HTML tab label based on content type
    if (contentType === 'application/pdf') {
        htmlTab.textContent = 'PDF';
    } else if (contentType?.startsWith('image/')) {
        htmlTab.textContent = 'Image';
    } else {
        htmlTab.textContent = 'HTML';
    }

    // Find first available format (HTML -> JSON -> Pretty)
    if (!htmlTab.disabled) return 'html';
    if (!jsonTab.disabled) return 'json';
    if (!textTab.disabled) return 'text';
    return 'html';
}

function showModal(stuffId) {
    currentStuffId = stuffId;
    const modal = document.getElementById('data-modal');
    const overlay = document.getElementById('modal-overlay');
    const title = document.getElementById('modal-title');

    // Build title from metadata (name + concept as primary, ID as secondary)
    const meta = stuffMetadata?.[stuffId];
    if (meta && (meta.name || meta.concept)) {
        const primaryParts = [];
        if (meta.name) primaryParts.push(escapeHtml(meta.name));
        if (meta.concept) primaryParts.push(`(${escapeHtml(meta.concept)})`);
        const primary = `<span class="data-modal-title-primary">${primaryParts.join(' ')}</span>`;
        const secondary = `<span class="data-modal-title-secondary">${escapeHtml(stuffId)}</span>`;
        title.innerHTML = primary + secondary;
    } else {
        title.innerHTML = `<span class="data-modal-title-primary">${escapeHtml(stuffId)}</span>`;
    }

    // Update tab availability and select best format
    const availableFormat = updateTabAvailability(stuffId);

    // If current format is not available, switch to available one
    const currentTab = document.getElementById(`tab-${currentFormat}`);
    if (currentTab.disabled) {
        setFormat(availableFormat);
    } else {
        renderContent(stuffId, currentFormat);
    }

    modal.style.display = 'block';
    overlay.style.display = 'block';
}

function hideModal() {
    document.getElementById('data-modal').style.display = 'none';
    document.getElementById('modal-overlay').style.display = 'none';
    currentStuffId = null;
}

// Get current content based on format
function getCurrentContent() {
    if (!currentStuffId) return null;

    if (currentFormat === 'json') {
        const data = stuffDataJson?.[currentStuffId];
        if (!data) return null;
        return { content: JSON.stringify(data, null, 2), ext: 'json', mime: 'application/json' };
    } else if (currentFormat === 'text') {
        const data = stuffDataText?.[currentStuffId];
        if (!data) return null;
        return { content: data, ext: 'txt', mime: 'text/plain' };
    } else if (currentFormat === 'html') {
        const data = stuffDataHtml?.[currentStuffId];
        if (!data) return null;
        return { content: data, ext: 'html', mime: 'text/html' };
    }
    return null;
}

// Copy content to clipboard
function copyContent() {
    const data = getCurrentContent();
    if (!data) return;

    navigator.clipboard.writeText(data.content).then(() => {
        const btn = document.getElementById('copy-btn');
        const checkIcon = '<svg viewBox="0 0 24 24">' +
            '<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>';
        const copyIcon = '<svg viewBox="0 0 24 24">' +
            '<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1z' +
            'm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2z' +
            'm0 16H8V7h11v14z"/></svg>';
        btn.innerHTML = checkIcon;
        btn.classList.add('copied');
        setTimeout(() => {
            btn.innerHTML = copyIcon;
            btn.classList.remove('copied');
        }, 1500);
    });
}

// Download content as file
function downloadContent() {
    if (!currentStuffId) return;

    // Get name from metadata or use ID
    const meta = stuffMetadata?.[currentStuffId];
    const baseName = meta?.name || currentStuffId || 'data';
    const contentType = stuffContentType?.[currentStuffId];
    const jsonData = stuffDataJson?.[currentStuffId];

    // For images, download the actual image file directly
    if (contentType?.startsWith('image/')) {
        const imageUrl = extractUrl(jsonData);
        if (imageUrl) {
            const ext = contentType.split('/')[1] || 'png';
            const filename = `${baseName.replace(/[^a-zA-Z0-9_-]/g, '_')}.${ext}`;
            const link = document.createElement('a');
            link.href = imageUrl;
            link.download = filename;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            return;
        }
    }

    // For PDFs, download the actual PDF file directly
    if (contentType === 'application/pdf') {
        const pdfUrl = extractUrl(jsonData);
        if (pdfUrl) {
            const filename = `${baseName.replace(/[^a-zA-Z0-9_-]/g, '_')}.pdf`;
            const link = document.createElement('a');
            link.href = pdfUrl;
            link.download = filename;
            link.target = '_blank';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            return;
        }
    }

    const data = getCurrentContent();
    if (!data) return;

    const filename = `${baseName.replace(/[^a-zA-Z0-9_-]/g, '_')}.${data.ext}`;
    const blob = new Blob([data.content], { type: data.mime });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
}

// Close modal when clicking overlay
document.getElementById('modal-overlay').addEventListener('click', hideModal);

// Close modal with Escape key
document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') hideModal();
});

// Open external URL for PDF content
function openExternal() {
    if (!currentStuffId) return;
    const contentType = stuffContentType?.[currentStuffId];
    const jsonData = stuffDataJson?.[currentStuffId];

    if (contentType === 'application/pdf') {
        const url = extractUrl(jsonData);
        if (url) {
            window.open(url, '_blank', 'noopener,noreferrer');
        }
    }
}

