// --- SKU List Utilities ---

/**
 * Decodes a base64-encoded string. Returns null if decoding fails.
 */
function decodeBase64(encodedStr) {
    try {
        return atob(encodedStr);
    } catch (e) {
        return null;
    }
}

/**
 * Retrieves the SKU list from Chrome local storage,
 * decodes each base64-encoded entry, and returns the decoded list.
 */
async function getDecodedSkuList() {
    return new Promise((resolve, reject) => {
        chrome.storage.local.get('skuList', async (result) => {
            const encodedList = result.skuList || [];
            const decodedList = [];
            for (let i = 0; i < encodedList.length; i++) {
                const decoded = await decodeBase64(encodedList[i]);
                if (decoded) decodedList.push(decoded);
            }
            resolve(decodedList);
        });
    });
}

/**
 * Checks whether a given SKU already exists in the stored SKU list.
 */
async function isSkuListed(sku) {
    const listedItems = await getDecodedSkuList();
    console.log('listedItems', listedItems);
    return listedItems.indexOf(sku) > -1;
}

/**
 * Adds a SKU (base64-encoded) to the stored SKU list.
 * Rejects if the SKU already exists.
 */
function addSkuToList(sku) {
    return new Promise((resolve, reject) => {
        const encodedSku = btoa(sku);
        chrome.storage.local.get('skuList', (result) => {
            let skuList = result.skuList || [];
            if (skuList.some(entry => entry === encodedSku)) {
                reject('SKU already exists in list');
            } else {
                skuList.push(encodedSku);
                chrome.storage.local.set({ skuList }, () => {
                    resolve();
                });
            }
        });
    });
}

/**
 * Logs the current SKU list to the console for debugging.
 */
function logSkuList() {
    chrome.storage.local.get('skuList', (result) => {
        console.log('skulist check: ', result.skuList);
    });
}

/**
 * (Legacy/unused) Checks if a SKU exists in a list using .SKU property.
 * Note: This function has a bug — it doesn't return its result properly.
 */
function checkSkuInLegacyList(sku) {
    chrome.storage.local.get('skuList', (result) => {
        const decodedList = [];
        const skuList = result.skuList;
        for (let i = 0; i < skuList.length; i++) {
            decodedList.push(atob(skuList[i].SKU));
        }
        return decodedList.indexOf(sku) > -1;
    });
}

// --- URL / ASIN Utilities ---

/**
 * Extracts a 10-character Amazon ASIN from the current page URL.
 * Returns null if no ASIN is found.
 */
function getAsinFromCurrentUrl() {
    const url = window.location.href;
    const asinRegex = /(?:\/)([A-Z0-9]{10})(?:$|\/|\?)/;
    const match = url.match(asinRegex);
    return match == null ? null : match[1];
}

/**
 * Extracts a 10-character Amazon ASIN from a given URL string.
 * Returns null if no ASIN is found.
 */
function getAsinFromUrl(url) {
    const asinRegex = /(?:\/)([A-Z0-9]{10})(?:$|\/|\?)/;
    const match = url.match(asinRegex);
    return match == null ? null : match[1];
}

// --- Chrome Storage Helpers ---

/**
 * Saves a key-value pair to Chrome local storage.
 * Logs before and after for debugging.
 */
function saveToLocalStorage(key, value) {
    console.log('test save to local storage');
    console.log('key ' + key + ', value ' + value);
    return new Promise((resolve, reject) => {
        chrome.storage.local.set({ [key]: value }, function () {
            console.log('my key', key);
            chrome.storage.local.get(key, function (result) {
                console.log('the Value currently is ', result[key]);
                resolve();
            });
        });
    });
}

/**
 * Retrieves a value from Chrome local storage by key.
 */
function getFromLocalStorage(key) {
    return new Promise((resolve, reject) => {
        chrome.storage.local.get(key, function (result) {
            console.log('Value currently is ', result[key]);
            resolve(result[key]);
        });
    });
}

// --- CSV Parser ---

/**
 * Parses a CSV string into a 2D array.
 * Supports custom delimiters (default: comma).
 */
function parseCsv(csvString, delimiter) {
    delimiter = delimiter || ',';
    const regex = new RegExp(
        '(\\' + delimiter + '|\\r?\\n|\\r|^)(?:"([^"]*(?:""[^"]*)*)"|([^"\\' + delimiter + '\\r\\n]*))',
        'gi'
    );
    const rows = [[]];
    let match;
    while ((match = regex.exec(csvString))) {
        const separator = match[1];
        if (separator.length && separator !== delimiter) rows.push([]);
        const value = match[2]
            ? match[2].replace(new RegExp('""', 'g'), '"')
            : match[3];
        rows[rows.length - 1].push(value);
    }
    return rows;
}

console.log('chat_gpt_web.js loaded');

// --- File / Prompt Loader ---

/**
 * Fetches a text file bundled with the Chrome extension by its relative path.
 */
async function loadExtensionFile(filePath) {
    const fileURL = chrome.runtime.getURL(filePath);
    const response = await fetch(fileURL);
    return await response.text();
}

// --- ChatGPT Messaging ---

/**
 * Sends a prompt to the background ChatGPT handler.
 * Retries automatically after 5 minutes if no response is received.
 */
async function askChatGptWeb(prompt, options = { startNewChat: false }) {
    let timeoutId;
    return new Promise((resolve, reject) => {
        timeoutId = setTimeout(() => {
            console.log('No response received in 5 minutes, retrying...');
            resolve(askChatGptWeb(prompt, options));
        }, 300000); // 5 minutes

        chrome.runtime.sendMessage(
            { type: 'ask_chat_gpt_web', prompt, options },
            function (result) {
                clearTimeout(timeoutId);
                console.log('result: ', result);
                try {
                    resolve(result.response);
                } catch (e) {
                    resolve(askChatGptWeb(prompt, options));
                }
            }
        );
    });
}

// --- Title Generation ---

/**
 * Uses ChatGPT to generate high-quality eBay listing titles
 * from a product title and description using a V4 prompt template.
 */
async function askChatGptForHighQualityTitles(title, description, options = { startNewChat: false }) {
    console.log('askChatGptForHighQualityTitles: ', title, description, options);
    let prompt = await loadExtensionFile('text_prompts/TitlePrompts/V4.txt');
    prompt = prompt.replace('{{Title}}', title).replace('{{Description}}', description);

    const response = await askChatGptWeb(prompt, options);

    if (!response || response.length === 0 || response === 'undefined' || response == null || response === 'null') {
        return await askChatGptForHighQualityTitles(title, description, { startNewChat: true });
    }

    try {
        const parts = response.split(/Title Versions.*:|Title Variations.*:/i);
        if (parts.length < 2) {
            return await askChatGptForHighQualityTitles(title, description, { startNewChat: true });
        }
        let titles = parts[1].split('\n');
        titles = titles
            .filter(line => line.startsWith('"') && line.endsWith('"'))
            .map(line => line.replace(/^"|"$/g, ''));
        console.log('titles: ', titles);
        return titles;
    } catch (e) {
        console.log('Error in askChatGptForHighQualityTitles: ', e);
        return await askChatGptForHighQualityTitles(title, description, { startNewChat: true });
    }
}

/**
 * Adjusts a title to be between 73 and 80 characters by
 * shortening or lengthening it as needed.
 */
async function adjustTitleLength(title, originalTitle, description) {
    while (title.length > 80 || title.length < 73) {
        if (title.length > 80) title = await shortenTitle(title, originalTitle, description);
        if (title.length < 73) title = await lengthenTitle(title, originalTitle, description);
    }
    return title;
}

/**
 * Uses ChatGPT to lengthen a title that is too short.
 */
async function lengthenTitle(titleToLengthen, originalTitle, description) {
    let prompt = await loadExtensionFile('text_prompts/TitlePrompts/LengthenTitle/V2.txt');
    prompt = prompt
        .replace('{{TitleToLengthen}}', titleToLengthen)
        .replace('{{Title}}', originalTitle)
        .replace('{{Description}}', description);
    const response = (await askChatGptWeb(prompt)).split('Enhanced Title:')[1].trim();
    return response.replace(/^"(.*)"$/, '$1');
}

/**
 * Uses ChatGPT to shorten a title that is too long.
 */
async function shortenTitle(titleToShorten, originalTitle, description) {
    let prompt = await loadExtensionFile('text_prompts/TitlePrompts/ShortenTitle/V1.txt');
    prompt = prompt
        .replace('{{TitleToShorten}}', titleToShorten)
        .replace('{{Title}}', originalTitle)
        .replace('{{Description}}', description);
    const response = await askChatGptWeb(prompt);
    if (!response.includes('Shortened Title:')) return await shortenTitle(titleToShorten, originalTitle, description);
    const shortened = response.split('Shortened Title:')[1].trim();
    return shortened.replace(/^"(.*)"$/, '$1');
}

/**
 * Generates titles using a V1 prompt template (older version).
 */
async function generateTitlesV1(title, description) {
    let prompt = await loadExtensionFile('text_prompts/TitlePrompts/V1.txt');
    prompt = prompt.replace('{{Title}}', title).replace('{{Description}}', description);
    const response = await askChatGptWeb(prompt);
    const parsedTitles = await parseTitlesFromResponse(response);
    console.log('parsedTitles: ', parsedTitles);
    return parsedTitles;
}

/**
 * Generates a product type / popular search query using ChatGPT.
 */
async function getProductTypeFromTitle(title, options = { startNewChat: false }) {
    let prompt = await loadExtensionFile('text_prompts/ProductTypePrompts/V1.txt');
    prompt = prompt.replace('{{Title}}', title);
    let response = await askChatGptWeb(prompt, options);

    const match = /popular search query:/i.exec(response);
    if (match) {
        response = response.substring(match.index + match[0].length).trim();
    }

    if (response.split(' ').length > 9) {
        return await getProductTypeFromTitle(title, { startNewChat: true });
    }
    response = response.split('\n')[0];
    return response.replace(/^"(.*)"$/, '$1');
}

/**
 * Identifies a colloquial/popular search query for a product using ChatGPT.
 */
async function getPopularSearchQuery(title, options = { startNewChat: false }) {
    let prompt = await loadExtensionFile('text_prompts/Identify_Popular_Search_Query_Prompts/V2.txt');
    prompt = prompt.replace('{{Title}}', title);
    let response = await askChatGptWeb(prompt, options);

    const match = /colloquial search term:/i.exec(response);
    if (match) {
        response = response.substring(match.index + match[0].length).trim();
    }

    if (response.split(' ').length > 9) {
        return await getPopularSearchQuery(title, { startNewChat: true });
    }
    response = response.split('\n')[0];
    return response.replace(/^"(.*)"$/, '$1');
}

/**
 * Gets the main benefit / banner words for a product listing using ChatGPT.
 */
async function getMainBenefit(title, description, options = { startNewChat: false }) {
    let prompt = await loadExtensionFile('text_prompts/MainBenefitPrompts/V1.txt');
    prompt = prompt.replace('{{Title}}', title).replace('{{Description}}', description);
    const response = await askChatGptWeb(prompt, options);

    if (response.split('\n').length === 1 && response.startsWith('"')) {
        return response.replace(/^"(.*)"$/, '$1');
    }
    if (!response.includes('Banner Words:')) {
        return await getMainBenefit(title, description, { startNewChat: true });
    }
    const bannerWords = response.split('Banner Words:')[1].trim();
    return bannerWords.replace(/^"(.*)"$/, '$1');
}

/**
 * Generates an HTML product description using ChatGPT.
 * Retries if the response doesn't contain expected HTML tags.
 */
async function generateDescription(title, description) {
    let prompt = await loadExtensionFile('text_prompts/DescriptionPrompts/V1.txt');
    prompt = prompt.replace('{{Title}}', title).replace('{{Description}}', description);
    let response = await askChatGptWeb(prompt, { startNewChat: true });

    if (!response.includes('<h2>')) return await generateDescription(title, description);

    if (/html\s*copy\s*code/i.test(response)) {
        const parts = response.split(/html\s*copy\s*code/i);
        response = parts[1].trim();
    }

    const trimMatch = response.match(/[\s\S]*<\/p>/);
    if (trimMatch) response = trimMatch[0];
    return response;
}

/**
 * Parses "Optimized Title #N: ..." lines from a ChatGPT response.
 */
async function parseTitlesFromResponse(responseText) {
    return new Promise(resolve => {
        const titles = [];
        const lines = responseText.trim().split('\n');
        if (lines[0] && !lines[0].startsWith('Optimized Title #')) {
            titles.push(lines[0].trim());
        }
        const titleRegex = /^(Optimized Title #[0-9]+:)\s*(.*)$/gm;
        let match;
        while ((match = titleRegex.exec(responseText)) !== null) {
            titles.push(match[2].trim());
        }
        resolve(titles);
    });
}

/**
 * Extracts a JSON "values" array from a response string.
 * Returns null if not found or invalid.
 */
function extractValuesFromJson(responseText) {
    try {
        const jsonMatch = responseText.match(/{[^}]+}/);
        if (!jsonMatch) return null;
        const parsed = JSON.parse(jsonMatch[0]);
        return parsed.hasOwnProperty('values') && parsed.values.length > 0 ? parsed.values : null;
    } catch (e) {
        return null;
    }
}

/**
 * Extracts a JSON object from a response string.
 * Returns null if not found or invalid.
 */
function extractJsonObject(responseText) {
    try {
        const jsonMatch = responseText.match(/{[^}]+}/);
        return jsonMatch ? JSON.parse(jsonMatch[0]) : null;
    } catch (e) {
        return null;
    }
}

/**
 * Generates SEO-optimized eBay listing titles using ChatGPT
 * with a V2 SEO prompt, incorporating keywords and product type.
 */
async function generateSeoTitles(productType, title, description, keywords, options = { startNewChat: true }) {
    let prompt = await loadExtensionFile('text_prompts/SEO_Title_Prompt/V2.txt');
    prompt = prompt
        .replace('{{Title}}', title)
        .replace('{{Description}}', description)
        .replace('{{Keywords}}', keywords.join(', '))
        .replace('{{ProductType}}', productType);

    const response = await askChatGptWeb(prompt, options);

    if (!response || response.length === 0 || response === 'undefined' || response == null || response === 'null') {
        return await generateSeoTitles(title, description, keywords, { startNewChat: true });
    }

    try {
        const parts = response.split(/Title Versions.*:|Title Variations.*:/i);
        let titlesSection;

        if (parts.length === 1 && parts[0].startsWith('"')) {
            titlesSection = parts[0];
        } else {
            if (parts.length < 2) return await generateSeoTitles(title, description, keywords, { startNewChat: true });
            if (parts.length > 1) titlesSection = parts[1];
        }

        let titles = titlesSection.split('\n');
        titles = titles
            .filter(line => line.startsWith('"') && line.endsWith('"'))
            .map(line => line.replace(/^"|"$/g, ''));
        console.log('titles: ', titles);
        return titles;
    } catch (e) {
        console.log('Error in askChatGptToCreateSEOTitles: ', e);
        return await generateSeoTitles(title, description, keywords, { startNewChat: true });
    }
}

// ============================================================
// --- UI / Popup Logic ---
// ============================================================


const statusText = document.getElementById('status_text');
const emailText = document.getElementById('email_text');
const userFeaturesContainer = document.getElementById('user_features_containers');





/**
 * Saves a UUID to Chrome local storage.
 */
function saveUuid(uuid) {
    chrome.storage.local.set({ uuid }, () => {
        console.log('UUID stored in local storage');
    });
}

/**
 * Removes the UUID from Chrome local storage.
 */
function clearUuid() {
    chrome.storage.local.remove('uuid', () => {
        console.log('UUID cleared from local storage');
    });
}

window.onload = function () {
    loadMarkupPrice();
};

// Start button — sends a 'start' message with the page number
document.getElementById('main_button').addEventListener('click', async function (e) {
    e.preventDefault();
    const pageNumber = document.getElementById('page_number').value;
    await saveToLocalStorage('page_number', pageNumber);
    chrome.runtime.sendMessage({ type: 'start', page_number: pageNumber });
});

// --- Markup Price ---
const markupPriceInput = document.getElementById('markup-price');
markupPriceInput.addEventListener('change', function () {
    const value = markupPriceInput.value;
    chrome.storage.local.set({ markupPrice: value });
});

function loadMarkupPrice() {
    chrome.storage.local.get('markupPrice', (result) => {
        const markupPrice = result.markupPrice;
        if (markupPrice !== undefined) {
            document.getElementById('markup-price').value = markupPrice;
        }
    });
}

// --- Sniper Price Markdown ---
document.getElementById('sniper-price-markdown').addEventListener('change', async function (e) {
    e.preventDefault();
    const value = document.getElementById('sniper-price-markdown').value;
    await saveToLocalStorage('sniper_price_markdown', value);
    const stored = await getFromLocalStorage('sniper_price_markdown');
    document.getElementById('sniper-price-markdown').value = stored;
});

chrome.storage.local.get(['sniper_price_markdown'], (result) => {
    let value = result && result.sniper_price_markdown !== undefined ? result.sniper_price_markdown : 0.05;
    if (result === undefined || result.sniper_price_markdown === undefined) {
        chrome.storage.local.set({ sniper_price_markdown: value });
    }
    const el = document.getElementById('sniper-price-markdown');
    if (el) el.value = value;
});

// --- Promoted Listing Ad Rate ---
document.getElementById('promoted_listing_ad_rate').addEventListener('change', async function (e) {
    e.preventDefault();
    const value = document.getElementById('promoted_listing_ad_rate').value;
    await saveToLocalStorage('promoted_listing_ad_rate', value);
    const stored = await getFromLocalStorage('promoted_listing_ad_rate');
    document.getElementById('promoted_listing_ad_rate').value = stored;
});

chrome.storage.local.get(['promoted_listing_ad_rate'], (result) => {
    const value = result && result.promoted_listing_ad_rate !== undefined ? result.promoted_listing_ad_rate : 5;
    if (result === undefined || result.promoted_listing_ad_rate === undefined) {
        chrome.storage.local.set({ promoted_listing_ad_rate: value });
    }
    const el = document.getElementById('promoted_listing_ad_rate');
    if (el) el.value = value;
});

// --- End Price ---
document.getElementById('end-price').addEventListener('change', async function (e) {
    e.preventDefault();
    const value = document.getElementById('end-price').value;
    await chrome.storage.local.set({ end_price: value });
});

chrome.storage.local.get('end_price', (result) => {
    const endPrice = result.end_price;
    if (endPrice) {
        document.getElementById('end-price').value = endPrice;
    } else {
        document.getElementById('end-price').value = 0.99;
        chrome.storage.local.set({ end_price: 0.99 });
    }
});

// --- Save SKU on Page ---
document.getElementById('save_sku_on_page').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.runtime.sendMessage({ type: 'save_sku_on_page' });
});

chrome.storage.local.get('skuList', (result) => {
    const skuList = result.skuList;
    if (skuList) {
        console.log('skuList', skuList.length);
        document.getElementById('skuFound').innerHTML = skuList.length;
    } else {
        document.getElementById('skuFound').innerHTML = 'No Skus Found, start scraping';
    }
});

// --- Watermark URL ---
document.getElementById('save_image_to_local_storage').addEventListener('click', async function (e) {
    e.preventDefault();
    const url = document.getElementById('watermark_url').value;
    await saveToLocalStorage('watermark_url', url);
    const stored = await getFromLocalStorage('watermark_url');
    document.getElementById('image_from_local_storage').src = stored;
});

// --- API Key ---
document.getElementById('save_api_key').addEventListener('click', async function (e) {
    e.preventDefault();
    const apiKey = document.getElementById('api_key').value;
    await saveToLocalStorage('api_key', apiKey);
    const stored = await getFromLocalStorage('api_key');
    document.getElementById('api_key_display').innerHTML = stored;
});

chrome.storage.local.get('api_key', (result) => {
    document.getElementById('api_key_display').innerHTML = result.api_key;
});

async function loadWatermarkImage() {
    const url = await getFromLocalStorage('watermark_url');
    document.getElementById('image_from_local_storage').src = url;
}
loadWatermarkImage();

// --- Delete SKUs ---
document.getElementById('delete_skus').addEventListener('click', async function (e) {
    e.preventDefault();
    await clearSkuList();
    chrome.storage.local.get('skuList', (result) => {
        const skuList = result.skuList;
        console.log('skuList', skuList.length);
        document.getElementById('skuFound').innerHTML = skuList.length;
    });
});

function clearSkuList() {
    return new Promise((resolve, reject) => {
        chrome.storage.local.set({ skuList: [] }, () => {
            resolve();
        });
    });
}

// --- Pause / Resume Buttons ---
const pauseButton = document.getElementById('pause_button');
const resumeButton = document.getElementById('resume_button');

chrome.storage.local.get(['pauseDisabled', 'resumeDisabled'], (result) => {
    pauseButton.disabled = result.pauseDisabled === true;
    resumeButton.disabled = result.resumeDisabled === true;
});

pauseButton.addEventListener('click', () => {
    pauseButton.disabled = true;
    resumeButton.disabled = false;
    chrome.storage.local.set({ pauseDisabled: true, resumeDisabled: false });
    chrome.runtime.sendMessage({ type: 'pause' });
});

resumeButton.addEventListener('click', () => {
    resumeButton.disabled = true;
    pauseButton.disabled = false;
    chrome.storage.local.set({ pauseDisabled: false, resumeDisabled: true });
    chrome.runtime.sendMessage({ type: 'resume' });
});

// --- Auto AI Title Checkbox ---
document.getElementById('auto_ai_title_checkbox').addEventListener('click', async function (e) {
    const checked = document.getElementById('auto_ai_title_checkbox').checked;
    await saveToLocalStorage('auto_ai_title_checkbox', checked);
    const stored = await getFromLocalStorage('auto_ai_title_checkbox');
    document.getElementById('auto_ai_title_checkbox').checked = stored;
});

chrome.storage.local.get('auto_ai_title_checkbox', (result) => {
    document.getElementById('auto_ai_title_checkbox').checked = result.auto_ai_title_checkbox;
});

// --- Domain Select ---
function saveDomain() {
    const domain = document.querySelector('#domain-select').value;
    chrome.storage.local.set({ domain });
    console.log('domain', domain);
}

function loadDomain() {
    chrome.storage.local.get('domain', (result) => {
        const domain = result.domain;
        if (domain) {
            document.querySelector('#domain-select').value = domain;
            console.log('domain', domain);
        }
    });
}

document.addEventListener('DOMContentLoaded', loadDomain);
document.querySelector('#domain-select').addEventListener('change', saveDomain);

// --- VeRO Protection Switch ---
const veroSwitch = document.getElementById('vero_protection_switch');
veroSwitch.addEventListener('change', () => {
    chrome.storage.local.set({ veroProtectionEnabled: veroSwitch.checked });
});
chrome.storage.local.get('veroProtectionEnabled', (result) => {
    const enabled = result.veroProtectionEnabled ?? true;
    veroSwitch.checked = enabled;
});

// --- Auto Submit Switch ---
document.getElementById('auto_submit_switch').addEventListener('change', async function (e) {
    chrome.storage.local.set({ autoSubmitEnabled: document.getElementById('auto_submit_switch').checked });
});
chrome.storage.local.get('autoSubmitEnabled', (result) => {
    if (result.autoSubmitEnabled == null) {
        result.autoSubmitEnabled = true;
        chrome.storage.local.set({ autoSubmitEnabled: result.autoSubmitEnabled });
    }
    document.getElementById('auto_submit_switch').checked = result.autoSubmitEnabled;
});

// --- Enable Image Template Switch ---
document.getElementById('enable_image_template_switch').addEventListener('change', async function (e) {
    chrome.storage.local.set({ enableImageTemplate: document.getElementById('enable_image_template_switch').checked });
});
chrome.storage.local.get('enableImageTemplate', (result) => {
    if (result.enableImageTemplate == null) {
        result.enableImageTemplate = false;
        chrome.storage.local.set({ enableImageTemplate: result.enableImageTemplate });
    }
    document.getElementById('enable_image_template_switch').checked = result.enableImageTemplate;
});

// --- Use Review Images Switch ---
document.getElementById('use_review_images_switch').addEventListener('change', async function (e) {
    // Keep review images and simple description in sync
    if (document.getElementById('use_review_images_switch').checked !== document.getElementById('use_simple_description_switch').checked) {
        document.getElementById('use_simple_description_switch').click();
    }
    chrome.storage.local.set({ useReviewImages: document.getElementById('use_review_images_switch').checked });
});
chrome.storage.local.get('useReviewImages', (result) => {
    if (result.useReviewImages == null) {
        result.useReviewImages = false;
        chrome.storage.local.set({ useReviewImages: result.useReviewImages });
    }
    document.getElementById('use_review_images_switch').checked = result.useReviewImages;
});

// --- Amazon Links List ---
const listButton = document.getElementById('list-btn');
const totalLinksLabel = document.getElementById('total-links-label');

listButton.addEventListener('click', () => {
    const links = document.getElementById('amazon-links').value.split('\n');
    chrome.storage.local.set({ amazonLinks: links }, () => {
        console.log('Amazon links saved to local storage:', links);
        chrome.runtime.sendMessage({ action: 'listAmazonProducts' });
    });
    pauseButton.disabled = false;
    resumeButton.disabled = true;
    chrome.storage.local.set({ pauseDisabled: false, resumeDisabled: true });
});

chrome.storage.local.get('amazonLinks', (result) => {
    const links = result.amazonLinks;
    console.log('amazonLinks', links);
    if (links) {
        document.getElementById('amazon-links').value = links.join('\n');
        totalLinksLabel.innerText = links.length;
    }
});

// --- Position / Deduplication ---
const positionInput = document.getElementById('position-input');
const updatePositionButton = document.getElementById('update-position-btn');

updatePositionButton.addEventListener('click', async () => {
    const position = parseInt(positionInput.value);
    if (!isNaN(position)) {
        chrome.storage.local.set({ position }, () => {
            console.log('Position updated:', position);
            positionInput.value = position;
        });
    }

    let linksText = document.getElementById('amazon-links').value.trim();
    let links = linksText === '' ? [] : linksText.split('\n');
    console.log('Amazon links saved to local storage:', links);
    console.log('amazonLinks.length', links.length);
    totalLinksLabel.innerText = links.length;

    const decodedSkus = await getDecodedSkuList();
    const filteredLinks = [];

    for await (const link of links) {
        if (link !== '') {
            const asin = getAsinFromUrl(link);
            console.log('asin', asin);
            const isDuplicate = decodedSkus.includes(asin);
            console.log('isDuplicate', isDuplicate);
            if (!isDuplicate) filteredLinks.push(link);
        }
    }

    await chrome.storage.local.set({ amazonLinks: filteredLinks });
    console.log('Amazon links saved to local storage:', filteredLinks);
    totalLinksLabel.innerText = filteredLinks.length;
    document.getElementById('amazon-links').value = filteredLinks.join('\n');
});

chrome.storage.local.get('position', (result) => {
    console.log('Position restored:', result.position);
    if (result.position) {
        positionInput.value = result.position;
    } else {
        chrome.storage.local.set({ position: 0 }, () => {
            console.log('Position set to 0');
        });
    }
});

// --- Navigation Buttons ---
document.getElementById('status-report').addEventListener('click', async function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('bulk_post/table.html') });
});

document.getElementById('toggle_chatgpt_test_mode').addEventListener('click', async function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('ChatGpt_Test_Mode/index.html') });
});

// --- Thread Count ---
const threadCountInput = document.getElementById('thread-count');
threadCountInput.addEventListener('change', () => {
    chrome.storage.local.set({ threadCount: threadCountInput.value });
});
chrome.storage.local.get('threadCount', ({ threadCount }) => {
    if (threadCount) {
        threadCountInput.value = threadCount;
    } else {
        threadCountInput.value = 1;
        chrome.storage.local.set({ threadCount: 1 });
    }
});

// --- Max / Min Price ---
document.getElementById('max-price').addEventListener('change', () => {
    chrome.storage.local.set({ maxPrice: document.getElementById('max-price').value });
});
chrome.storage.local.get('maxPrice', ({ maxPrice }) => {
    if (maxPrice) {
        document.getElementById('max-price').value = maxPrice;
    } else {
        document.getElementById('max-price').value = 100;
        chrome.storage.local.set({ maxPrice: 100 });
    }
});

document.getElementById('min-price').addEventListener('change', () => {
    chrome.storage.local.set({ minPrice: document.getElementById('min-price').value });
});
chrome.storage.local.get('minPrice', ({ minPrice }) => {
    if (minPrice) {
        document.getElementById('min-price').value = minPrice;
    } else {
        document.getElementById('min-price').value = 0;
        chrome.storage.local.set({ minPrice: 0 });
    }
});

// --- Total ASINs to Fetch from Search ---
document.getElementById('total-asins-to-fetch-from-search').addEventListener('change', () => {
    chrome.storage.local.set({ totalAsinsToFetchFromSearch: document.getElementById('total-asins-to-fetch-from-search').value });
});
chrome.storage.local.get('totalAsinsToFetchFromSearch', ({ totalAsinsToFetchFromSearch }) => {
    if (totalAsinsToFetchFromSearch) {
        document.getElementById('total-asins-to-fetch-from-search').value = totalAsinsToFetchFromSearch;
    } else {
        document.getElementById('total-asins-to-fetch-from-search').value = 2;
        chrome.storage.local.set({ totalAsinsToFetchFromSearch: 2 });
    }
});

// --- Amazon Search Queries ---
const searchQueriesTextarea = document.getElementById('amazon-search-querys');
searchQueriesTextarea.addEventListener('change', () => {
    const queries = searchQueriesTextarea.value.split('\n');
    chrome.storage.local.set({ amazonSearchQuerys: queries }, () => {
        console.log('Amazon Search Querys saved to local storage:', queries);
    });
    document.getElementById('amazon-search-total-querys-label').innerText = queries.length;
});
chrome.storage.local.get('amazonSearchQuerys', (result) => {
    const queries = result.amazonSearchQuerys;
    if (queries) {
        searchQueriesTextarea.value = queries.join('\n');
        document.getElementById('amazon-search-total-querys-label').innerText = queries.length;
    }
});

document.getElementById('amazon-search-position-input').addEventListener('change', () => {
    const pos = parseInt(document.getElementById('amazon-search-position-input').value);
    if (!isNaN(pos)) {
        chrome.storage.local.set({ amazonSearchQueryPosition: pos }, () => {
            console.log('amazonSearchQueryPosition updated:', pos);
        });
    }
});
chrome.storage.local.get('amazonSearchQueryPosition', (result) => {
    const pos = result.amazonSearchQueryPosition;
    if (pos) {
        document.getElementById('amazon-search-position-input').value = pos;
    } else {
        document.getElementById('amazon-search-position-input').value = 0;
        chrome.storage.local.set({ amazonSearchQueryPosition: 0 });
    }
});

document.getElementById('search-amazon-querys-btn').addEventListener('click', async function (e) {
    e.preventDefault();
    chrome.runtime.sendMessage({ type: 'startSearchingAmazon', searchType: 'title' });
});

document.getElementById('search-amazon-keywords-btn').addEventListener('click', async function (e) {
    e.preventDefault();
    chrome.runtime.sendMessage({ type: 'startSearchingAmazon', searchType: 'keywords' });
});

// --- Open Sub-Pages ---
document.getElementById('open_duplicate_checker').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Duplicate_Settings/page.html') });
});

document.getElementById('research_seo').addEventListener('click', function (e) {
    console.log('research_seo clicked');
    e.preventDefault();
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, { message: 'research_seo' });
    });
});

document.getElementById('toggle_test_mode_ebay').addEventListener('click', async function (e) {
    e.preventDefault();
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, { message: 'toggle_test_mode_ebay' });
    });
});

document.getElementById('open_product_finder_button').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Product_Finder/product_finder.html') });
});

document.getElementById('open_bulk_lister').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('bulk_post/bulk_post_settings.html') });
});

document.getElementById('open_image_template').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Image_Template_Designer/index.html') });
});

document.getElementById('open_tracker').addEventListener('click', function (e) {
    e.preventDefault();
    const url = chrome.runtime.getURL('fast_tracker/index.html');
    console.log('url ', url);
    chrome.tabs.create({ url });
});

document.getElementById('open_competitor_research').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Competitor_Research/index.html') });
});

document.getElementById('open_quick_chat_settings').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Quick_Chat_Settings/index.html') });
});

// --- VeRO Brands Fetcher ---
document.addEventListener('DOMContentLoaded', async () => {
    const getVeroBrandsButton = document.getElementById('getVeroBrandsButton');
    const veroBrandStatus = document.getElementById('veroBrandStatus');
    const spinner = document.getElementById('spinner');
    const statusIcon = document.getElementById('statusIcon');
    const fetchedCount = document.getElementById('fetchedCount');

    chrome.storage.local.get(['status', 'veroBrands', 'lastFetch'], (result) => {
        if (result.status && result.veroBrands) {
            veroBrandStatus.textContent = result.status === 'success' ? 'Success!' : 'Failed!';
            statusIcon.className = 'icon ' + (result.status === 'success' ? 'success' : 'fail');
            statusIcon.textContent = result.status === 'success' ? '✓' : '✗';
            fetchedCount.textContent = 'Total Brands: ' + result.veroBrands.length;
            if (result.lastFetch) {
                const lastFetchStr = new Date(result.lastFetch).toLocaleString();
                veroBrandStatus.textContent += ' Last fetched on ' + lastFetchStr + '.';
            }
        }
    });

    getVeroBrandsButton.addEventListener('click', async () => {
        spinner.classList.remove('hidden');
        veroBrandStatus.textContent = 'Fetching...';
        statusIcon.classList.add('hidden');
        fetchedCount.classList.add('hidden');

        const brands = await (async function fetchVeroBrands() {
            try {
                const response = await fetch('https://us-central1-silentsnipe-ce4ca.cloudfunctions.net/app/api/v1/veroBrands');
                if (!response.ok) throw new Error('Network response was not ok ' + response.statusText);
                const data = await response.json();
                return data.data.map(item => item.title);
            } catch (e) {
                console.error('There has been a problem with your fetch operation:', e);
                return null;
            }
        }());

        spinner.classList.add('hidden');
        fetchedCount.classList.remove('hidden');

        if (brands) {
            const now = new Date();
            chrome.storage.local.set({ status: 'success', veroBrands: brands, lastFetch: now.getTime() });
            veroBrandStatus.textContent = 'Success! Last fetched on ' + now.toLocaleString() + '.';
            statusIcon.className = 'icon success';
            statusIcon.textContent = '✓';
            fetchedCount.textContent = 'Total Brands: ' + brands.length;
        } else {
            chrome.storage.local.set({ status: 'fail' });
            veroBrandStatus.textContent = 'Failed!';
            statusIcon.className = 'icon fail';
            statusIcon.textContent = '✗';
            fetchedCount.textContent = 'Total Brands: 0';
        }
    });
});

// --- ChatGPT Test Button ---
document.getElementById('ask_chatgpt').addEventListener('click', async function (e) {
    e.preventDefault();
    const input = document.getElementById('chatgpt_input').value;
    console.log('chatgpt_input ', input);
    const response = await askChatGptForHighQualityTitles(
        'Pawfly Adjustable Aquarium Air Pump 4-LPM 2 Outlets with Oxygen Accessories f...',
        'Pawfly Adjustable Aquarium Air Pump 4-LPM 2 Outlets with Oxygen Accessories for 20-100 Gallon Fish Tank Pond\n  Pawfly Adjustable aquarium air pump is perfect for both medium Freshwater and Marine fish tank.\n  Ultra whisper quiet, Minimum 25 dB in lowest flow rate(sound like rusting leaves, ticking watch)\n  Adjustable flow rate with 2 outlets, fit for fish tanks up to 100-gallon.\n  4-LPM, 4 Watt, Pressure: 0.016 Mpa.\n  Comes with Accessories you need: 6.5 ft Airline, 2 x Air Stone, 2 x Return Valve, 2 Connectors.'
    );
    console.log('response ', response);
});

// --- Amazon Affiliate Tag Switch ---
document.getElementById('apply_amazon_affiliate_tag_switch').addEventListener('change', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ applyAmazonAffiliateTag: document.getElementById('apply_amazon_affiliate_tag_switch').checked });
});
chrome.storage.local.get('applyAmazonAffiliateTag', (result) => {
    if (result.applyAmazonAffiliateTag == null) {
        result.applyAmazonAffiliateTag = false;
        chrome.storage.local.set({ applyAmazonAffiliateTag: result.applyAmazonAffiliateTag });
    } else {
        document.getElementById('apply_amazon_affiliate_tag_switch').checked = result.applyAmazonAffiliateTag;
    }
});

document.getElementById('open_advanced_title_builder').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Advanced_Title_Builder/index.html') });
});

// --- Fill Required Item Specifics ---
document.getElementById('fill_required_item_specifics_switch').addEventListener('change', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ shouldFillRequiredItemSpecifics: document.getElementById('fill_required_item_specifics_switch').checked });
});
chrome.storage.local.get('shouldFillRequiredItemSpecifics', (result) => {
    console.log('res.shouldFillRequiredItemSpecifics ', result.shouldFillRequiredItemSpecifics);
    if (result.shouldFillRequiredItemSpecifics == null) {
        result.shouldFillRequiredItemSpecifics = true;
        chrome.storage.local.set({ shouldFillRequiredItemSpecifics: result.shouldFillRequiredItemSpecifics });
    } else {
        document.getElementById('fill_required_item_specifics_switch').checked = result.shouldFillRequiredItemSpecifics;
    }
});

// --- Fill Optional Item Specifics ---
document.getElementById('fill_optional_item_specifics_switch').addEventListener('change', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ shouldFillOptionalItemSpecifics: document.getElementById('fill_optional_item_specifics_switch').checked });
});
chrome.storage.local.get('shouldFillOptionalItemSpecifics', (result) => {
    console.log('res.shouldFillOptionalItemSpecifics ', result.shouldFillOptionalItemSpecifics);
    if (result.shouldFillOptionalItemSpecifics == null) {
        result.shouldFillOptionalItemSpecifics = true;
        chrome.storage.local.set({ shouldFillOptionalItemSpecifics: result.shouldFillOptionalItemSpecifics });
    } else {
        document.getElementById('fill_optional_item_specifics_switch').checked = result.shouldFillOptionalItemSpecifics;
    }
});

// --- Hide Personal Information ---
document.getElementById('hide_personal_information_switch').addEventListener('change', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ shouldHidePersonalInformation: document.getElementById('hide_personal_information_switch').checked });
});
chrome.storage.local.get('shouldHidePersonalInformation', (result) => {
    if (result.shouldHidePersonalInformation == null) {
        result.shouldHidePersonalInformation = false;
        chrome.storage.local.set({ shouldHidePersonalInformation: result.shouldHidePersonalInformation });
    } else {
        document.getElementById('hide_personal_information_switch').checked = result.shouldHidePersonalInformation;
    }
});

// --- Test Identify Listing ---
document.getElementById('test_identify_listing').addEventListener('click', async function (e) {
    e.preventDefault();
    const productData = await fetch('../amazonDataTest.json').then(r => r.json());
    console.log('product_data ', productData);
    chrome.runtime.sendMessage({ type: 'list_to_ebay_in_same_tab', product_data: productData });
});

// --- Agent Name ---
document.getElementById('agent_name').addEventListener('input', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ agentName: document.getElementById('agent_name').value });
});
chrome.storage.local.get('agentName', (result) => {
    if (result.agentName == null) {
        chrome.storage.local.set({ agentName: document.getElementById('agent_name').value });
    } else {
        document.getElementById('agent_name').value = result.agentName;
    }
});

// --- Virtual Clipboard Keys ---
document.getElementById('virtual_clipboard_1_key').addEventListener('input', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ virtualClipboard1Key: document.getElementById('virtual_clipboard_1_key').value });
});
chrome.storage.local.get('virtualClipboard1Key', async (result) => {
    if (result.virtualClipboard1Key == null) {
        // No user login - leave field empty
        chrome.storage.local.set({ virtualClipboard1Key: '' });
        document.getElementById('virtual_clipboard_1_key').value = '';
    } else {
        document.getElementById('virtual_clipboard_1_key').value = result.virtualClipboard1Key;
    }
});

document.getElementById('virtual_clipboard_2_key').addEventListener('input', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ virtualClipboard2Key: document.getElementById('virtual_clipboard_2_key').value });
});
chrome.storage.local.get('virtualClipboard2Key', (result) => {
    if (result.virtualClipboard2Key == null) {
        chrome.storage.local.set({ virtualClipboard2Key: document.getElementById('virtual_clipboard_2_key').value });
    } else {
        document.getElementById('virtual_clipboard_2_key').value = result.virtualClipboard2Key;
    }
});

// --- Snipe Mode ---
document.getElementById('snipe_mode_switch').addEventListener('change', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ snipeModeEnabled: document.getElementById('snipe_mode_switch').checked });
});
chrome.storage.local.get('snipeModeEnabled', (result) => {
    if (result.snipeModeEnabled == null || result.snipeModeEnabled === '') {
        result.snipeModeEnabled = false;
        chrome.storage.local.set({ snipeModeEnabled: result.snipeModeEnabled });
    } else {
        document.getElementById('snipe_mode_switch').checked = result.snipeModeEnabled;
    }
});

// --- Use Simple Description ---
document.getElementById('use_simple_description_switch').addEventListener('change', async function (e) {
    e.preventDefault();
    chrome.storage.local.set({ useSimpleDescription: document.getElementById('use_simple_description_switch').checked });
});
chrome.storage.local.get('useSimpleDescription', (result) => {
    console.log('useSimpleDescription ', result.useSimpleDescription);
    if (result.useSimpleDescription == null) {
        result.useSimpleDescription = false;
        chrome.storage.local.set({ useSimpleDescription: result.useSimpleDescription });
    } else {
        document.getElementById('use_simple_description_switch').checked = result.useSimpleDescription;
    }
});

// --- More Navigation Buttons ---
document.getElementById('open_boost_my_listings').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Boost_My_Listings/index.html') });
});

document.getElementById('open_sniper_list').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('Sniper_List/index.html') });
});

document.getElementById('open_stock_monitor').addEventListener('click', function (e) {
    e.preventDefault();
    chrome.tabs.create({ url: chrome.runtime.getURL('fast_tracker/index.html') });
});

// --- Schedule Listing Time ---
const scheduleListingTimeSelect = document.getElementById('schedule_listing_time');
scheduleListingTimeSelect.addEventListener('change', function (e) {
    e.preventDefault();
    let rawValue = scheduleListingTimeSelect.value;
    let scheduleTime = rawValue !== 'false' && Number(rawValue);
    console.log('scheduleTime', scheduleTime);
    chrome.storage.local.set({ scheduleListingTime: scheduleTime });
});

chrome.storage.local.get('scheduleListingTime', (result) => {
    console.log('scheduleListingTime', result.scheduleListingTime);
    if (result.scheduleListingTime === undefined) {
        chrome.storage.local.set({ scheduleListingTime: false });
        scheduleListingTimeSelect.value = 'false';
    } else {
        const value = result.scheduleListingTime;
        scheduleListingTimeSelect.value = value === false ? 'false' : String(value);
    }
});
// ---- Firebase Auth for Popup ----
const FIREBASE_API_KEY = 'AIzaSyATF7lsdV369C-F3fVxrhsz1aDbuBABACg';

// FIX: this used to send {type: 'setAuthToken', ...}, but background.bundle.js
// only ever listens for 'setAuthData' — there is no 'setAuthToken' handler at all,
// so every one of these messages was silently going nowhere. This also never
// forwarded plan/freeCredits, so the background service worker's cache
// (_cachedPlan, used by checkMembership as a fallback) was never populated,
// even though the popup itself knew the user's plan and credits the whole time.
function pushAuthDataToBackground({ token, uid, refreshToken, plan, freeCredits } = {}) {
    if (!token || !uid) return;
    chrome.runtime.sendMessage({
        type: 'setAuthData',
        token,
        uid,
        refreshToken,
        plan,
        freeCredits
    });
}

async function loginWithEmail(email, password) {
    const res = await fetch(
        `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${FIREBASE_API_KEY}`,
        {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ email, password, returnSecureToken: true })
        }
    );
    const data = await res.json();
    if (data.error) throw new Error(data.error.message);
    return data; // contains idToken, localId (uid), email
}

async function initAuth() {
    // Check if already logged in
    const stored = await chrome.storage.local.get(['authToken', 'userEmail', 'userId', 'refreshToken']);

    if (stored.authToken) {
        // Already logged in - show features, hide login
        showLoggedIn(stored.userEmail);
        // Send token to background (plan/credits get pushed separately once fetchUserCredits resolves)
        pushAuthDataToBackground({
            token: stored.authToken,
            uid: stored.userId,
            refreshToken: stored.refreshToken
        });
    } else {
        // Not logged in - show login form
        document.getElementById('login_status').style.display = 'block';
        document.getElementById('user_features_containers').style.display = 'none';
    }
}

function showLoggedIn(email) {
    // Hide login form, show features and user header
    document.getElementById('login_status').style.display = 'none';
    document.getElementById('user_features_containers').style.display = 'block';
    document.getElementById('user_header').style.display = 'block';
    document.getElementById('status_text').textContent = 'Logged in as:';
    document.getElementById('email_text').textContent = email;
    document.getElementById('logout_icon').style.display = 'inline-block';
    document.getElementById('credits_text').style.display = 'inline';
    document.getElementById('subscription_text').style.display = 'inline';
    // Fetch and display credits from server
    fetchUserCredits();
}

/**
 * Refreshes an expired Firebase ID token using the stored refresh token.
 * Returns the new idToken string, or null if refresh fails.
 * Also persists the new idToken + refreshToken back to chrome.storage.local.
 */
async function refreshFirebaseToken(storedRefreshToken) {
    if (!storedRefreshToken) return null;
    try {
        const res = await fetch(
            `https://securetoken.googleapis.com/v1/token?key=${FIREBASE_API_KEY}`,
            {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(storedRefreshToken)}`
            }
        );
        if (!res.ok) {
            console.warn('Token refresh failed with status', res.status);
            return null;
        }
        const data = await res.json();
        const newIdToken = data.id_token;
        const newRefreshToken = data.refresh_token;
        if (!newIdToken) return null;
        // Persist fresh tokens so future popup opens don't need to refresh again immediately
        await chrome.storage.local.set({ authToken: newIdToken, refreshToken: newRefreshToken });
        return newIdToken;
    } catch (e) {
        console.warn('Token refresh error:', e);
        return null;
    }
}

/**
 * Fetches the user's credits and subscription tier from Firestore
 * and updates the header display. Automatically refreshes the Firebase
 * ID token if it has expired (the previous root cause of "Unlimited" being shown).
 */
async function fetchUserCredits() {
    const creditsEl = document.getElementById('credits_text');
    const subscriptionEl = document.getElementById('subscription_text');

    // Helper: apply values to the header display
    function applyDisplay(credits, subscription) {
        if (credits !== null && credits !== undefined) creditsEl.textContent = `Credits: ${credits}`;
        if (subscription !== null && subscription !== undefined) subscriptionEl.textContent = subscription;
    }

    // Helper: parse a Firestore field value regardless of its type wrapper
    const getVal = (f) => {
        if (!f) return null;
        return f.stringValue ?? f.integerValue ?? f.doubleValue ?? f.booleanValue ?? null;
    };

    // Helper: attempt a Firestore fetch for the user doc and return parsed credits/subscription,
    // or null if the response is not ok or the doc has no recognised fields.
    async function tryFirestore(idToken, uid) {
        const fsUrl = `https://firestore.googleapis.com/v1/projects/silentsnipe-ce4ca/databases/(default)/documents/users/${uid}`;
        const fsRes = await fetch(fsUrl, {
            headers: { 'Authorization': `Bearer ${idToken}` }
        });

        if (!fsRes.ok) {
            console.warn('Firestore returned', fsRes.status, fsRes.statusText);
            return null; // caller decides whether to refresh and retry
        }

        const doc = await fsRes.json();
        const fields = doc.fields || {};
        console.log('Firestore user fields:', JSON.stringify(fields, null, 2));

        const rawCredits = getVal(fields.freeCredits) ?? getVal(fields.credits) ?? getVal(fields.aiCredits)
            ?? getVal(fields.remainingCredits) ?? getVal(fields.Credits) ?? null;
        const credits = rawCredits !== null ? Math.floor(Number(rawCredits)) : null;

        const subscription = getVal(fields.subscription) ?? getVal(fields.subscriptionTier)
            ?? getVal(fields.plan) ?? getVal(fields.tier) ?? null;

        if (credits === null && subscription === null) {
            console.warn('Firestore doc found but no recognised credits/subscription field. Fields present:', Object.keys(fields));
            return null;
        }
        return { credits, subscription };
    }

    try {
        const stored = await chrome.storage.local.get(['authToken', 'refreshToken', 'userId', 'userEmail']);

        if (!stored.authToken) {
            // No token at all — user is not authenticated; nothing to show
            console.info('fetchUserCredits: no authToken in storage');
            return;
        }

        // Decode UID from the JWT (more reliable than the stored userId field)
        let uid = stored.userId;
        try {
            const payload = JSON.parse(atob(stored.authToken.split('.')[1]));
            uid = payload.user_id || payload.sub || uid;
        } catch (e) { /* keep stored.userId */ }

        // --- Attempt 1: use current stored token ---
        try {
            const result = await tryFirestore(stored.authToken, uid);
            if (result) {
                applyDisplay(result.credits, result.subscription);
                pushAuthDataToBackground({
                    token: stored.authToken,
                    uid,
                    refreshToken: stored.refreshToken,
                    plan: result.subscription,
                    freeCredits: result.credits
                });
                return;
            }
        } catch (fsErr) {
            console.warn('Firestore fetch error (attempt 1):', fsErr);
        }

        // --- Attempt 2: token may be expired — try refreshing then retry ---
        console.info('fetchUserCredits: retrying after token refresh...');
        const newIdToken = await refreshFirebaseToken(stored.refreshToken);
        if (newIdToken) {
            // Re-decode uid from fresh token just in case
            try {
                const payload = JSON.parse(atob(newIdToken.split('.')[1]));
                uid = payload.user_id || payload.sub || uid;
            } catch (e) { /* keep existing uid */ }

            try {
                const result = await tryFirestore(newIdToken, uid);
                if (result) {
                    applyDisplay(result.credits, result.subscription);
                    const latest = await chrome.storage.local.get('refreshToken');
                    pushAuthDataToBackground({
                        token: newIdToken,
                        uid,
                        refreshToken: latest.refreshToken,
                        plan: result.subscription,
                        freeCredits: result.credits
                    });
                    return;
                }
            } catch (fsErr) {
                console.warn('Firestore fetch error (attempt 2, after refresh):', fsErr);
            }
        }

        // --- Fallback: all Firestore attempts failed ---
        // Do NOT silently show "Unlimited" — show an honest error state instead
        console.warn('fetchUserCredits: all Firestore attempts failed; showing error state');
        creditsEl.textContent = 'Credits: error';

    } catch (e) {
        console.warn('fetchUserCredits unhandled error:', e);
        creditsEl.textContent = 'Credits: error';
    }
}

// Login button handler
document.getElementById('login_button').addEventListener('click', async (e) => {
    e.preventDefault();
    const email = document.getElementById('username').value;
    const password = document.getElementById('password').value;

    try {
        const data = await loginWithEmail(email, password);
        // Save to storage
        await chrome.storage.local.set({
            authToken: data.idToken,
            refreshToken: data.refreshToken,
            userId: data.localId,
            userEmail: data.email
        });
        // Tell background script
        pushAuthDataToBackground({
            token: data.idToken,
            uid: data.localId,
            refreshToken: data.refreshToken
        });
        showLoggedIn(data.email);
    } catch (err) {
        alert('Login failed: ' + err.message);
    }
});

// Logout handler
document.getElementById('logout_icon').addEventListener('click', async () => {
    await chrome.storage.local.remove(['authToken', 'userId', 'userEmail']);
    chrome.runtime.sendMessage({ type: 'clearAuthToken' });
    document.getElementById('user_header').style.display = 'none';
    document.getElementById('login_status').style.display = 'block';
    document.getElementById('user_features_containers').style.display = 'none';
    document.getElementById('status_text').textContent = 'Not logged in';
    document.getElementById('logout_icon').style.display = 'none';
    document.getElementById('email_text').textContent = '';
    document.getElementById('credits_text').textContent = 'Credits: --';
    document.getElementById('credits_text').style.display = 'none';
    document.getElementById('subscription_text').style.display = 'none';
});

// Run on popup open
initAuth();