// Global JavaScript functions for AstroManager

// Helper function to check if screen is mobile (returns boolean)
window.isMobileScreen = function() {
    return window.matchMedia('(max-width: 768px)').matches;
};

// Responsive layout resize listener
let resizeTimeout;
let dotNetRef;

window.setupResizeListener = function(dotNetReference) {
    dotNetRef = dotNetReference;
    
    // Add resize event listener with debouncing
    window.addEventListener('resize', function() {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(function() {
            if (dotNetRef) {
                dotNetRef.invokeMethodAsync('OnWindowResize');
            }
        }, 250); // 250ms debounce
    });
};

window.cleanupResizeListener = function() {
    if (resizeTimeout) {
        clearTimeout(resizeTimeout);
    }
    dotNetRef = null;
};

// Make sure the fileInterop module is loaded
window.initializeFileInterop = async () => {
    try {
        await import('./js/fileInterop.js');
        console.log('File interop module loaded');
        return true;
    } catch (error) {
        console.error('Failed to load file interop module:', error);
        return false;
    }
};

// Shared startup asset loader used to keep initial interactivity fast on mobile
window.astroAppAssets = (() => {
    const scriptPromises = new Map();
    let deferredAssetsPrefetched = false;
    const looksLikeAladinApi = (value) => !!value
        && typeof value.aladin === 'function'
        && typeof value.init?.then === 'function';

    function getPreferredAladinAsset() {
        return {
            id: '3.6.5',
            url: 'https://aladin.cds.unistra.fr/AladinLite/api/v3/3.6.5/aladin.js'
        };
    }

    function reportAssetError(assetName, error) {
        console.error(`[Assets] Failed to load ${assetName}`, error);
    }

    function loadScript(key, src, isReady) {
        if (typeof isReady === 'function' && isReady()) {
            return Promise.resolve(true);
        }

        if (scriptPromises.has(key)) {
            return scriptPromises.get(key);
        }

        const promise = new Promise((resolve, reject) => {
            const existing = document.querySelector(`script[data-am-asset="${key}"]`);
            if (existing) {
                existing.addEventListener('load', () => resolve(true), { once: true });
                existing.addEventListener('error', reject, { once: true });
                return;
            }

            const script = document.createElement('script');
            script.src = src;
            script.async = true;
            script.dataset.amAsset = key;
            script.onload = () => resolve(true);
            script.onerror = reject;
            document.head.appendChild(script);
        }).catch(error => {
            scriptPromises.delete(key);
            throw error;
        });

        scriptPromises.set(key, promise);
        return promise;
    }

    function removeAladinScripts(aladinAsset) {
        for (const selector of [
            `script[data-am-asset="aladin-lite-${aladinAsset.id}"]`,
            `script[src="${aladinAsset.url}"]`
        ]) {
            document.querySelectorAll(selector).forEach(script => script.remove());
        }
    }

    function resetAladinState(aladinAsset) {
        if (aladinAsset) {
            scriptPromises.delete(`aladin-lite-${aladinAsset.id}`);
            removeAladinScripts(aladinAsset);
        }

        try {
            delete window.__amAladinApi;
        } catch {
            window.__amAladinApi = undefined;
        }

        try {
            delete window.A;
        } catch {
            window.A = undefined;
        }

        window.__amAladinVersion = null;
    }

    function scheduleIdle(work) {
        const runner = () => {
            Promise.resolve()
                .then(work)
                .catch(error => reportAssetError('deferred startup assets', error));
        };

        if (typeof window.requestIdleCallback === 'function') {
            window.requestIdleCallback(runner, { timeout: 5000 });
            return;
        }

        window.setTimeout(runner, 1200);
    }

    async function ensureChartJsBundle() {
        if (typeof Chart !== 'undefined') {
            return true;
        }

        await loadScript(
            'chartjs-core',
            'https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js',
            () => typeof Chart !== 'undefined');

        await loadScript(
            'chartjs-date-adapter',
            'https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0/dist/chartjs-adapter-date-fns.bundle.min.js');

        await loadScript(
            'chartjs-annotation',
            'https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@3.0.1/dist/chartjs-plugin-annotation.min.js');

        return typeof Chart !== 'undefined';
    }

    async function ensureAladinReady(options = {}) {
        const aladinAsset = getPreferredAladinAsset();
        const trackedAladinApi = looksLikeAladinApi(window.__amAladinApi)
            ? window.__amAladinApi
            : window.A;
        const forceReload = options.forceReload === true;

        if (looksLikeAladinApi(trackedAladinApi)
            && window.__amAladinVersion === aladinAsset.id
            && !forceReload) {
            await trackedAladinApi.init;
            return true;
        }

        if (forceReload) {
            resetAladinState(aladinAsset);
        }

        await loadScript(
            `aladin-lite-${aladinAsset.id}`,
            aladinAsset.url,
            () => {
                const api = looksLikeAladinApi(window.__amAladinApi)
                    ? window.__amAladinApi
                    : window.A;
                return looksLikeAladinApi(api);
            });

        const api = looksLikeAladinApi(window.__amAladinApi)
            ? window.__amAladinApi
            : window.A;

        if (looksLikeAladinApi(api) && api.init && typeof api.init.then === 'function') {
            await api.init;
        }

        if (looksLikeAladinApi(api)) {
            if (!looksLikeAladinApi(window.__amAladinApi) && looksLikeAladinApi(window.A)) {
                window.__amAladinApi = window.A;
            }
            window.__amAladinVersion = aladinAsset.id;
            return true;
        }

        return false;
    }

    async function ensureCropperReady() {
        if (typeof window.Cropper !== 'undefined') {
            return true;
        }

        await loadScript(
            'cropper-blazor',
            '_content/Cropper.Blazor/cropper.min.js',
            () => typeof window.Cropper !== 'undefined');

        return typeof window.Cropper !== 'undefined';
    }

    function prefetchDeferredAssets() {
        if (deferredAssetsPrefetched) {
            return;
        }

        deferredAssetsPrefetched = true;
        scheduleIdle(async () => {
            const results = await Promise.allSettled([
                ensureChartJsBundle(),
                ensureCropperReady()
            ]);

            for (const result of results) {
                if (result.status === 'rejected') {
                    reportAssetError('deferred startup asset', result.reason);
                }
            }
        });
    }

    return {
        ensureChartJsBundle,
        ensureAladinReady,
        ensureCropperReady,
        prefetchDeferredAssets
    };
})();

// File download function
window.downloadFile = function(fileName, base64Data, mimeType) {
    mimeType = mimeType || 'application/octet-stream';
    const byteCharacters = atob(base64Data);
    const byteNumbers = new Array(byteCharacters.length);
    for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: mimeType });
    
    // Check if we're in a MAUI WebView (no standard download support)
    // In MAUI, window.chrome.webview exists but standard downloads don't work
    const isMauiWebView = typeof window.chrome !== 'undefined' && 
                          typeof window.chrome.webview !== 'undefined';
    
    if (isMauiWebView) {
        // For MAUI, use data URL and open in new window to trigger system handler
        // Or return the blob URL for .NET to handle
        console.log('[Download] MAUI WebView detected, using alternative download method');
        
        // Try to use the File System Access API if available
        if (window.showSaveFilePicker) {
            (async () => {
                try {
                    const handle = await window.showSaveFilePicker({
                        suggestedName: fileName,
                        types: [{
                            description: 'PDF Document',
                            accept: { 'application/pdf': ['.pdf'] }
                        }]
                    });
                    const writable = await handle.createWritable();
                    await writable.write(blob);
                    await writable.close();
                    console.log('[Download] File saved via File System Access API');
                } catch (err) {
                    console.error('[Download] File System Access API failed:', err);
                    // Fallback: open blob URL
                    const url = window.URL.createObjectURL(blob);
                    window.open(url, '_blank');
                    setTimeout(() => window.URL.revokeObjectURL(url), 60000);
                }
            })();
        } else {
            // Fallback: create a data URL and try to open it
            const url = window.URL.createObjectURL(blob);
            window.open(url, '_blank');
            setTimeout(() => window.URL.revokeObjectURL(url), 60000);
        }
        return;
    }
    
    // Standard browser download
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);
};

window.astroManager = window.astroManager || {};

window.astroManager.createObjectUrlFromBytes = function(bytes, contentType) {
    const blob = new Blob([bytes], { type: contentType || 'image/jpeg' });
    return window.URL.createObjectURL(blob);
};

window.astroManager.revokeObjectUrl = function(url) {
    if (typeof url === 'string' && url.startsWith('blob:')) {
        window.URL.revokeObjectURL(url);
    }
};

(function initializeHeaderFilterOutsideClose() {
    if (window.astroManager.headerFilterOutsideCloseInitialized) {
        return;
    }

    window.astroManager.headerFilterOutsideCloseInitialized = true;

    const closeOpenHeaderFilters = () => {
        document
            .querySelectorAll('details.image-library-header-filter[open]')
            .forEach((details) => details.removeAttribute('open'));
    };

    const isInsideInteractivePopup = (target) => {
        if (!(target instanceof Element)) {
            return false;
        }

        return Boolean(
            target.closest('.image-library-header-filter') ||
            target.closest('.image-library-header-dropdown.e-popup') ||
            target.closest('.image-library-filter-field__dropdown.e-popup') ||
            target.closest('.e-popup'));
    };

    document.addEventListener('pointerdown', (event) => {
        if (isInsideInteractivePopup(event.target)) {
            return;
        }

        closeOpenHeaderFilters();
    }, true);

    document.addEventListener('keydown', (event) => {
        if (event.key === 'Escape') {
            closeOpenHeaderFilters();
        }
    }, true);
})();

// Expose directory picker function to window
window.showDirectoryPicker = async () => {
    try {
        if (window.electron) {
            // In Electron environment
            return await window.electron.showDirectoryPicker();
        } else if (window.showDirectoryPicker) {
            // In modern browsers with the File System Access API
            const dirHandle = await window.showDirectoryPicker();
            return dirHandle.name;
        } else {
            // Fallback to input element
            return new Promise((resolve, reject) => {
                const input = document.createElement('input');
                input.type = 'file';
                input.webkitdirectory = true;
                input.multiple = false;
                
                input.onchange = (e) => {
                    const files = e.target.files;
                    if (files.length > 0) {
                        resolve(files[0].path || files[0].webkitRelativePath.split('/')[0]);
                    } else {
                        reject(new Error('No directory selected'));
                    }
                };
                
                input.oncancel = () => {
                    reject(new Error('Directory selection cancelled'));
                };
                
                input.click();
            });
        }
    } catch (error) {
        console.error('Error in showDirectoryPicker:', error);
        throw error;
    }
};

// Smooth scroll to element function
window.scrollToElement = function(elementId) {
    try {
        const element = document.getElementById(elementId);
        if (element) {
            element.scrollIntoView({
                behavior: 'smooth',
                block: 'start',
                inline: 'nearest'
            });
            return true;
        } else {
            console.warn(`Element with ID '${elementId}' not found`);
            return false;
        }
    } catch (error) {
        console.error('Error scrolling to element:', error);
        return false;
    }
};

window.scrollToElementAndHighlight = function(elementId, highlightClass) {
    try {
        const element = document.getElementById(elementId);
        if (!element) {
            console.warn(`Element with ID '${elementId}' not found`);
            return false;
        }

        element.scrollIntoView({
            behavior: 'smooth',
            block: 'start',
            inline: 'nearest'
        });

        if (highlightClass) {
            element.classList.add(highlightClass);
            window.setTimeout(() => element.classList.remove(highlightClass), 2400);
        }

        return true;
    } catch (error) {
        console.error('Error scrolling to highlighted element:', error);
        return false;
    }
};

// Smooth scroll to element with offset function
window.scrollToElementWithOffset = function(elementId, offset = 0) {
    try {
        const element = document.getElementById(elementId);
        if (element) {
            const elementPosition = element.offsetTop;
            const offsetPosition = elementPosition + offset;
            
            // Find the scrollable container (likely the filter content area)
            let scrollContainer = element.closest('.overflow-y-auto');
            if (!scrollContainer) {
                scrollContainer = window;
            }
            
            if (scrollContainer === window) {
                window.scrollTo({
                    top: offsetPosition,
                    behavior: 'smooth'
                });
            } else {
                scrollContainer.scrollTo({
                    top: offsetPosition,
                    behavior: 'smooth'
                });
            }
            return true;
        } else {
            console.warn(`Element with ID '${elementId}' not found`);
            return false;
        }
    } catch (error) {
        console.error('Error scrolling to element with offset:', error);
        return false;
    }
};

// Sticky filter functionality
let stickyFilterDotNetRef = null;
let stickyFilterScrollListener = null;
let stickyFilterThreshold = 200; // Pixels scrolled before filter becomes sticky

window.setupStickyFilterListener = function(dotNetReference) {
    stickyFilterDotNetRef = dotNetReference;
    
    // Remove existing listener if any
    if (stickyFilterScrollListener) {
        window.removeEventListener('scroll', stickyFilterScrollListener);
    }
    
    // Create throttled scroll listener for better performance
    let scrollTimeout;
    stickyFilterScrollListener = function() {
        if (scrollTimeout) {
            clearTimeout(scrollTimeout);
        }
        
        scrollTimeout = setTimeout(function() {
            const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
            const shouldBeSticky = scrollTop > stickyFilterThreshold;
            
            if (stickyFilterDotNetRef) {
                stickyFilterDotNetRef.invokeMethodAsync('OnScrollPositionChanged', shouldBeSticky);
            }
        }, 16); // ~60fps throttling
    };
    
    // Add scroll listener
    window.addEventListener('scroll', stickyFilterScrollListener, { passive: true });
    
    console.log('Sticky filter scroll listener setup complete');
};

window.cleanupStickyFilterListener = function() {
    if (stickyFilterScrollListener) {
        window.removeEventListener('scroll', stickyFilterScrollListener);
        stickyFilterScrollListener = null;
    }
    stickyFilterDotNetRef = null;
    console.log('Sticky filter scroll listener cleaned up');
};

window.__astroManagerShareState = window.__astroManagerShareState || { inProgress: false };

// Share content function with multiple fallback methods
window.shareContent = async function(shareData) {
    const shareState = window.__astroManagerShareState || (window.__astroManagerShareState = { inProgress: false });

    if (shareState.inProgress) {
        return { success: false, busy: true, cancelled: true };
    }

    shareState.inProgress = true;

    try {
        if (navigator.share) {
            try {
                const canShare = !navigator.canShare || navigator.canShare(shareData);
                if (canShare) {
                    await navigator.share(shareData);
                    return { success: true, method: 'native' };
                }
            } catch (error) {
                if (error?.name === 'AbortError') {
                    return { success: false, cancelled: true };
                }
            }
        }

        if (navigator.clipboard && navigator.clipboard.writeText) {
            try {
                await navigator.clipboard.writeText(shareData.url);
                return { success: true, method: 'clipboard' };
            } catch {
                // Continue to legacy/manual fallbacks when clipboard permissions are denied.
            }
        }

        const textArea = document.createElement('textarea');
        textArea.value = shareData.url;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        textArea.style.top = '-999999px';
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();

        try {
            const successful = document.execCommand('copy');
            document.body.removeChild(textArea);

            if (successful) {
                return { success: true, method: 'execCommand' };
            }
        } catch (err) {
            document.body.removeChild(textArea);
        }

        if (typeof window.prompt === 'function') {
            window.prompt('Copy this link:', shareData.url);
            return { success: true, method: 'prompt' };
        }

        return { success: false, error: 'Unable to share or copy link.' };
    } catch (error) {
        return { success: false, error: error?.message || 'Unable to share or copy link.' };
    } finally {
        shareState.inProgress = false;
    }
};

window.copyTextToClipboard = async function(text) {
    try {
        if (navigator.clipboard && navigator.clipboard.writeText) {
            try {
                await navigator.clipboard.writeText(text);
                return { success: true, method: 'clipboard' };
            } catch {
                // Continue to legacy/manual fallbacks when clipboard permissions are denied.
            }
        }

        const textArea = document.createElement('textarea');
        textArea.value = text;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        textArea.style.top = '-999999px';
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();

        try {
            const successful = document.execCommand('copy');
            document.body.removeChild(textArea);

            if (successful) {
                return { success: true, method: 'execCommand' };
            }
        } catch (err) {
            document.body.removeChild(textArea);
        }

        if (typeof window.prompt === 'function') {
            window.prompt('Copy this text:', text);
            return { success: false, method: 'prompt', error: 'Clipboard access was blocked. Please copy the text manually from the prompt.' };
        }

        return { success: false, error: 'Unable to copy link.' };
    } catch (error) {
        return { success: false, error: error?.message || 'Unable to copy link.' };
    }
};

window.getTextFromClipboard = async function() {
    try {
        if (navigator.clipboard && navigator.clipboard.readText) {
            return await navigator.clipboard.readText();
        }
    } catch {
        // Ignore permission and platform-specific clipboard read failures.
    }

    return null;
};

window.installClipboardWriteFallback = function() {
    try {
        const fallbackWriteText = async function(text) {
            const normalizedText = text == null ? '' : String(text);

            const textArea = document.createElement('textarea');
            textArea.value = normalizedText;
            textArea.setAttribute('readonly', 'readonly');
            textArea.style.position = 'fixed';
            textArea.style.opacity = '0';
            textArea.style.pointerEvents = 'none';
            textArea.style.left = '-999999px';
            textArea.style.top = '-999999px';
            document.body.appendChild(textArea);

            const selection = document.getSelection ? document.getSelection() : null;
            const originalRange = selection && selection.rangeCount > 0
                ? selection.getRangeAt(0)
                : null;
            const activeElement = document.activeElement;

            textArea.focus();
            textArea.select();
            textArea.setSelectionRange(0, normalizedText.length);

            try {
                const copied = document.execCommand && document.execCommand('copy');
                if (copied) {
                    return;
                }
            } finally {
                document.body.removeChild(textArea);

                if (selection) {
                    selection.removeAllRanges();
                    if (originalRange) {
                        selection.addRange(originalRange);
                    }
                }

                if (activeElement && typeof activeElement.focus === 'function') {
                    try {
                        activeElement.focus();
                    } catch {
                        // Ignore focus restoration issues.
                    }
                }
            }

            if (typeof window.prompt === 'function') {
                window.prompt('Copy this text:', normalizedText);
                return;
            }

            throw new Error('Clipboard write failed.');
        };

        const existingClipboard = navigator.clipboard || {};
        const originalWriteText = typeof existingClipboard.writeText === 'function'
            ? existingClipboard.writeText.bind(existingClipboard)
            : null;

        const wrappedWriteText = async function(text) {
            if (originalWriteText) {
                try {
                    await originalWriteText(text);
                    return;
                } catch {
                    // Fall back to textarea/prompt behavior below.
                }
            }

            await fallbackWriteText(text);
        };

        if (navigator.clipboard) {
            try {
                navigator.clipboard.writeText = wrappedWriteText;
            } catch {
                Object.defineProperty(navigator.clipboard, 'writeText', {
                    configurable: true,
                    value: wrappedWriteText
                });
            }
        } else {
            Object.defineProperty(navigator, 'clipboard', {
                configurable: true,
                value: {
                    writeText: wrappedWriteText
                }
            });
        }
    } catch (error) {
        console.warn('Clipboard fallback installation failed:', error);
    }
};

window.installClipboardWriteFallback();

window.getTextareaMentionContext = function (element, value) {
    if (!element) {
        return null;
    }

    const text = typeof value === 'string' ? value : (element.value || '');
    const caret = typeof element.selectionStart === 'number' ? element.selectionStart : text.length;
    const beforeCaret = text.slice(0, caret);
    const match = beforeCaret.match(/(^|\s)@([A-Za-z0-9._-]{0,64})$/);
    if (!match) {
        return null;
    }

    const query = match[2] || '';
    const replaceStart = caret - query.length - 1;
    return {
        query,
        replaceStart,
        replaceEnd: caret
    };
};

window.setTextareaCursorPosition = function (element, position) {
    if (!element || typeof element.focus !== 'function') {
        return false;
    }

    element.focus();
    if (typeof element.setSelectionRange === 'function') {
        element.setSelectionRange(position, position);
    }

    return true;
};

window.moveElementToBody = function (elementId, originalParentId) {
    if (!elementId) {
        return false;
    }

    const element = document.getElementById(elementId);
    if (!element) {
        return false;
    }

    const originalParent = (originalParentId && document.getElementById(originalParentId)) || element.parentElement;
    if (!originalParent) {
        return false;
    }

    if (!element.dataset.amOriginalParentId && originalParent.id) {
        element.dataset.amOriginalParentId = originalParent.id;
    }

    if (element.parentElement !== document.body) {
        document.body.appendChild(element);
    }

    return true;
};

window.__amDropdownMenuState = window.__amDropdownMenuState || new Map();

window.setupAmDropdownMenu = function (triggerElement, menuElement, align, offsetY) {
    if (!triggerElement || !menuElement) {
        return false;
    }

    const verticalGap = Number.isFinite(offsetY) ? offsetY : 8;
    const horizontalAlign = align === 'left' ? 'left' : 'right';

    const positionMenu = () => {
        if (!triggerElement.isConnected || !menuElement.isConnected) {
            return;
        }

        const triggerRect = triggerElement.getBoundingClientRect();

        menuElement.style.position = 'fixed';
        menuElement.style.top = '0px';
        menuElement.style.left = '0px';
        menuElement.style.right = 'auto';
        menuElement.style.bottom = 'auto';
        menuElement.style.maxWidth = 'min(24rem, calc(100vw - 1rem))';
        menuElement.style.maxHeight = 'calc(100vh - 1rem)';
        menuElement.style.overflowY = 'auto';

        const menuRect = menuElement.getBoundingClientRect();
        const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0;
        const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
        const margin = 8;

        let left = horizontalAlign === 'left'
            ? triggerRect.left
            : triggerRect.right - menuRect.width;

        left = Math.max(margin, Math.min(left, viewportWidth - menuRect.width - margin));

        let top = triggerRect.bottom + verticalGap;
        const maxTop = viewportHeight - menuRect.height - margin;
        if (top > maxTop) {
            top = Math.max(margin, triggerRect.top - menuRect.height - verticalGap);
        }

        if (top < margin) {
            top = margin;
        }

        menuElement.style.left = `${Math.round(left)}px`;
        menuElement.style.top = `${Math.round(top)}px`;
    };

    const requestPosition = () => window.requestAnimationFrame(positionMenu);
    const state = {
        requestPosition
    };

    window.__amDropdownMenuState.set(menuElement.id, state);

    window.addEventListener('resize', requestPosition, { passive: true });
    window.addEventListener('scroll', requestPosition, { passive: true, capture: true });

    requestPosition();
    return true;
};

window.restoreElementToParent = function (elementId, originalParentId) {
    if (!elementId) {
        return false;
    }

    const element = document.getElementById(elementId);
    if (!element) {
        return false;
    }

    const resolvedParentId = originalParentId || element.dataset.amOriginalParentId;
    if (!resolvedParentId) {
        return false;
    }

    const parent = document.getElementById(resolvedParentId);
    if (!parent) {
        return false;
    }

    if (element.parentElement !== parent) {
        parent.appendChild(element);
    }

    return true;
};

window.teardownAmDropdownMenu = function (elementId, originalParentId) {
    if (!elementId) {
        return false;
    }

    const state = window.__amDropdownMenuState && window.__amDropdownMenuState.get(elementId);
    if (state) {
        window.removeEventListener('resize', state.requestPosition, { passive: true });
        window.removeEventListener('scroll', state.requestPosition, { passive: true, capture: true });
        window.__amDropdownMenuState.delete(elementId);
    }

    return window.restoreElementToParent(elementId, originalParentId);
};

window.cropProfileImageToJpegBase64 = async function (dataUrl, zoom, offsetX, offsetY, previewSize, outputSize) {
    if (!dataUrl) {
        throw new Error('No image selected.');
    }

    const image = await new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = () => reject(new Error('Unable to load selected image.'));
        img.src = dataUrl;
    });

    const sourceWidth = image.naturalWidth || image.width;
    const sourceHeight = image.naturalHeight || image.height;
    if (!sourceWidth || !sourceHeight) {
        throw new Error('Selected image dimensions are invalid.');
    }

    const safeZoom = Math.max(1, Number(zoom) || 1);
    const targetSize = Math.max(64, Number(outputSize) || 512);
    const preview = Math.max(64, Number(previewSize) || targetSize);
    const previewToOutputScale = targetSize / preview;

    const coverScale = Math.max(targetSize / sourceWidth, targetSize / sourceHeight);
    const drawWidth = sourceWidth * coverScale * safeZoom;
    const drawHeight = sourceHeight * coverScale * safeZoom;

    const maxOffsetX = Math.max(0, (drawWidth - targetSize) / 2);
    const maxOffsetY = Math.max(0, (drawHeight - targetSize) / 2);
    const scaledOffsetX = (Number(offsetX) || 0) * previewToOutputScale;
    const scaledOffsetY = (Number(offsetY) || 0) * previewToOutputScale;
    const clampedOffsetX = Math.max(-maxOffsetX, Math.min(maxOffsetX, scaledOffsetX));
    const clampedOffsetY = Math.max(-maxOffsetY, Math.min(maxOffsetY, scaledOffsetY));

    const drawX = (targetSize - drawWidth) / 2 + clampedOffsetX;
    const drawY = (targetSize - drawHeight) / 2 + clampedOffsetY;

    const canvas = document.createElement('canvas');
    canvas.width = targetSize;
    canvas.height = targetSize;

    const context = canvas.getContext('2d');
    if (!context) {
        throw new Error('Canvas is not available in this browser.');
    }

    context.clearRect(0, 0, targetSize, targetSize);
    context.drawImage(image, drawX, drawY, drawWidth, drawHeight);

    const jpegDataUrl = canvas.toDataURL('image/jpeg', 0.9);
    const commaIndex = jpegDataUrl.indexOf(',');
    return commaIndex >= 0 ? jpegDataUrl.substring(commaIndex + 1) : jpegDataUrl;
};

window.syncCommunityTargetDetailImagingPlanHeight = function (leftColumn, imagingPlanPanel) {
    try {
        if (!leftColumn || !imagingPlanPanel) {
            return;
        }

        const isDesktop = window.matchMedia('(min-width: 1280px)').matches;
        if (!isDesktop) {
            imagingPlanPanel.style.height = '';
            return;
        }

        const leftHeight = leftColumn.getBoundingClientRect().height;
        if (!leftHeight || Number.isNaN(leftHeight)) {
            imagingPlanPanel.style.height = '';
            return;
        }

        imagingPlanPanel.style.height = `${Math.round(leftHeight)}px`;
    } catch (error) {
        console.error('Error syncing community target imaging plan height:', error);
    }
};
