// =====================
// FAVICON / ANIMATION HELPERS
// =====================

async function createSniperMark(id = 'sniper-mark') {
    const img = document.createElement('img');
    img.id = id;
    img.classList.add('sniper-mark');
    img.src = await chrome.runtime.getURL('libraries/target-spin/target.png');
    return img;
}

function spinAllSniperMarks() {
    document.querySelectorAll('.sniper-mark').forEach(el => el.classList.add('spin'));
}

function stopSpinAllSniperMarks() {
    document.querySelectorAll('.sniper-mark').forEach(el => el.classList.remove('spin'));
}

function flashAllSniperMarks() {
    document.querySelectorAll('.sniper-mark').forEach(el => el.classList.add('flash'));
}

function stopFlashAllSniperMarks() {
    document.querySelectorAll('.sniper-mark').forEach(el => el.classList.remove('flash'));
}

function spinElement(el) { el.classList.add('spin'); }
function stopSpinElement(el) { el.classList.remove('spin'); }
function flashElement(el) { el.classList.add('flash'); }
function stopFlashElement(el) { el.classList.remove('flash'); }

// Animated text fly-in effect (character by character)
function flyInText(text, element) {
    const chars = text.split('');
    element.innerHTML = '';

    const style = document.createElement('style');
    style.innerHTML = `
        @keyframes flyIn {
            from { transform: translateY(-100%); opacity: 0; }
            to   { transform: translateY(0%);   opacity: 1; }
        }
    `;
    document.head.appendChild(style);

    chars.forEach((char, index) => {
        const span = document.createElement('span');
        span.innerHTML = char;
        span.style.opacity = '0';
        span.style.animation = `flyIn 0.1s ease forwards ${index / 35}s`;
        element.appendChild(span);
    });
}

// =====================
// FAVICON ANIMATORS
// =====================

let faviconAnimating = false;

function setFavicon(url, type = 'image/x-icon') {
    const rel = (type === 'image/gif' || type === 'image/png') ? 'icon' : 'shortcut icon';
    if (type !== 'image/gif' && type !== 'image/png') faviconAnimating = false;
    const link = document.querySelector("link[rel*='icon']") || document.createElement('link');
    link.type = type;
    link.rel = rel;
    link.href = url;
    document.getElementsByTagName('head')[0].appendChild(link);
}

function replaceFavicon(url, type = 'image/x-icon') {
    const rel = (type === 'image/gif' || type === 'image/png') ? 'icon' : 'shortcut icon';
    const links = document.querySelectorAll("link[rel*='icon']");
    if (links.length === 0) {
        const link = document.createElement('link');
        link.type = type;
        link.rel = rel;
        link.href = url;
        document.getElementsByTagName('head')[0].appendChild(link);
        return;
    }
    links.forEach(link => {
        link.type = type;
        link.rel = rel;
        link.href = url;
    });
}

function animateGearFavicon() {
    faviconAnimating = true;
    let frame = 0;
    const interval = setInterval(() => {
        if (!faviconAnimating) { clearInterval(interval); return; }
        if (frame >= 28) frame = 0;
        const url = chrome.runtime.getURL(`Favicons/Gifs/Gear/frame_${frame}_delay-0.04s.gif`);
        setFavicon(url, 'image/gif');
        frame++;
    }, 40);
}

function animateTaskBarFavicon() {
    faviconAnimating = true;
    let frame = 0;
    const interval = setInterval(() => {
        if (!faviconAnimating) { clearInterval(interval); return; }
        if (frame >= 27) frame = 0;
        const url = chrome.runtime.getURL(`Favicons/Task_Bar/${frame}.png`);
        setFavicon(url, 'image/gif');
        frame++;
    }, 40);
}

function animateSniperFavicon() {
    faviconAnimating = true;
    let frame = 0;
    const longFrames = [2, 8, 14, 20, 26, 27];
    let delay = 40;

    const interval = setInterval(() => {
        if (!faviconAnimating) { clearInterval(interval); return; }
        const frameName = `frame_${String(frame).padStart(2, '0')}_delay-${longFrames.includes(frame) ? '0.05s' : '0.04s'}.gif`;
        setFavicon(chrome.runtime.getURL(`Favicons/Sniper/${frameName}`), 'image/gif');
        frame = ++frame >= 27 ? 0 : frame;
        delay = longFrames.includes(frame) ? 50 : 40;
    }, delay);
}

async function stopFaviconAnimation() {
    faviconAnimating = false;
    await new Promise(resolve => setTimeout(resolve, 2000));
}

// =====================
// NETWORK HELPERS
// =====================

async function fetchData(url, data) {
    return new Promise((resolve, reject) => {
        chrome.runtime.sendMessage({ type: 'fetchData', url, data }, response => {
            resolve(response.data);
        });
    });
}

async function fetchDataWithError(url, data) {
    return new Promise((resolve, reject) => {
        chrome.runtime.sendMessage({ type: 'fetchData', url, data }, response => {
            if (response.error) reject(response.error);
            else resolve(response.data);
        });
    });
}

async function fetchPrompt(path) {
    const url = chrome.runtime.getURL(path);
    const res = await fetch(url);
    return await res.text();
}

async function requestOpenAI(prompt, temperature = 0.7, model = 'text-davinci-003') {
    return new Promise(resolve => {
        chrome.runtime.sendMessage(
            { type: 'request-openAi', prompt, temperature, model },
            response => resolve(response.response)
        );
    });
}

// =====================
// CHROME STORAGE HELPERS
// =====================

function saveToStorage(key, value) {
    return new Promise(resolve => {
        chrome.storage.local.set({ [key]: value }, () => resolve());
    });
}

function getFromStorage(key) {
    return new Promise(resolve => {
        chrome.storage.local.get(key, result => resolve(result[key]));
    });
}

// =====================
// TABLE HELPERS
// =====================

function createTable() {
    const table = document.createElement('table');
    table.setAttribute('id', 'listing-data-table');
    table.setAttribute('class', 'styled-table');
    table.createTHead().insertRow(0);
    table.createTBody();
    return table;
}

function addTableHeader(table, { headerName }) {
    const cssClass = headerName.toLowerCase().replace(/ /g, '-');
    const row = table.querySelector('thead').getElementsByTagName('tr')[0];
    const th = document.createElement('th');
    th.innerHTML = headerName;
    th.setAttribute('class', `${cssClass}-header`);
    row.appendChild(th);
}

function getColumnIndex(headerName) {
    const cssClass = headerName.toLowerCase().replace(/ /g, '-');
    return document.querySelector(`.${cssClass}-header`).cellIndex;
}

function addTableRow(table) {
    const headers = table.querySelector('thead').getElementsByTagName('tr')[0].getElementsByTagName('th');
    const rows = table.querySelector('tbody').getElementsByTagName('tr');
    const newRow = table.querySelector('tbody').insertRow(rows.length);
    for (let i = 0; i < headers.length; i++) {
        newRow.insertCell(i).setAttribute(
            'class',
            `${headers[i].innerHTML.toLowerCase().replace(/ /g, '-')}-cell`
        );
    }
    return rows.length;
}

function setCellValue(table, { rowNumber, headerName, cellValue }) {
    const cssClass = headerName.toLowerCase().replace(/ /g, '-');
    table.querySelector(`tbody tr:nth-child(${rowNumber}) td.${cssClass}-cell`).innerHTML = cellValue;
}

function appendButtonToCell(table, { button, rowNumber, headerName }) {
    const cssClass = headerName.toLowerCase().replace(/ /g, '-');
    table.querySelector(`tbody tr:nth-child(${rowNumber}) td.${cssClass}-cell`).appendChild(button);
}

// =====================
// DOM WAIT HELPERS
// =====================

function waitUntilElementExists(selector, callback) {
    const el = document.querySelector(selector);
    if (el) return callback(el);
    setTimeout(() => waitUntilElementExists(selector, callback), 500);
}

async function waitForElement(selector, delay = 50, maxTries = 100) {
    const el = document.querySelector(selector);
    if (!window[`__${selector}`]) {
        window[`__${selector}`] = 0;
        window[`__${selector}__delay`] = delay;
        window[`__${selector}__tries`] = maxTries;
    }
    if (el === null) {
        if (window[`__${selector}`] >= maxTries) {
            window[`__${selector}`] = 0;
            return Promise.resolve(null);
        }
        return new Promise(resolve => {
            window[`__${selector}`]++;
            setTimeout(resolve, delay);
        }).then(() => waitForElement(selector));
    }
    return Promise.resolve(el);
}

// =====================
// SCRAPE HELPERS (site-specific)
// =====================

function scrapTitle() {
    return document.getElementById('rightContent').firstChild.innerText;
}

function scrapePrice() {
    const label = document.querySelector('._3cZnvUvE').getAttribute('aria-label');
    return parseFloat(label.match(/\d+\.\d+/)[0]);
}

function scrapeDescription() {
    const el = Array.from(document.body.querySelectorAll('*'))
        .find(el => el.innerText && el.innerText.trim() === 'Description');
    if (el) return el.parentNode.innerText;
    console.error('Could not find the desired element.');
    return null;
}

function scrapeImages() {
    const imgs = document.getElementById('leftContent')
        .querySelector('._2AOclWz7')
        .querySelectorAll('img[src]');
    return Array.from(imgs).map(img => img.src.split('?')[0]);
}

function scrapeUrl() {
    return window.location.href.split('?')[0];
}

// =====================
// PRICING
// =====================

async function calculateListingPrice(scrapedPrice) {
    const { markupPrice } = await chrome.storage.local.get('markupPrice');
    let price = scrapedPrice * (1 + markupPrice / 100);
    price = Math.ceil(price);

    const { end_price } = await chrome.storage.local.get('end_price');
    const endPriceFloat = parseFloat(end_price);
    const reduction = 1 - endPriceFloat;
    price -= (reduction === 1 ? 0 : reduction);
    return price;
}

// =====================
// UI BUILDERS
// =====================

function createPageTitle(title) {
    const h2 = document.createElement('h2');
    h2.id = 'title_silent_sniper';
    h2.textContent = title;
    return h2;
}

function createTitleEditor(title) {
    const container = document.createElement('div');
    container.id = 'listTitleContainer';

    const textarea = document.createElement('textarea');
    textarea.id = 'listTitle';
    textarea.rows = '1';
    textarea.cols = '50';
    textarea.placeholder = 'Input new title here...';
    textarea.textContent = title;

    const charCount = document.createElement('div');
    charCount.id = 'charCount';
    charCount.textContent = `Characters: ${textarea.value.length}/80`;
    textarea.addEventListener('input', () => {
        charCount.textContent = `Characters: ${textarea.value.length}/80`;
    });

    container.appendChild(textarea);
    container.appendChild(charCount);
    return container;
}

function createDescriptionBox(description) {
    const container = document.createElement('div');
    container.id = 'listDescriptionContainer';

    const h2 = document.createElement('h2');
    h2.textContent = 'Scraped Description';
    container.appendChild(h2);

    const p = document.createElement('p');
    p.id = 'listDescription';
    p.contentEditable = 'true';
    p.innerHTML = description;
    container.appendChild(p);

    return container;
}

function createImageContainers(imageUrls) {
    const fragment = document.createDocumentFragment();
    imageUrls.forEach(url => {
        const div = document.createElement('div');
        div.classList.add('imageContainer');

        const img = document.createElement('img');
        img.src = url;
        img.width = 100;
        img.height = 100;

        const deleteBtn = document.createElement('span');
        deleteBtn.textContent = 'x';
        deleteBtn.classList.add('deleteButton');
        deleteBtn.addEventListener('click', e => {
            e.stopPropagation();
            deleteBtn.parentNode.remove();
        });

        img.addEventListener('click', function () {
            document.querySelectorAll('.highlight').forEach(el => el.classList.remove('highlight'));
            this.classList.add('highlight');
        });
        img.addEventListener('dblclick', openImageModal);

        div.appendChild(img);
        div.appendChild(deleteBtn);
        fragment.appendChild(div);
    });
    return fragment;
}

function createPriceDisplay(price) {
    const h3 = document.createElement('h3');
    h3.textContent = `Scraped Price: $${price}`;
    return h3;
}

function createSkuDisplay(sku) {
    const h3 = document.createElement('h3');
    h3.id = 'listSku';
    h3.textContent = sku;
    return h3;
}

function createPriceInput(price) {
    const container = document.createElement('div');
    container.id = 'listPriceContainer';

    const label = document.createElement('label');
    label.htmlFor = 'newPrice';
    label.textContent = 'Price to be listed on eBay:';

    const input = document.createElement('input');
    input.id = 'listPrice';
    input.type = 'number';
    input.placeholder = 'Input new price here...';
    input.value = price;

    container.appendChild(label);
    container.appendChild(input);
    return container;
}

function createListOnEbayButton() {
    const btn = document.createElement('button');
    btn.id = 'listOnEbayButton';
    btn.textContent = 'List on eBay';
    btn.addEventListener('click', () => listOnEbay());
    return btn;
}

function createSnipeTitleButton() {
    const btn = document.createElement('button');
    btn.innerHTML = '<b>Snipe Title</b>';
    btn.id = 'create-title-v4';
    btn.classList.add('create-title-v4');

    btn.onclick = async () => {
        const title = document.querySelector('#listTitle').textContent;
        const description = document.querySelector('#listDescriptionContainer p').innerText;
        await generateAndDisplayTitles(title, description);
    };

    return btn;
}

// =====================
// IMAGE MODAL
// =====================

function openImageModal() {
    const modal = document.getElementById('myModal');
    const img = document.getElementById('img01');
    modal.style.display = 'block';
    img.src = this.src;
}

function closeImageModal() {
    document.getElementById('myModal').style.display = 'none';
}

function handleModalBackdropClick(event) {
    if (event.target === document.getElementById('myModal')) closeImageModal();
}

function createModal() {
    const modal = document.createElement('div');
    modal.id = 'myModal';
    modal.classList.add('modal');

    const closeBtn = document.createElement('span');
    closeBtn.classList.add('close');
    closeBtn.innerHTML = '&times;';
    modal.appendChild(closeBtn);

    const img = document.createElement('img');
    img.classList.add('modal-content');
    img.id = 'img01';
    modal.appendChild(img);

    document.body.appendChild(modal);
    document.getElementsByClassName('close')[0].addEventListener('click', closeImageModal);
    window.addEventListener('click', handleModalBackdropClick);
}

// =====================
// TITLE GENERATION
// =====================

async function generateAndDisplayTitles(title, description) {
    const btn = document.querySelector('#create-title-v4');
    btn.disabled = true;
    btn.style.backgroundColor = 'grey';
    btn.innerHTML = '<b>Sniping Title...</b>';

    stopFaviconAnimation();
    spinAllSniperMarks();
    title = title || getFilteredTitle();
    description = description || getProductDescriptionAndFeatures();

    const data = await fetchData('https://suggest-optimized-titles-2-djybcnnsgq-uc.a.run.app', {
        request_type: 'generate_10_titles',
        product_description: description,
        product_title: title,
    });

    let titles = data;
    if (!titles) {
        await addTitleToTable('Error - Try Again', 'Perfect Title');
        stopSpinAllSniperMarks();
        flashAllSniperMarks();
        await new Promise(r => setTimeout(r, 2000));
        stopFlashAllSniperMarks();
        btn.innerHTML = '<b>Sniped Title!</b>';
        btn.style.backgroundColor = '#3a86ff';
        setTimeout(() => { btn.innerHTML = '<b>Snipe Title</b>'; btn.disabled = false; }, 2000);
        return null;
    }

    if (!Array.isArray(titles)) titles = [titles];
    titles = titles.filter(t => t.trim().length > 0).map(t => t.trim());

    // Pick the longest title under 80 chars as the "best"
    let bestTitle = '';
    for (const t of titles) {
        if (t.length > bestTitle.length && t.length <= 80) bestTitle = t;
    }
    if (bestTitle.length === 0) bestTitle = titles[0];

    for (const t of titles) {
        if (t.length > 90) continue; // skip excessively long titles
        await addTitleToTable(t, bestTitle === t ? 'Perfect Title' : 'Great Title');
        const table = document.getElementById('listing-data-table');
        flyInText(t, table.rows[table.rows.length - 1].querySelector('.title-cell'));
        flashAllSniperMarks();
        await new Promise(r => setTimeout(r, 300));
        stopFlashAllSniperMarks();
    }

    // Set best title in textarea
    const textarea = document.querySelector('#the-textarea') || document.querySelector('#listTitle');
    textarea.value = bestTitle;
    try { updateTheCharacterCountOnTextArea(); } catch (e) { }

    stopSpinAllSniperMarks();
    flashAllSniperMarks();
    await new Promise(r => setTimeout(r, 2000));
    stopFlashAllSniperMarks();

    btn.innerHTML = '<b>Sniped Title!</b>';
    btn.style.backgroundColor = '#3a86ff';
    setTimeout(() => { btn.innerHTML = '<b>Snipe Title</b>'; btn.disabled = false; }, 2000);

    return bestTitle;
}

async function addTitleToTable(title, type) {
    const table = document.getElementById('listing-data-table');
    const rowNum = addTableRow(table);

    setCellValue(table, { rowNumber: rowNum, cellValue: rowNum, headerName: 'Rank' });
    setCellValue(table, { rowNumber: rowNum, cellValue: title, headerName: 'Title' });
    setCellValue(table, { rowNumber: rowNum, cellValue: type, headerName: 'Type' });
    setCellValue(table, { rowNumber: rowNum, cellValue: title.length, headerName: 'Total Characters' });

    const changeBtn = document.createElement('button');
    changeBtn.innerHTML = 'Change';
    changeBtn.onclick = () => {
        const textarea = document.querySelector('#listTitle');
        textarea.value = title;
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
    };
    appendButtonToCell(table, { button: changeBtn, rowNumber: rowNum, headerName: 'Action' });
}

// =====================
// EBAY LISTING
// =====================

function listOnEbay() {
    setFavicon(chrome.runtime.getURL('Favicons/Completed/right_arrow.png'));

    const imageEls = document.querySelectorAll('.imageContainer img');
    const imageUrls = Array.from(imageEls).map(img => img.src);
    const selectedImageUrl = document.querySelector('.imageContainer img.highlight').src;
    const selectedImage = await loadImageFromUrl(selectedImageUrl);

    const productData = {
        title: document.querySelector('#title_silent_sniper').innerText,
        custom_title: document.querySelector('#listTitle').value,
        custom_price: document.querySelector('#listPrice').value,
        descriptionHTML: document.querySelector('#listDescription').innerHTML,
        descriptionText: document.querySelector('#listDescription').innerText,
        main_hd_images: imageUrls,
        main_sd_images: [],
        selected_image: selectedImage.src,
        listingType: 'paid2',
        sku: document.querySelector('#listSku').innerText,
    };

    chrome.runtime.sendMessage(
        { type: 'list_to_ebay', product_data: productData },
        response => console.log(response.farewell)
    );
}

// =====================
// MAIN ENTRY POINT
// =====================

document.addEventListener('DOMContentLoaded', async () => {
    let attempts = 0;
    const interval = setInterval(async () => {
        const el = document.getElementById('rightContent');
        if (el || attempts > 20) {
            clearInterval(interval);
            if (el) await initPage();
            else console.error("Element 'rightContent' was not found after multiple attempts.");
        }
        attempts++;
    }, 500);
});

async function initPage() {
    const title = scrapTitle();
    const price = scrapePrice();
    const description = scrapeDescription();
    const images = scrapeImages();
    const sku = scrapeUrl();
    const listPrice = await calculateListingPrice(price);

    buildUI({ title, description, images, price: listPrice, sku });
}

function buildUI({ images, title, price, description, sku }) {
    const snipeTitleBtn = createSnipeTitleButton();
    const sniperMark = createSniperMark();
    createModal();

    const wrapper = document.createElement('div');
    wrapper.id = 'data-box';

    // Images section
    const imagesContainer = document.createElement('div');
    imagesContainer.id = 'imagesContainer';
    imagesContainer.appendChild(createImageContainers(images));
    wrapper.appendChild(imagesContainer);

    // Buttons
    const buttonContainer = document.createElement('div');
    buttonContainer.id = 'buttonContainer';

    const quadBtn = document.createElement('button');
    quadBtn.innerHTML = 'Generate Quad Image';
    quadBtn.id = 'generateQuadImageButton';
    quadBtn.onclick = async e => {
        e.preventDefault();
        quadBtn.disabled = true;
        quadBtn.style.backgroundColor = 'grey';
        await generateQuadImage();
        quadBtn.disabled = false;
        quadBtn.style.backgroundColor = '#4CAF50';
    };

    const multiBtn = document.createElement('button');
    multiBtn.innerHTML = 'Create Multi Image';
    multiBtn.id = 'createMultiImageButton';
    multiBtn.onclick = async e => {
        e.preventDefault();
        multiBtn.disabled = true;
        multiBtn.style.backgroundColor = 'grey';
        await createMultiImage();
        multiBtn.disabled = false;
        multiBtn.style.backgroundColor = '#4CAF50';
    };

    buttonContainer.appendChild(sniperMark.cloneNode(true));
    buttonContainer.appendChild(quadBtn);
    buttonContainer.appendChild(multiBtn);
    wrapper.appendChild(buttonContainer);

    // Text/price fields
    wrapper.appendChild(createPageTitle(title));
    wrapper.appendChild(createTitleEditor(title));
    wrapper.appendChild(createPriceInput(price));
    wrapper.appendChild(sniperMark);
    wrapper.appendChild(snipeTitleBtn);
    wrapper.appendChild(createListOnEbayButton());

    // Title table
    const table = createTable();
    wrapper.appendChild(table);
    addTableHeader(table, { headerName: 'Rank' });
    addTableHeader(table, { headerName: 'Type' });
    addTableHeader(table, { headerName: 'Title' });
    addTableHeader(table, { headerName: 'Total Characters' });
    addTableHeader(table, { headerName: 'Action' });

    const rowNum = addTableRow(table);
    setCellValue(table, { rowNumber: rowNum, cellValue: rowNum, headerName: 'Rank' });
    setCellValue(table, { rowNumber: rowNum, cellValue: title, headerName: 'Title' });
    setCellValue(table, { rowNumber: rowNum, cellValue: 'Filtered', headerName: 'Type' });
    setCellValue(table, { rowNumber: rowNum, cellValue: title.length, headerName: 'Total Characters' });

    const changeBtn = document.createElement('button');
    changeBtn.innerHTML = 'Change';
    changeBtn.onclick = () => {
        const ta = document.querySelector('#listTitle');
        ta.value = title;
        ta.dispatchEvent(new Event('input', { bubbles: true }));
    };
    appendButtonToCell(table, { button: changeBtn, rowNumber: rowNum, headerName: 'Action' });

    wrapper.appendChild(createDescriptionBox(description));
    wrapper.appendChild(createPriceDisplay(price));
    wrapper.appendChild(createSkuDisplay(sku));

    // Close button
    const closeBtn = document.createElement('span');
    closeBtn.innerHTML = '&times;';
    closeBtn.classList.add('close-button');
    closeBtn.onclick = () => wrapper.remove();
    wrapper.appendChild(closeBtn);

    document.body.insertBefore(wrapper, document.body.firstChild);

    // Highlight first image by default
    document.querySelector('.imageContainer').querySelector('img').click();

    // Enable drag-to-reorder images
    new Sortable(imagesContainer, {
        animation: 150,
        chosenClass: 'sortable-chosen',
        dragClass: 'sortable-drag',
    });
}



