const GITEA_INSTANCE = 'https://git.waifuboard.app';
const REPO_OWNER = 'ItsSkaiya';
const REPO_NAME = 'WaifuBoard-Extensions';
let DETECTED_BRANCH = 'main';
const API_URL_BASE = `${GITEA_INSTANCE}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/contents`;

const INSTALLED_EXTENSIONS_API = '/api/extensions';

const extensionsGrid = document.getElementById('extensions-grid');
const filterSelect = document.getElementById('extension-filter');

let allExtensionsData = [];

const customModal = document.getElementById('customModal');
const modalTitle = document.getElementById('modalTitle');
const modalMessage = document.getElementById('modalMessage');

function getRawUrl(filename) {

    const targetUrl = `${GITEA_INSTANCE}/${REPO_OWNER}/${REPO_NAME}/raw/branch/main/${filename}`;

    const encodedUrl = encodeURIComponent(targetUrl);

    return `/api/proxy?url=${encodedUrl}`;
}

function updateExtensionState(fileName, installed) {
    const ext = allExtensionsData.find(e => e.fileName === fileName);
    if (!ext) return;

    ext.isInstalled = installed;
    ext.isLocal = installed && ext.isLocal;

    filterAndRenderExtensions(filterSelect?.value || 'All');
}

function formatExtensionName(fileName) {
    return fileName.replace('.js', '')
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        .replace(/^[a-z]/, (char) => char.toUpperCase());
}

function getIconUrl(extensionDetails) {
    return extensionDetails;
}

async function getExtensionDetails(url) {
    try {
        const res = await fetch(url);
        if (!res.ok) throw new Error(`Fetch failed: ${res.status}`);
        const text = await res.text();

        const regex = /(?:this\.|const\s+|let\s+|var\s+)?baseUrl\s*=\s*(["'`])(.*?)\1/i;
        const match = text.match(regex);
        let finalHostname = null;
        if (match && match[2]) {
            let rawUrl = match[2].trim();
            if (!rawUrl.startsWith('http')) rawUrl = 'https://' + rawUrl;
            try {
                const urlObj = new URL(rawUrl);
                finalHostname = urlObj.hostname;
            } catch(e) {
                console.warn(`Could not parse baseUrl: ${rawUrl}`);
            }
        }

        const classMatch = text.match(/class\s+(\w+)/);
        const name = classMatch ? classMatch[1] : null;

        let type = 'Image';
        if (text.includes('type = "book-board"') || text.includes("type = 'book-board'")) type = 'Book';
        else if (text.includes('type = "anime-board"') || text.includes("type = 'anime-board'")) type = 'Anime';

        return { baseUrl: finalHostname, name, type };
    } catch (e) {
        return { baseUrl: null, name: null, type: 'Unknown' };
    }
}

function showCustomModal(title, message, isConfirm = false) {
    return new Promise(resolve => {

        modalTitle.textContent = title;
        modalMessage.textContent = message;

        const currentConfirmButton = document.getElementById('modalConfirmButton');
        const currentCloseButton = document.getElementById('modalCloseButton');

        const newConfirmButton = currentConfirmButton.cloneNode(true);
        currentConfirmButton.parentNode.replaceChild(newConfirmButton, currentConfirmButton);

        const newCloseButton = currentCloseButton.cloneNode(true);
        currentCloseButton.parentNode.replaceChild(newCloseButton, currentCloseButton);

        if (isConfirm) {

            newConfirmButton.classList.remove('hidden');
            newConfirmButton.textContent = 'Confirm';
            newCloseButton.textContent = 'Cancel';
        } else {

            newConfirmButton.classList.add('hidden');
            newCloseButton.textContent = 'Close';
        }

        const closeModal = (confirmed) => {
            customModal.classList.add('hidden');
            resolve(confirmed);
        };

        newConfirmButton.onclick = () => closeModal(true);
        newCloseButton.onclick = () => closeModal(false);

        customModal.classList.remove('hidden');
    });
}

function renderExtensionCard(extension, isInstalled, isLocalOnly = false) {

    const extensionName = formatExtensionName(extension.fileName || extension.name);
    const extensionType = extension.type || 'Unknown';

    let iconUrl;

    if (extension.baseUrl && extension.baseUrl !== 'Local Install') {

        iconUrl = `https://www.google.com/s2/favicons?domain=${extension.baseUrl}&sz=128`;
    } else {

        const displayName = extensionName.replace(/\s/g, '+');
        iconUrl = `https://ui-avatars.com/api/?name=${displayName}&background=1f2937&color=fff&length=1`;
    }

    const card = document.createElement('div');
    card.className = `extension-card grid-item extension-type-${extensionType.toLowerCase()}`;
    card.dataset.path = extension.fileName || extension.name;
    card.dataset.type = extensionType;

    let buttonHtml;
    let badgeHtml = '';

    if (isInstalled) {

        if (isLocalOnly) {
            badgeHtml = '<span class="extension-status-badge badge-local">Local</span>';
        } else {
            badgeHtml = '<span class="extension-status-badge badge-installed">Installed</span>';
        }
        buttonHtml = `
            <button class="extension-action-button btn-uninstall" data-action="uninstall">Uninstall</button>
        `;
    } else {

        buttonHtml = `
            <button class="extension-action-button btn-install" data-action="install">Install</button>
        `;
    }

    card.innerHTML = `
        <img class="extension-icon" src="${iconUrl}" alt="${extensionName} Icon" onerror="this.onerror=null; this.src='https://ui-avatars.com/api/?name=E&background=1f2937&color=fff&length=1'">
        <div class="card-content-wrapper">
            <h3 class="extension-name" title="${extensionName}">${extensionName}</h3>
            ${badgeHtml}
        </div>
        ${buttonHtml}
    `;

    const installButton = card.querySelector('[data-action="install"]');
    const uninstallButton = card.querySelector('[data-action="uninstall"]');

    if (installButton) {
        installButton.addEventListener('click', async () => {
            try {
                const response = await fetch('/api/extensions/install', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ fileName: extension.fileName }),
                });

                const result = await response.json();

                if (response.ok) {
                    updateExtensionState(extension.fileName, true);

                    await showCustomModal(
                        'Installation Successful',
                        `${extensionName} has been successfully installed.`,
                        false
                    );
                } else {

                    await showCustomModal(
                        'Installation Failed',
                        `Installation failed: ${result.error || 'Unknown error.'}`,
                        false
                    );
                }
            } catch (error) {

                await showCustomModal(
                    'Installation Failed',
                    `Network error during installation.`,
                    false
                );
            }
        });
    }

    if (uninstallButton) {
        uninstallButton.addEventListener('click', async () => {

            const confirmed = await showCustomModal(
                'Confirm Uninstallation',
                `Are you sure you want to uninstall ${extensionName}?`,
                true
            );

            if (!confirmed) return;

            try {
                const response = await fetch('/api/extensions/uninstall', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ fileName: extension.fileName }),
                });

                const result = await response.json();

                if (response.ok) {
                    updateExtensionState(extension.fileName, false);

                    await showCustomModal(
                        'Uninstallation Successful',
                        `${extensionName} has been successfully uninstalled.`,
                        false
                    );
                } else {

                    await showCustomModal(
                        'Uninstallation Failed',
                        `Uninstallation failed: ${result.error || 'Unknown error.'}`,
                        false
                    );
                }
            } catch (error) {

                await showCustomModal(
                    'Uninstallation Failed',
                    `Network error during uninstallation.`,
                    false
                );
            }
        });
    }

    extensionsGrid.appendChild(card);
}

async function getInstalledExtensions() {
    console.log(`Fetching installed extensions from: ${INSTALLED_EXTENSIONS_API}`);

    try {
        const response = await fetch(INSTALLED_EXTENSIONS_API);

        if (!response.ok) {
            console.error(`Error fetching installed extensions. Status: ${response.status}`);
            return new Set();
        }

        const data = await response.json();

        if (!data.extensions || !Array.isArray(data.extensions)) {
            console.error("Invalid response format from /api/extensions: 'extensions' array missing or incorrect.");
            return new Set();
        }

        const installedFileNames = data.extensions
            .map(name => `${name.toLowerCase()}.js`);

        return new Set(installedFileNames);

    } catch (error) {
        console.error('Network or JSON parsing error during fetch of installed extensions:', error);
        return new Set();
    }
}

function filterAndRenderExtensions(filterType) {
    extensionsGrid.innerHTML = '';

    if (!allExtensionsData || allExtensionsData.length === 0) {
        console.log('No extension data to filter.');
        return;
    }

    const filteredExtensions = allExtensionsData.filter(ext =>
        filterType === 'All' || ext.type === filterType || (ext.isLocal && filterType === 'Local')
    );

    filteredExtensions.forEach(ext => {
        renderExtensionCard(ext, ext.isInstalled, ext.isLocal);
    });

    if (filteredExtensions.length === 0) {
        extensionsGrid.innerHTML = `<p style="grid-column: 1 / -1; text-align: center; color: var(--text-secondary);">No extensions found for the selected filter (${filterType}).</p>`;
    }
}

async function loadMarketplace() {
    extensionsGrid.innerHTML = '';

    for (let i = 0; i < 6; i++) {
        extensionsGrid.innerHTML += `
            <div class="extension-card skeleton grid-item">
                <div class="skeleton-icon skeleton" style="width: 50px; height: 50px;"></div>
                <div class="card-content-wrapper">
                    <div class="skeleton-text title-skeleton skeleton" style="width: 80%; height: 1.1em;"></div>
                    <div class="skeleton-text text-skeleton skeleton" style="width: 50%; height: 0.7em; margin-top: 0.25rem;"></div>
                </div>
                <div class="skeleton-button skeleton" style="width: 100%; height: 32px; margin-top: 0.5rem;"></div>
            </div>`;
    }

    try {

        const [availableExtensionsRaw, installedExtensionsSet] = await Promise.all([
            fetch(API_URL_BASE).then(res => {
                if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
                return res.json();
            }),
            getInstalledExtensions()
        ]);

        const availableExtensionsJs = availableExtensionsRaw.filter(ext => ext.type === 'file' && ext.name.endsWith('.js'));
        const detailPromises = [];

        const marketplaceFileNames = new Set(availableExtensionsJs.map(ext => ext.name.toLowerCase()));

        for (const ext of availableExtensionsJs) {

            const downloadUrl = getRawUrl(ext.name);

            const detailsPromise = getExtensionDetails(downloadUrl).then(details => ({
                ...ext,
                ...details,
                fileName: ext.name,

                isInstalled: installedExtensionsSet.has(ext.name.toLowerCase()),
                isLocal: false,
            }));
            detailPromises.push(detailsPromise);
        }

        const extensionsWithDetails = await Promise.all(detailPromises);

        installedExtensionsSet.forEach(installedName => {

            if (!marketplaceFileNames.has(installedName)) {

                const localExt = {
                    name: formatExtensionName(installedName),
                    fileName: installedName,
                    type: 'Local',
                    isInstalled: true,
                    isLocal: true,
                    baseUrl: 'Local Install',
                };
                extensionsWithDetails.push(localExt);
            }
        });

        extensionsWithDetails.sort((a, b) => {
            if (a.isInstalled !== b.isInstalled) {
                return b.isInstalled - a.isInstalled;

            }

            const nameA = a.name || '';
            const nameB = b.name || '';

            return nameA.localeCompare(nameB);

        });

        allExtensionsData = extensionsWithDetails;

        if (filterSelect) {
            filterSelect.addEventListener('change', (event) => {
                filterAndRenderExtensions(event.target.value);
            });
        }

        filterAndRenderExtensions('All');

    } catch (error) {
        console.error('Error loading the marketplace:', error);
        extensionsGrid.innerHTML = `
            <div style="grid-column: 1 / -1; color: #dc2626; text-align: center; padding: 2rem; background: rgba(220,38,38,0.1); border-radius: 12px; margin-top: 1rem;">
                🚨 Error loading extensions.
                <p>Could not connect to the extension repository or local endpoint. Detail: ${error.message}</p>
            </div>
        `;
        allExtensionsData = [];
    }
}

customModal.addEventListener('click', (e) => {
    if (e.target === customModal || e.target.tagName === 'BUTTON') {
        customModal.classList.add('hidden');
    }
});

document.addEventListener('DOMContentLoaded', loadMarketplace);

window.addEventListener('scroll', () => {
    const navbar = document.getElementById('navbar');
    if (window.scrollY > 0) {
        navbar.classList.add('scrolled');
    } else {
        navbar.classList.remove('scrolled');
    }
});