Torn Stock Investment Advisor

Calculates optimal next stock investment based on ROI

// ==UserScript==
// @name         Torn Stock Investment Advisor
// @namespace    http://tampermonkey.net/
// @version      1.11
// @description  Calculates optimal next stock investment based on ROI 
// @author       ShAdOwCrEsT [3929345]
// @match        https://www.torn.com/*
// @grant        GM_xmlhttpRequest
// @connect      ath.shadowcrest96.workers.dev
// ==/UserScript==

(function() {
    'use strict';

    function gmFetch(url) {
        return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            onload: function(response) {
                try {
                    resolve({
                        ok: response.status >= 200 && response.status < 300,
                        status: response.status,
                        json: async () => JSON.parse(response.responseText)
                    });
                } catch (e) {
                    reject(e);
                }
            },
            onerror: function(error) {
                reject(error);
            }
        });
    });
    }

    const WORKER_URL = 'https://ath.shadowcrest96.workers.dev/';

    const INVESTMENT_TABLE = [
        { acronym: 'MCS', increment: 1, cost: 275586500 },
        { acronym: 'SYM', increment: 1, cost: 354730000 },
        { acronym: 'CBD', increment: 1, cost: 136076500 },
        { acronym: 'FHG', increment: 1, cost: 1687140000 },
        { acronym: 'MCS', increment: 2, cost: 551173000 },
        { acronym: 'TCT', increment: 1, cost: 32146000 },
        { acronym: 'PRN', increment: 1, cost: 607940000 },
        { acronym: 'GRN', increment: 1, cost: 150135000 },
        { acronym: 'SYM', increment: 2, cost: 709460000 },
        { acronym: 'MUN', increment: 1, cost: 2834250000 },
        { acronym: 'THS', increment: 1, cost: 58533000 },
        { acronym: 'IOU', increment: 1, cost: 538470000 },
        { acronym: 'CBD', increment: 2, cost: 272153000 },
        { acronym: 'FHG', increment: 2, cost: 3374280000 },
        { acronym: 'MCS', increment: 3, cost: 1102346000 },
        { acronym: 'PTS', increment: 1, cost: 755400000 },
        { acronym: 'TMI', increment: 1, cost: 1336920000 },
        { acronym: 'EWM', increment: 1, cost: 278490000 },
        { acronym: 'HRG', increment: 1, cost: 2708400000 },
        { acronym: 'TCT', increment: 2, cost: 64292000 },
        { acronym: 'PRN', increment: 2, cost: 1215880000 },
        { acronym: 'TSB', increment: 1, cost: 3432480000 },
        { acronym: 'LSC', increment: 1, cost: 281230000 },
        { acronym: 'GRN', increment: 2, cost: 300270000 },
        { acronym: 'SYM', increment: 3, cost: 1418920000 },
        { acronym: 'ASS', increment: 1, cost: 353150000 },
        { acronym: 'CNC', increment: 1, cost: 6772350000 },
        { acronym: 'MUN', increment: 2, cost: 5668500000 },
        { acronym: 'THS', increment: 2, cost: 117066000 },
        { acronym: 'TCI', increment: 1, cost: 1806360000 },
        { acronym: 'IOU', increment: 2, cost: 1076940000 },
        { acronym: 'CBD', increment: 3, cost: 544306000 },
        { acronym: 'FHG', increment: 3, cost: 6748560000 },
        { acronym: 'MCS', increment: 4, cost: 2204692000 },
        { acronym: 'PTS', increment: 2, cost: 1510800000 },
        { acronym: 'TMI', increment: 2, cost: 2673840000 },
        { acronym: 'EWM', increment: 2, cost: 556980000 },
        { acronym: 'HRG', increment: 2, cost: 5416800000 },
        { acronym: 'TCT', increment: 3, cost: 128584000 },
        { acronym: 'PRN', increment: 3, cost: 2431760000 },
        { acronym: 'TCI', increment: 2, cost: 1806360000 },
        { acronym: 'TSB', increment: 2, cost: 6864960000 },
        { acronym: 'TCI', increment: 3, cost: 1806360000 },
        { acronym: 'LSC', increment: 2, cost: 562460000 },
        { acronym: 'GRN', increment: 3, cost: 600540000 },
        { acronym: 'SYM', increment: 4, cost: 2837840000 },
        { acronym: 'ASS', increment: 2, cost: 706300000 },
        { acronym: 'CNC', increment: 2, cost: 13544700000 },
        { acronym: 'MUN', increment: 3, cost: 11337000000 },
        { acronym: 'THS', increment: 3, cost: 234132000 },
        { acronym: 'IOU', increment: 3, cost: 2153880000 },
        { acronym: 'CBD', increment: 4, cost: 1088612000 },
        { acronym: 'FHG', increment: 4, cost: 13497120000 },
        { acronym: 'PTS', increment: 3, cost: 3021600000 },
        { acronym: 'TMI', increment: 3, cost: 5347680000 },
        { acronym: 'EWM', increment: 3, cost: 1113960000 },
        { acronym: 'HRG', increment: 3, cost: 10833600000 },
        { acronym: 'TCT', increment: 4, cost: 257168000 },
        { acronym: 'LAG', increment: 1, cost: 344790000 },
        { acronym: 'PRN', increment: 4, cost: 4863520000 },
        { acronym: 'TSB', increment: 3, cost: 13729920000 },
        { acronym: 'LSC', increment: 3, cost: 1124920000 },
        { acronym: 'GRN', increment: 4, cost: 1201080000 },
        { acronym: 'ASS', increment: 3, cost: 1412600000 },
        { acronym: 'CNC', increment: 3, cost: 27089400000 },
        { acronym: 'MUN', increment: 4, cost: 22674000000 },
        { acronym: 'THS', increment: 4, cost: 468264000 },
        { acronym: 'IOU', increment: 4, cost: 4307760000 },
        { acronym: 'PTS', increment: 4, cost: 6043200000 },
        { acronym: 'TMI', increment: 4, cost: 10695360000 },
        { acronym: 'EWM', increment: 4, cost: 2227920000 },
        { acronym: 'HRG', increment: 4, cost: 21667200000 },
        { acronym: 'LAG', increment: 2, cost: 689580000 },
        { acronym: 'TSB', increment: 4, cost: 27459840000 },
        { acronym: 'LSC', increment: 4, cost: 2249840000 },
        { acronym: 'ASS', increment: 4, cost: 2825200000 },
        { acronym: 'CNC', increment: 4, cost: 54178800000 },
        { acronym: 'LAG', increment: 3, cost: 1379160000 },
        { acronym: 'TCC', increment: 1, cost: 3820275000 },
        { acronym: 'LAG', increment: 4, cost: 2758320000 },
        { acronym: 'TCC', increment: 2, cost: 7640550000 },
        { acronym: 'TCC', increment: 3, cost: 15281100000 },
        { acronym: 'TCC', increment: 4, cost: 30562200000 }
    ];

    const STOCK_MAP = {
        1: 'TSB', 2: 'TCI', 3: 'SYS', 4: 'LAG', 5: 'IOU',
        6: 'GRN', 7: 'THS', 8: 'YAZ', 9: 'TCT', 10: 'CNC',
        11: 'MSG', 12: 'TMI', 13: 'TCP', 14: 'IIL', 15: 'FHG',
        16: 'SYM', 17: 'LSC', 18: 'PRN', 19: 'EWM', 20: 'TCM',
        21: 'ELT', 22: 'HRG', 23: 'TGP', 24: 'MUN', 25: 'WSU',
        26: 'IST', 27: 'BAG', 28: 'EVL', 29: 'MCS', 30: 'WLT',
        31: 'TCC', 32: 'ASS', 33: 'CBD', 34: 'LOS', 35: 'PTS'
    };

    const STOCK_IMAGES = {
        'TSB': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TSB.svg',
        'TCI': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TCI.svg',
        'SYS': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/SYS.svg',
        'LAG': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/LAG.svg',
        'IOU': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/IOU.svg',
        'GRN': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/GRN.svg',
        'THS': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/THS.svg',
        'YAZ': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/YAZ.svg',
        'TCT': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TCT.svg',
        'CNC': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/CNC.svg',
        'MSG': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/MSG.svg',
        'TMI': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TMI.svg',
        'TCP': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TCP.svg',
        'IIL': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/IIL.svg',
        'FHG': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/FHG.svg',
        'SYM': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/SYM.svg',
        'LSC': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/LSC.svg',
        'PRN': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/PRN.svg',
        'EWM': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/EWM.svg',
        'TCM': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TCM.svg',
        'ELT': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/ELT.svg',
        'HRG': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/HRG.svg',
        'TGP': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TGP.svg',
        'MUN': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/MUN.svg',
        'WSU': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/WSU.svg',
        'IST': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/IST.svg',
        'BAG': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/BAG.svg',
        'EVL': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/EVL.svg',
        'MCS': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/MCS.svg',
        'WLT': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/WLT.svg',
        'TCC': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/TCC.svg',
        'ASS': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/ASS.svg',
        'CBD': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/CBD.svg',
        'LOS': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/LOS.svg',
        'PTS': 'https://www.torn.com/images/v2/stock-market/dark-mode/logos/PTS.svg'
    };

    const STORAGE_KEY = 'torn_stock_advisor_api_key';
    const SETTINGS_KEY = 'torn_stock_advisor_settings';
    const INVESTMENTS_KEY = 'torn_stock_advisor_investments';
    const EXTRA_STOCKS_KEY = 'torn_stock_advisor_extra_stocks';
    let apiKey = localStorage.getItem(STORAGE_KEY) || '';

    let settings = {
        pending: true, wallet: true, bank: true, cayman: true, vault: true, piggybank: true,
        items: true, displaycase: true, bazaar: true, trade: true, itemmarket: true,
        properties: true, auctionhouse: true, bookie: true, enlistedcars: true, loan: true,
        unpaidfees: true, points: true, factionMoney: true, company: true, extraStockShares: true
    };

    const savedSettings = localStorage.getItem(SETTINGS_KEY);
    if (savedSettings) settings = { ...settings, ...JSON.parse(savedSettings) };

    let investmentPreferences = {};
    INVESTMENT_TABLE.forEach((inv, index) => { investmentPreferences[index] = true; });

    let extraStockPreferences = {};
    const savedExtraStocks = localStorage.getItem(EXTRA_STOCKS_KEY);
    if (savedExtraStocks) extraStockPreferences = JSON.parse(savedExtraStocks);

    const savedInvestments = localStorage.getItem(INVESTMENTS_KEY);
    if (savedInvestments) investmentPreferences = { ...investmentPreferences, ...JSON.parse(savedInvestments) };

    async function checkAuthorization(apiKeyToCheck) {
    try {
        const userResponse = await fetch(`https://api.torn.com/v2/user?selections=&key=${apiKeyToCheck}`);
        const userData = await userResponse.json();

        console.log('User data:', userData); 

        if (userData.error) return { authorized: false, error: 'Invalid API key' };

        const userId = userData.profile.id.toString();
        console.log('User ID:', userId); 
        console.log('Checking URL:', `${WORKER_URL}?user_id=${userId}`); 

        const authResponse = await gmFetch(`${WORKER_URL}?user_id=${userId}`);
        const authData = await authResponse.json();

        console.log('Auth response:', authData); 

        if (!authData.authorized) {
            return { authorized: false, error: 'Something went wrong with your verification. Contact ShAdOwCrEsT [3929345].' };
        }
        return { authorized: true };
    } catch (error) {
        console.error('Authorization error:', error); 
        return { authorized: false, error: 'Authorization check failed' };
    }
}

    function formatMoney(amount) { return '$' + amount.toLocaleString('en-US'); }
    function saveApiKey(key) { localStorage.setItem(STORAGE_KEY, key); apiKey = key; }
    function clearApiKey() { localStorage.removeItem(STORAGE_KEY); apiKey = ''; }
    function saveSettings() { localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings)); }
    function saveInvestmentPreferences() { localStorage.setItem(INVESTMENTS_KEY, JSON.stringify(investmentPreferences)); }
    function saveExtraStockPreferences() { localStorage.setItem(EXTRA_STOCKS_KEY, JSON.stringify(extraStockPreferences)); }

    function createButton() {
        const isPDA = /android|iphone|ipad|mobile/i.test(navigator.userAgent.toLowerCase()) || window.innerWidth <= 768;
        const container = document.createElement('div');
        container.style.cssText = `position: fixed; top: ${isPDA ? '35px' : '50px'}; right: ${isPDA ? '10px' : '20px'}; z-index: 99999; display: flex; gap: ${isPDA ? '5px' : '10px'}; align-items: center;`;

        const toggleBtn = document.createElement('button');
        toggleBtn.innerHTML = '📊';
        toggleBtn.style.cssText = `padding: ${isPDA ? '8px 10px' : '10px 15px'}; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.3); font-size: ${isPDA ? '14px' : '16px'}; transition: all 0.3s ease;`;
        toggleBtn.onmouseover = () => { toggleBtn.style.transform = 'translateY(-2px)'; toggleBtn.style.boxShadow = '0 6px 8px rgba(0,0,0,0.4)'; };
        toggleBtn.onmouseout = () => { toggleBtn.style.transform = 'translateY(0)'; toggleBtn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.3)'; };

        const buttonsContainer = document.createElement('div');
        buttonsContainer.style.cssText = `display: none; gap: ${isPDA ? '5px' : '10px'};`;

        const button = document.createElement('button');
        button.innerHTML = '📊 Stock Advisor';
        button.style.cssText = `padding: ${isPDA ? '8px 12px' : '10px 20px'}; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.3); font-size: ${isPDA ? '12px' : '14px'}; transition: all 0.3s ease;`;
        button.onmouseover = () => { button.style.transform = 'translateY(-2px)'; button.style.boxShadow = '0 6px 8px rgba(0,0,0,0.4)'; };
        button.onmouseout = () => { button.style.transform = 'translateY(0)'; button.style.boxShadow = '0 4px 6px rgba(0,0,0,0.3)'; };
        button.onclick = calculateRecommendation;

        const settingsBtn = document.createElement('button');
        settingsBtn.innerHTML = '⚙️';
        settingsBtn.style.cssText = `padding: ${isPDA ? '8px 10px' : '10px 15px'}; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.3); font-size: ${isPDA ? '14px' : '16px'}; transition: all 0.3s ease;`;
        settingsBtn.onmouseover = () => { settingsBtn.style.transform = 'translateY(-2px)'; settingsBtn.style.boxShadow = '0 6px 8px rgba(0,0,0,0.4)'; };
        settingsBtn.onmouseout = () => { settingsBtn.style.transform = 'translateY(0)'; settingsBtn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.3)'; };
        settingsBtn.onclick = openSettings;

        buttonsContainer.appendChild(button);
        buttonsContainer.appendChild(settingsBtn);
        toggleBtn.onclick = () => {
            if (buttonsContainer.style.display === 'none') buttonsContainer.style.display = 'flex';
            else buttonsContainer.style.display = 'none';
        };

        container.appendChild(buttonsContainer);
        container.appendChild(toggleBtn);
        document.body.appendChild(container);
    }

   function showNotification(message, type = 'info') {
       const notification = document.createElement('div');
       notification.style.cssText = `position: fixed; top: 80px; right: 20px; z-index: 100000; padding: 20px 25px 20px 20px; background: ${type === 'error' ? '#e74c3c' : type === 'success' ? '#27ae60' : '#3498db'}; color: white; border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,0.3); max-width: 400px; font-size: 14px; line-height: 1.6; animation: slideIn 0.3s ease; display: flex; gap: 15px; align-items: flex-start;`;

       const messageDiv = document.createElement('div');
       messageDiv.innerHTML = message;
       messageDiv.style.cssText = `flex: 1;`;

       const closeBtn = document.createElement('button');
       closeBtn.innerHTML = '✕';
       closeBtn.style.cssText = `background: rgba(255,255,255,0.2); border: none; color: white; width: 24px; height: 24px; border-radius: 4px; cursor: pointer; font-size: 16px; line-height: 1; padding: 0; flex-shrink: 0; transition: background 0.2s;`;
       closeBtn.onmouseover = () => { closeBtn.style.background = 'rgba(255,255,255,0.3)'; };
       closeBtn.onmouseout = () => { closeBtn.style.background = 'rgba(255,255,255,0.2)'; };
       closeBtn.onclick = () => {
           notification.style.animation = 'slideIn 0.3s ease reverse';
           setTimeout(() => notification.remove(), 300);
       };

       notification.appendChild(messageDiv);
       notification.appendChild(closeBtn);

       const style = document.createElement('style');
       style.textContent = `@keyframes slideIn { from { transform: translateX(500px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }`;
       document.head.appendChild(style);
       document.body.appendChild(notification);

       setTimeout(() => {
           notification.style.animation = 'slideIn 0.3s ease reverse';
           setTimeout(() => notification.remove(), 300);
       }, 4000);
   }

    function openSettings() {
        const backdrop = document.createElement('div');
        backdrop.style.cssText = `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 100001; display: flex; justify-content: center; align-items: center;`;

        const modal = document.createElement('div');
        modal.style.cssText = `background: white; padding: 30px; border-radius: 15px; box-shadow: 0 10px 40px rgba(0,0,0,0.5); max-width: 500px; max-height: 80vh; overflow-y: auto;`;

        const title = document.createElement('h2');
        title.textContent = 'Settings';
        title.style.cssText = `margin: 0 0 20px 0; color: #333; font-size: 20px;`;
        modal.appendChild(title);

        const apiKeySection = document.createElement('div');
        apiKeySection.style.cssText = `margin-bottom: 25px; padding-bottom: 25px; border-bottom: 2px solid #eee;`;

        const apiKeyTitle = document.createElement('h3');
        apiKeyTitle.textContent = 'API Key';
        apiKeyTitle.style.cssText = `margin: 0 0 10px 0; color: #333; font-size: 16px;`;

        const apiKeyInput = document.createElement('input');
        apiKeyInput.type = 'text';
        apiKeyInput.value = apiKey;
        apiKeyInput.placeholder = 'Enter your Torn API key';
        apiKeyInput.style.cssText = `width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 8px; font-size: 14px; box-sizing: border-box;`;

        apiKeySection.appendChild(apiKeyTitle);
        apiKeySection.appendChild(apiKeyInput);
        modal.appendChild(apiKeySection);

        const balanceDistSection = document.createElement('div');
        balanceDistSection.style.cssText = `margin-bottom: 25px; padding-bottom: 25px; border-bottom: 2px solid #eee;`;

        const balanceDistBtn = document.createElement('button');
        balanceDistBtn.textContent = '💰 Balance Distribution ▼';
        balanceDistBtn.style.cssText = `width: 100%; padding: 12px; background: #3498db; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 14px; text-align: left;`;

        const balanceContent = document.createElement('div');
        balanceContent.id = 'balance_content';
        balanceContent.style.cssText = `display: none; margin-top: 10px; padding: 15px; background: #f5f5f5; border-radius: 8px; font-size: 13px;`;

        balanceDistBtn.onclick = async () => {
            if (balanceContent.style.display === 'none') {
                if (!apiKey) { alert('Please enter your API key first.'); return; }

                balanceContent.innerHTML = '<div style="text-align: center; color: #666;">Loading...</div>';
                balanceContent.style.display = 'block';
                balanceDistBtn.textContent = '💰 Balance Distribution ▲';

                const authResult = await checkAuthorization(apiKey);
                if (!authResult.authorized) {
                    balanceContent.innerHTML = `<div style="color: #e74c3c; text-align: center;">Error loading data. Please check your API key.</div>`;
                    return;
                }

                try {
                    const networthData = await fetchAPI(`https://api.torn.com/v2/user?selections=networth&key=${apiKey}`);
                    const nw = networthData.networth;

                    let html = '';
                    let totalBalance = 0;

                    const components = [
                        { key: 'pending', label: 'Pending', value: nw.pending || 0 },
                        { key: 'wallet', label: 'Wallet', value: nw.wallet || 0 },
                        { key: 'bank', label: 'Bank', value: nw.bank || 0 },
                        { key: 'cayman', label: 'Cayman', value: nw.cayman || 0 },
                        { key: 'vault', label: 'Vault', value: nw.vault || 0 },
                        { key: 'piggybank', label: 'Piggy Bank', value: nw.piggybank || 0 },
                        { key: 'items', label: 'Items', value: nw.items || 0 },
                        { key: 'displaycase', label: 'Display Case', value: nw.displaycase || 0 },
                        { key: 'bazaar', label: 'Bazaar', value: nw.bazaar || 0 },
                        { key: 'trade', label: 'Trade', value: nw.trade || 0 },
                        { key: 'itemmarket', label: 'Item Market', value: nw.itemmarket || 0 },
                        { key: 'properties', label: 'Properties', value: nw.properties || 0 },
                        { key: 'auctionhouse', label: 'Auction House', value: nw.auctionhouse || 0 },
                        { key: 'bookie', label: 'Bookie', value: nw.bookie || 0 },
                        { key: 'enlistedcars', label: 'Enlisted Cars', value: nw.enlistedcars || 0 },
                        { key: 'loan', label: 'Loan', value: nw.loan || 0 },
                        { key: 'unpaidfees', label: 'Unpaid Fees', value: nw.unpaidfees || 0 },
                        { key: 'points', label: 'Points', value: nw.points || 0 }
                    ];

                    components.forEach(comp => {
                        if (settings[comp.key] && comp.value !== 0) {
                            html += `<div style="margin-bottom: 5px; color: #333;"><strong>${comp.label}:</strong> ${formatMoney(comp.value)}</div>`;
                            totalBalance += comp.value;
                        }
                    });

                    if (settings.factionMoney || settings.company) {
                        const moneyData = await fetchAPI(`https://api.torn.com/v2/user/money?key=${apiKey}`);
                        if (settings.factionMoney) {
                            const factionMoney = moneyData.money.faction?.money || 0;
                            if (factionMoney !== 0) {
                                html += `<div style="margin-bottom: 5px; color: #333;"><strong>Faction Money:</strong> ${formatMoney(factionMoney)}</div>`;
                                totalBalance += factionMoney;
                            }
                        }
                        if (settings.company) {
                            const companyMoney = moneyData.money.company || 0;
                            if (companyMoney !== 0) {
                                html += `<div style="margin-bottom: 5px; color: #333;"><strong>Company Money:</strong> ${formatMoney(companyMoney)}</div>`;
                                totalBalance += companyMoney;
                            }
                        }
                    }

                    if (settings.extraStockShares) {
                        const stocksData = await fetchAPI(`https://api.torn.com/v2/user?selections=stocks&key=${apiKey}`);
                        const tornStocksData = await fetchAPI(`https://api.torn.com/v2/torn?selections=stocks&key=${apiKey}`);
                        let stockBreakdown = [];
                        let stockTotal = 0;

                        for (const [stockId, stockInfo] of Object.entries(stocksData.stocks || {})) {
                            const acronym = STOCK_MAP[stockId];
                            if (acronym) {
                                const currentPrice = tornStocksData.stocks[stockId]?.current_price || 0;
                                const baseRequirement = tornStocksData.stocks[stockId]?.benefit?.requirement || 0;

                                if (stockInfo.dividend || stockInfo.benefit) {
                                    let actualIncrement = 0;
                                    for (let i = 1; i <= 4; i++) {
                                        let sharesForIncrement = (i === 1) ? baseRequirement : (baseRequirement * Math.pow(2, i)) - baseRequirement;
                                        if (stockInfo.total_shares >= sharesForIncrement) actualIncrement = i;
                                        else break;
                                    }
                                    let totalSharesNeeded = (actualIncrement === 1) ? baseRequirement : (baseRequirement * Math.pow(2, actualIncrement)) - baseRequirement;
                                    const extraShares = stockInfo.total_shares - totalSharesNeeded;
                                    if (extraShares > 0 && extraStockPreferences[acronym] !== false) {
                                        const value = extraShares * currentPrice;
                                        stockBreakdown.push({ acronym, shares: extraShares, price: currentPrice, value });
                                        stockTotal += value;
                                    }
                                } else {
                                    if (extraStockPreferences[acronym] !== false) {
                                        const value = stockInfo.total_shares * currentPrice;
                                        stockBreakdown.push({ acronym, shares: stockInfo.total_shares, price: currentPrice, value });
                                        stockTotal += value;
                                    }
                                }
                            }
                        }

                        if (stockTotal > 0) {
                            html += `<div style="margin: 10px 0 5px 0; color: #333;"><strong>Extra Stock Shares:</strong> ${formatMoney(stockTotal)}<button id="stock_details_toggle" style="margin-left: 8px; padding: 2px 8px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 11px;">▼</button></div><div id="stock_details_content" style="display: none; margin-left: 15px; padding: 10px; background: white; border-radius: 6px; margin-top: 5px; font-size: 12px;">`;
                            stockBreakdown.forEach(stock => {
                                html += `<div style="margin-bottom: 4px; color: #333;">${stock.acronym}: ${stock.shares.toLocaleString()} × ${formatMoney(stock.price)} = ${formatMoney(stock.value)}</div>`;
                            });
                            html += `</div>`;
                            totalBalance += stockTotal;
                        }
                    }

                    html += `<div style="margin-top: 15px; padding-top: 10px; border-top: 2px solid #ddd; font-weight: bold; color: #333;">Total: ${formatMoney(totalBalance)}</div>`;
                    balanceContent.innerHTML = html;

                    const stockToggle = document.getElementById('stock_details_toggle');
                    if (stockToggle) {
                        stockToggle.onclick = () => {
                            const stockDetails = document.getElementById('stock_details_content');
                            if (stockDetails.style.display === 'none') {
                                stockDetails.style.display = 'block';
                                stockToggle.textContent = '▲';
                            } else {
                                stockDetails.style.display = 'none';
                                stockToggle.textContent = '▼';
                            }
                        };
                    }
                } catch (error) {
                    balanceContent.innerHTML = `<div style="color: #e74c3c;">Error: ${error.message}</div>`;
                }
            } else {
                balanceContent.style.display = 'none';
                balanceDistBtn.textContent = '💰 Balance Distribution ▼';
            }
        };

        balanceDistSection.appendChild(balanceDistBtn);
        balanceDistSection.appendChild(balanceContent);
        modal.appendChild(balanceDistSection);

        const balanceTitle = document.createElement('h3');
        balanceTitle.textContent = 'Balance Calculation';
        balanceTitle.style.cssText = `margin: 0 0 10px 0; color: #333; font-size: 16px;`;

        const description = document.createElement('p');
        description.textContent = 'Select which components to include in your balance calculation:';
        description.style.cssText = `margin: 0 0 15px 0; color: #666; font-size: 14px;`;

        modal.appendChild(balanceTitle);
        modal.appendChild(description);

        const settingsOptions = [
            { key: 'pending', label: 'Pending' }, { key: 'wallet', label: 'Wallet' }, { key: 'bank', label: 'Bank' },
            { key: 'cayman', label: 'Cayman' }, { key: 'vault', label: 'Vault' }, { key: 'piggybank', label: 'Piggy Bank' },
            { key: 'items', label: 'Items' }, { key: 'displaycase', label: 'Display Case' }, { key: 'bazaar', label: 'Bazaar' },
            { key: 'trade', label: 'Trade' }, { key: 'itemmarket', label: 'Item Market' }, { key: 'properties', label: 'Properties' },
            { key: 'auctionhouse', label: 'Auction House' }, { key: 'bookie', label: 'Bookie' }, { key: 'enlistedcars', label: 'Enlisted Cars' },
            { key: 'loan', label: 'Loan' }, { key: 'unpaidfees', label: 'Unpaid Fees' }, { key: 'points', label: 'Points' },
            { key: 'factionMoney', label: 'Faction Money' }, { key: 'company', label: 'Company Money' }, { key: 'extraStockShares', label: 'Extra Stock Shares' }
        ];

        settingsOptions.forEach(option => {
            const checkboxContainer = document.createElement('div');
            checkboxContainer.style.cssText = `margin-bottom: 12px; display: flex; align-items: center;`;

            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.id = `setting_${option.key}`;
            checkbox.checked = settings[option.key];
            checkbox.style.cssText = `width: 18px; height: 18px; cursor: pointer; margin-right: 10px;`;
            checkbox.onchange = (e) => {
                settings[option.key] = e.target.checked;
                if (option.key === 'extraStockShares') {
                    const btn = modal.querySelector('#config_stocks_btn');
                    if (btn) {
                        btn.style.display = e.target.checked ? 'block' : 'none';
                        if (!e.target.checked) {
                            const content = modal.querySelector('#config_stocks_content');
                            if (content) content.style.display = 'none';
                            btn.textContent = '🔧 Configure Stocks ▼';
                        }
                    }
                }
            };

            const label = document.createElement('label');
            label.htmlFor = `setting_${option.key}`;
            label.textContent = option.label;
            label.style.cssText = `color: #333; font-size: 14px; cursor: pointer;`;

            checkboxContainer.appendChild(checkbox);
            checkboxContainer.appendChild(label);
            modal.appendChild(checkboxContainer);

            if (option.key === 'extraStockShares') {
                const configStocksBtn = document.createElement('button');
                configStocksBtn.textContent = '🔧 Configure Stocks ▼';
                configStocksBtn.id = 'config_stocks_btn';
                configStocksBtn.style.cssText = `width: 100%; padding: 10px; background: #9b59b6; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; font-size: 13px; text-align: left; margin-top: 8px; margin-bottom: 12px; display: ${settings.extraStockShares ? 'block' : 'none'};`;

                const configStocksContent = document.createElement('div');
                configStocksContent.id = 'config_stocks_content';
                configStocksContent.style.cssText = `display: none; margin-top: 10px; margin-bottom: 12px; padding: 12px; background: #f9f9f9; border-radius: 6px; font-size: 13px; max-height: 250px; overflow-y: auto;`;

                configStocksBtn.onclick = async () => {
                    if (configStocksContent.style.display === 'none') {
                        if (!apiKey) { alert('Please enter your API key first.'); return; }

                        configStocksContent.innerHTML = '<div style="text-align: center; color: #666;">Loading stocks...</div>';
                        configStocksContent.style.display = 'block';
                        configStocksBtn.textContent = '🔧 Configure Stocks ▲';

                        try {
                            const stocksData = await fetchAPI(`https://api.torn.com/v2/user?selections=stocks&key=${apiKey}`);
                            const tornStocksData = await fetchAPI(`https://api.torn.com/v2/torn?selections=stocks&key=${apiKey}`);
                            let html = '';
                            let hasStocks = false;

                            for (const [stockId, stockInfo] of Object.entries(stocksData.stocks || {})) {
                                const acronym = STOCK_MAP[stockId];
                                if (acronym && stockInfo.total_shares > 0) {
                                    const currentPrice = tornStocksData.stocks[stockId]?.current_price || 0;
                                    const baseRequirement = tornStocksData.stocks[stockId]?.benefit?.requirement || 0;
                                    let extraShares = 0;
                                    let extraValue = 0;

                                    if (stockInfo.dividend || stockInfo.benefit) {
                                        let actualIncrement = 0;
                                        for (let i = 1; i <= 4; i++) {
                                            let sharesForIncrement = (i === 1) ? baseRequirement : (baseRequirement * Math.pow(2, i)) - baseRequirement;
                                            if (stockInfo.total_shares >= sharesForIncrement) actualIncrement = i;
                                            else break;
                                        }
                                        let totalSharesNeeded = (actualIncrement === 1) ? baseRequirement : (baseRequirement * Math.pow(2, actualIncrement)) - baseRequirement;
                                        extraShares = stockInfo.total_shares - totalSharesNeeded;
                                        extraValue = extraShares * currentPrice;
                                    } else {
                                        extraShares = stockInfo.total_shares;
                                        extraValue = extraShares * currentPrice;
                                    }

                                    if (extraShares > 0) {
                                        hasStocks = true;
                                        if (extraStockPreferences[acronym] === undefined) extraStockPreferences[acronym] = true;
                                        html += `<div style="margin-bottom: 10px; display: flex; align-items: center; padding: 8px; background: white; border-radius: 4px;"><input type="checkbox" id="extra_stock_${acronym}" ${extraStockPreferences[acronym] ? 'checked' : ''} style="width: 16px; height: 16px; cursor: pointer; margin-right: 10px; flex-shrink: 0;"><label for="extra_stock_${acronym}" style="color: #333; font-size: 13px; cursor: pointer; flex-grow: 1;"><strong>${acronym}</strong> - ${extraShares.toLocaleString()} shares (${formatMoney(extraValue)})</label></div>`;
                                    }
                                }
                            }

                            if (hasStocks) {
                                configStocksContent.innerHTML = html;
                                Object.keys(extraStockPreferences).forEach(acronym => {
                                    const cb = document.getElementById(`extra_stock_${acronym}`);
                                    if (cb) cb.onchange = (e) => { extraStockPreferences[acronym] = e.target.checked; };
                                });
                            } else {
                                configStocksContent.innerHTML = '<div style="text-align: center; color: #666;">No extra stock shares found.</div>';
                            }
                        } catch (error) {
                            configStocksContent.innerHTML = `<div style="color: #e74c3c;">Error: ${error.message}</div>`;
                        }
                    } else {
                        configStocksContent.style.display = 'none';
                        configStocksBtn.textContent = '🔧 Configure Stocks ▼';
                    }
                };

                checkboxContainer.appendChild(configStocksBtn);
                checkboxContainer.appendChild(configStocksContent);
            }
        });

        const investmentSection = document.createElement('div');
        investmentSection.style.cssText = `margin-top: 25px; padding-top: 25px; border-top: 2px solid #eee;`;

        const investmentTitle = document.createElement('h3');
        investmentTitle.textContent = 'Investment Rankings';
        investmentTitle.style.cssText = `margin: 0 0 10px 0; color: #333; font-size: 16px;`;

        const investmentDesc = document.createElement('p');
        investmentDesc.textContent = 'Select which investments you want to consider (in priority order):';
        investmentDesc.style.cssText = `margin: 0 0 15px 0; color: #666; font-size: 14px;`;

        investmentSection.appendChild(investmentTitle);
        investmentSection.appendChild(investmentDesc);

        const toggleButtonsContainer = document.createElement('div');
        toggleButtonsContainer.style.cssText = `margin-bottom: 15px; display: flex; gap: 10px;`;

        const selectAllBtn = document.createElement('button');
        selectAllBtn.textContent = 'Select All';
        selectAllBtn.style.cssText = `padding: 6px 12px; background: #3498db; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 12px;`;
        selectAllBtn.onclick = () => {
            INVESTMENT_TABLE.forEach((inv, index) => {
                investmentPreferences[index] = true;
                const checkbox = document.getElementById(`inv_${index}`);
                if (checkbox) checkbox.checked = true;
            });
        };

        const deselectAllBtn = document.createElement('button');
        deselectAllBtn.textContent = 'Deselect All';
        deselectAllBtn.style.cssText = `padding: 6px 12px; background: #95a5a6; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 12px;`;
        deselectAllBtn.onclick = () => {
            INVESTMENT_TABLE.forEach((inv, index) => {
                investmentPreferences[index] = false;
                const checkbox = document.getElementById(`inv_${index}`);
                if (checkbox) checkbox.checked = false;
            });
        };

        toggleButtonsContainer.appendChild(selectAllBtn);
        toggleButtonsContainer.appendChild(deselectAllBtn);
        investmentSection.appendChild(toggleButtonsContainer);

        const investmentList = document.createElement('div');
        investmentList.style.cssText = `max-height: 300px; overflow-y: auto; border: 1px solid #ddd; border-radius: 8px; padding: 10px; background: #f9f9f9;`;

        INVESTMENT_TABLE.forEach((investment, index) => {
            const invContainer = document.createElement('div');
            invContainer.style.cssText = `margin-bottom: 8px; display: flex; align-items: center; padding: 5px; background: white; border-radius: 4px;`;

            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.id = `inv_${index}`;
            checkbox.checked = investmentPreferences[index];
            checkbox.style.cssText = `width: 16px; height: 16px; cursor: pointer; margin-right: 10px; flex-shrink: 0;`;
            checkbox.onchange = (e) => { investmentPreferences[index] = e.target.checked; };

            const label = document.createElement('label');
            label.htmlFor = `inv_${index}`;
            label.textContent = `${index + 1}. ${investment.acronym} - Increment ${investment.increment} (${formatMoney(investment.cost)})`;
            label.style.cssText = `color: #333; font-size: 13px; cursor: pointer; flex-grow: 1;`;

            invContainer.appendChild(checkbox);
            invContainer.appendChild(label);
            investmentList.appendChild(invContainer);
        });

        investmentSection.appendChild(investmentList);
        modal.appendChild(investmentSection);

        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = `margin-top: 25px; display: flex; gap: 10px; justify-content: flex-end;`;

        const saveBtn = document.createElement('button');
        saveBtn.textContent = 'Save';
        saveBtn.style.cssText = `padding: 10px 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 14px;`;
        saveBtn.onclick = () => {
            const newKey = apiKeyInput.value.trim();
            if (newKey && newKey !== apiKey) saveApiKey(newKey);
            saveSettings();
            saveInvestmentPreferences();
            saveExtraStockPreferences();
            backdrop.remove();
            showNotification('Settings saved successfully!', 'success');
        };

        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = 'Cancel';
        cancelBtn.style.cssText = `padding: 10px 20px; background: #95a5a6; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer; font-size: 14px;`;
        cancelBtn.onclick = () => { backdrop.remove(); };

        buttonContainer.appendChild(cancelBtn);
        buttonContainer.appendChild(saveBtn);
        modal.appendChild(buttonContainer);

        backdrop.appendChild(modal);
        backdrop.onclick = (e) => { if (e.target === backdrop) backdrop.remove(); };
        document.body.appendChild(backdrop);
    }

    async function fetchAPI(url) {
        try {
            const response = await fetch(url);
            if (!response.ok) throw new Error('API request failed');
            return await response.json();
        } catch (error) {
            throw new Error(`Failed to fetch data: ${error.message}`);
        }
    }

    async function calculateRecommendation() {
        if (!apiKey) {
            const newKey = prompt('Enter your Limited or Full Access Torn API key:');
            if (!newKey) { showNotification('API key is required to calculate recommendations.', 'error'); return; }
            saveApiKey(newKey);
        }

        const authResult = await checkAuthorization(apiKey);
        if (!authResult.authorized) {
            showNotification(authResult.error, 'error');
            clearApiKey();
            return;
        }

        const savedInvestments = localStorage.getItem(INVESTMENTS_KEY);
        if (savedInvestments) investmentPreferences = { ...investmentPreferences, ...JSON.parse(savedInvestments) };

        showNotification('Calculating your next investment... Please wait.', 'info');

        try {
            const networthData = await fetchAPI(`https://api.torn.com/v2/user?selections=networth&key=${apiKey}`);
            const nw = networthData.networth;

            let balance = 0;
            if (settings.pending) balance += (nw.pending || 0);
            if (settings.wallet) balance += (nw.wallet || 0);
            if (settings.bank) balance += (nw.bank || 0);
            if (settings.cayman) balance += (nw.cayman || 0);
            if (settings.vault) balance += (nw.vault || 0);
            if (settings.piggybank) balance += (nw.piggybank || 0);
            if (settings.items) balance += (nw.items || 0);
            if (settings.displaycase) balance += (nw.displaycase || 0);
            if (settings.bazaar) balance += (nw.bazaar || 0);
            if (settings.trade) balance += (nw.trade || 0);
            if (settings.itemmarket) balance += (nw.itemmarket || 0);
            if (settings.properties) balance += (nw.properties || 0);
            if (settings.auctionhouse) balance += (nw.auctionhouse || 0);
            if (settings.bookie) balance += (nw.bookie || 0);
            if (settings.enlistedcars) balance += (nw.enlistedcars || 0);
            if (settings.loan) balance += (nw.loan || 0);
            if (settings.unpaidfees) balance += (nw.unpaidfees || 0);
            if (settings.points) balance += (nw.points || 0);

            if (settings.factionMoney || settings.company) {
                const moneyData = await fetchAPI(`https://api.torn.com/v2/user/money?key=${apiKey}`);
                if (settings.factionMoney) balance += (moneyData.money.faction?.money || 0);
                if (settings.company) balance += (moneyData.money.company || 0);
            }

            const stocksData = await fetchAPI(`https://api.torn.com/v2/user?selections=stocks&key=${apiKey}`);
            const tornStocksData = await fetchAPI(`https://api.torn.com/v2/torn?selections=stocks&key=${apiKey}`);

            const userStocks = {};
            let stockTotal = 0;

            for (const [stockId, stockInfo] of Object.entries(stocksData.stocks || {})) {
                const acronym = STOCK_MAP[stockId];
                if (acronym) {
                    const currentPrice = tornStocksData.stocks[stockId]?.current_price || 0;
                    const baseRequirement = tornStocksData.stocks[stockId]?.benefit?.requirement || 0;

                    if (stockInfo.dividend || stockInfo.benefit) {
                        let actualIncrement = 0;
                        for (let i = 1; i <= 4; i++) {
                            let sharesForIncrement = (i === 1) ? baseRequirement : (baseRequirement * Math.pow(2, i)) - baseRequirement;
                            if (stockInfo.total_shares >= sharesForIncrement) actualIncrement = i;
                            else break;
                        }
                        userStocks[acronym] = actualIncrement;

                        if (settings.extraStockShares) {
                            let totalSharesNeeded = (actualIncrement === 1) ? baseRequirement : (baseRequirement * Math.pow(2, actualIncrement)) - baseRequirement;
                            const extraShares = stockInfo.total_shares - totalSharesNeeded;
                            if (extraShares > 0 && extraStockPreferences[acronym] !== false) {
                                stockTotal += extraShares * currentPrice;
                            }
                        }
                    } else {
                        userStocks[acronym] = 0;
                        if (settings.extraStockShares && extraStockPreferences[acronym] !== false) {
                            stockTotal += stockInfo.total_shares * currentPrice;
                        }
                    }
                }
            }

            if (settings.extraStockShares) balance += stockTotal;

            let nextInvestment = null;
            for (let i = 0; i < INVESTMENT_TABLE.length; i++) {
                const investment = INVESTMENT_TABLE[i];
                if (!investmentPreferences[i]) continue;
                const currentIncrement = userStocks[investment.acronym] || 0;
                if (currentIncrement < investment.increment) {
                    nextInvestment = investment;
                    break;
                }
            }

            if (!nextInvestment) {
                showNotification('🎉 Congratulations! You have completed all recommended stock investments!', 'success');
                return;
            }

            const canAfford = balance >= nextInvestment.cost;
            const shortfall = canAfford ? 0 : nextInvestment.cost - balance;

            let message = `
                <div style="font-weight: bold; font-size: 16px; margin-bottom: 10px;">📈 Next Investment Recommendation</div>
                <div style="text-align: center; margin: 15px 0;">
                    <img src="${STOCK_IMAGES[nextInvestment.acronym]}" alt="${nextInvestment.acronym}" style="width: 80px; height: 80px; border-radius: 10px; background: rgba(255,255,255,0.1); padding: 10px;">
                </div>
                <div style="margin-bottom: 8px;"><strong>Stock:</strong> ${nextInvestment.acronym} (Increment ${nextInvestment.increment})</div>
                <div style="margin-bottom: 8px;"><strong>Cost:</strong> ${formatMoney(nextInvestment.cost)}</div>
                <div style="margin-bottom: 8px;"><strong>Your Balance:</strong> ${formatMoney(balance)}</div>
                <div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,0.3);">
                    ${canAfford ? `✅ <strong>You can invest now!</strong><br><a href="https://www.torn.com/page.php?sid=stocks&stockID=${Object.keys(STOCK_MAP).find(key => STOCK_MAP[key] === nextInvestment.acronym)}&tab=owned" style="color: white; text-decoration: underline; font-weight: bold;">Take me there!</a>` : `❌ You need ${formatMoney(shortfall)} more to invest.`}
                </div>
            `;

            showNotification(message, canAfford ? 'success' : 'info');
        } catch (error) {
            showNotification(`Error: ${error.message}<br><br>Please check your API key and try again.`, 'error');
            clearApiKey();
        }
    }

    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', createButton);
    else createButton();
})();