// ==UserScript==
// @name         GG.deals Steam Companion
// @namespace    http://tampermonkey.net/
// @version      1.5.1
// @description  Shows lowest price from gg.deals on Steam game pages
// @author       Crimsab
// @license      GPL-3.0-or-later
// @match        https://store.steampowered.com/app/*
// @match        https://store.steampowered.com/sub/*
// @match        https://store.steampowered.com/bundle/*
// @icon         https://gg.deals/favicon.ico
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        unsafeWindow
// @connect      gg.deals
// @grant        GM_setValue
// @grant        GM_getValue
// @downloadURL  https://raw.githubusercontent.com/Crimsab/ggdeals-steam-companion/main/userscript.user.js
// @updateURL    https://raw.githubusercontent.com/Crimsab/ggdeals-steam-companion/main/userscript.user.js
// ==/UserScript==

(function () {
  "use strict";

  GM_addStyle(`
        .gg-deals-container {
            background: #16202d !important;
            border-radius: 4px;
            padding: 15px;
            margin: 20px 0;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
            border: 1px solid #67c1f530;
            width: 100%;
            max-width: 100%;
            box-sizing: border-box;
            clear: both;
        }
        .gg-deals-container.compact {
            padding: 10px;
            margin: 10px 0;
        }
        .gg-deals-container.compact .gg-header,
        .gg-deals-container.compact .gg-attribution,
        .gg-deals-container.compact .gg-price-sections {
            display: none;
        }
        .gg-compact-row {
            display: none;
            align-items: center;
            gap: 15px;
            padding: 5px;
            flex-wrap: nowrap;
            min-width: 0;
        }
        .gg-deals-container.compact .gg-compact-row {
            display: flex;
        }
        .gg-compact-prices {
            display: flex;
            align-items: center;
            gap: 20px;
            flex: 1;
            min-width: 0;
            overflow: visible;
        }
        .gg-compact-price-item {
            display: flex;
            align-items: center;
            position: relative;
            gap: 8px;
            min-width: 0;
            flex-shrink: 1;
        }
        .gg-compact-price-item .gg-price-value {
            font-size: 18px;
        }
        .gg-price-value.best-price {
            color: #a4d007;
            position: relative;
            padding-top: 16px;
        }
        .gg-price-value.best-price:before {
            content: "✓ Best Price";
            position: absolute;
            right: 0;
            top: 0;
            font-size: 12px;
            opacity: 0.9;
            color: #a4d007;
            white-space: nowrap;
        }
        /* Hide the "Best Price" text in compact view */
        .gg-compact-price-item .gg-price-value.best-price {
            padding-top: 0;
        }
        .gg-compact-price-item .gg-price-value.best-price:before {
            display: none;
        }
        .gg-settings-dropdown {
            position: relative;
            display: inline-block;
        }
        .gg-settings-icon {
            cursor: pointer;
            padding: 5px;
            opacity: 0.7;
            transition: opacity 0.2s;
        }
        .gg-settings-icon:hover {
            opacity: 1;
        }
        .gg-settings-icon svg {
            width: 20px;
            height: 20px;
            fill: #67c1f5;
        }
        .gg-settings-content {
            display: none;
            position: absolute;
            right: 0;
            background: #16202d;
            min-width: 160px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
            border: 1px solid #67c1f530;
            border-radius: 4px;
            z-index: 1000;
            padding: 10px;
        }
        .gg-settings-content.show {
            display: block;
        }
        .gg-compact-controls {
            display: flex;
            align-items: center;
            gap: 10px;
            flex-shrink: 0;
        }
        .gg-tooltip {
            position: relative;
            display: inline-block;
        }
        .gg-tooltip:hover .gg-tooltip-text {
            visibility: visible;
            opacity: 1;
        }
        .gg-tooltip-text {
            visibility: hidden;
            opacity: 0;
            background-color: #16202d;
            color: #fff;
            text-align: center;
            padding: 5px 10px;
            border-radius: 4px;
            border: 1px solid #67c1f530;
            position: absolute;
            z-index: 1;
            bottom: 125%;
            left: 50%;
            transform: translateX(-50%);
            white-space: nowrap;
            transition: opacity 0.2s;
            font-size: 12px;
        }
        /* New historical tooltip styles */
        .gg-historical-tooltip {
            position: relative;
            display: inline-block;
        }
        .gg-historical-tooltip:hover .gg-historical-tooltip-text {
            visibility: visible;
            opacity: 1;
        }
        .gg-historical-tooltip-text {
            visibility: hidden;
            opacity: 0;
            background-color: #16202d;
            color: #fff;
            text-align: center;
            padding: 5px 10px;
            border-radius: 4px;
            border: 1px solid #67c1f530;
            position: absolute;
            z-index: 1;
            bottom: 125%;
            left: 50%;
            transform: translateX(-50%);
            white-space: nowrap;
            transition: opacity 0.2s;
            font-size: 12px;
        }
        .gg-controls {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-top: 10px;
            padding-top: 10px;
            border-top: 1px solid rgba(103, 193, 245, 0.1);
        }
        .gg-header {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin: -15px -15px 15px -15px;
            padding: 15px;
            background:rgb(13, 20, 28);
            border-radius: 4px 4px 0 0;
            border-bottom: 1px solid rgba(103, 193, 245, 0.2);
            text-align: center;
        }
        .gg-title {
            color: #67c1f5;
            font-size: 24px;
            font-weight: bold;
            text-transform: uppercase;
            letter-spacing: 1px;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
            display: flex;
            align-items: center;
            gap: 12px;
        }
        .gg-title img {
            width: 32px;
            height: 32px;
            filter: brightness(1.2) drop-shadow(1px 1px 2px rgba(0,0,0,0.5));
        }
        .gg-attribution {
            color: #8f98a0;
            font-size: 11px;
            opacity: 0.8;
            font-style: italic;
            text-align: center;
            margin-top: 12px;
            padding-top: 12px;
            border-top: 1px solid rgba(103, 193, 245, 0.1);
        }
        .gg-price-sections {
            display: flex;
            justify-content: space-between;
            margin: 8px 0;
            padding: 12px;
            background: #1b2838;
            border-radius: 3px;
            transition: all 0.3s ease;
            position: relative;
            min-height: 60px;
        }
        .gg-price-section {
            display: flex;
            flex-direction: column;
            gap: 4px;
            flex: 1;
            min-width: 0;
        }
        .gg-price-left {
            display: flex;
            align-items: center;
            justify-content: center;
            flex: 1;
        }
        .gg-price-label {
            color: #67c1f5;
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 8px;
            white-space: nowrap;
        }
        .gg-price-info {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-width: 120px;
            text-align: center;
            margin-left: 20px;
        }
        .gg-price-value {
            color: #fff;
            font-weight: bold;
            font-size: 24px;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
            transition: color 0.3s ease;
            white-space: nowrap;
        }
        .gg-price-value.historical {
            font-size: 13px;
            color: #acdbf5;
            opacity: 0.9;
            margin-top: 4px;
        }
        .gg-icon {
            width: 20px;
            height: 20px;
            filter: brightness(0.8);
            flex-shrink: 0;
        }
        .gg-footer {
            margin-top: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 10px;
        }
        .gg-view-offers {
            width: 100%;
            background: linear-gradient(to right, #67c1f5 0%, #4a9bd5 100%);
            padding: 8px 20px;
            border-radius: 3px;
            color: #fff !important;
            font-size: 14px;
            text-decoration: none !important;
            transition: all 0.2s ease;
            text-shadow: 1px 1px 1px rgba(0,0,0,0.3);
            text-align: center;
            white-space: nowrap;
        }
        .gg-view-offers:hover {
            background: linear-gradient(to right, #7dcbff 0%, #4a9bd5 100%);
            transform: translateY(-1px);
        }
        .gg-toggles {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }
        .gg-toggle {
            display: flex;
            align-items: center;
            gap: 5px;
            cursor: pointer;
            user-select: none;
            opacity: 0.7;
            transition: opacity 0.2s ease;
            white-space: nowrap;
            color: #67c1f5;
        }
        .gg-toggle:hover {
            opacity: 1;
        }
        .gg-toggle.active {
            opacity: 1;
        }
        .gg-toggle input {
            margin: 0;
        }
        .gg-toggle label {
            color: #67c1f5;
            font-size: 12px;
        }

        @media (max-width: 640px) {
            .gg-price-sections {
                flex-direction: column;
                align-items: stretch;
                gap: 10px;
            }
            .gg-price-info {
                align-items: flex-start;
                margin-left: 28px;
            }
            .gg-price-value.best-price {
                padding-top: 0;
                padding-right: 80px;
            }
            .gg-price-value.best-price:before {
                top: 50%;
                transform: translateY(-50%);
                right: 0;
            }
            .gg-footer {
                flex-direction: column-reverse;
                align-items: stretch;
            }
            .gg-view-offers {
                text-align: center;
            }
            .gg-toggles {
                justify-content: center;
            }
        }

        .gg-icon-button {
            background: none;
            border: none;
            color: #67c1f5;
            cursor: pointer;
            padding: 5px;
            border-radius: 3px;
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 12px;
            opacity: 0.7;
            transition: all 0.2s ease;
        }
        .gg-icon-button:hover {
            opacity: 1;
            background: rgba(103, 193, 245, 0.1);
        }
        .gg-icon-button svg {
            width: 20px;
            height: 20px;
            fill: currentColor;
        }
        .gg-refresh {
            padding: 5px 8px;
            display: flex;
            align-items: center;
            min-width: max-content;
            flex-shrink: 0;
            position: relative;
        }
        .gg-refresh svg {
            transition: transform 0.5s ease;
            stroke: currentColor;
            fill: none;
        }
        .gg-refresh.loading svg {
            transform: rotate(360deg);
        }
        .gg-refresh-text {
            display: none;
        }
        .gg-refresh:hover .gg-tooltip-text {
            visibility: visible;
            opacity: 1;
        }

        .github-icon {
            width: 16px;
            height: 16px;
            vertical-align: middle;
            margin: -2px 4px 0 2px;
            opacity: 0.8;
            transition: opacity 0.2s ease;
        }
        .github-icon:hover {
            opacity: 1;
        }
        .gg-deals-container.compact .gg-controls {
            display: none;
        }
        .bundle-sub-display {
            background: #16202d !important;
            border-radius: 4px;
            border: 1px solid #67c1f530;
            position: relative;
            z-index: 1;
        }
        .game_area_purchase_game_wrapper + .bundle-sub-display {
            margin-top: -10px !important;
        }
        .bundle_contents_preview + .gg-deals-container {
            margin-top: 0 !important;
        }
        .game_area_purchase + .gg-deals-container {
            margin-top: 0 !important;
        }
        .gg-view-offers {
            display: inline-block;
            text-align: center;
            transition: transform 0.2s ease;
        }
        .gg-view-offers:hover {
            transform: translateY(-1px);
        }
        .gg-price-value {
            display: inline-block;
            min-width: 80px;
        }
        .gg-deals-container.compact .gg-view-offers {
            width: auto;
            min-width: 90px;
            white-space: nowrap;
            flex-shrink: 0;
        }
    `);

  // Get saved toggle states or set defaults
  const toggleStates = {
    official: GM_getValue("showOfficial", true),
    keyshop: GM_getValue("showKeyshop", true),
    compact: GM_getValue("compactView", false),
    subDisplay: GM_getValue("showSubDisplay", true)
  };

  // Cache configuration
  const CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours
  const RATE_LIMIT_DELAY = 2000; // 2 seconds between requests
  const MAX_RETRIES = 1;

  // Cache structure with force refresh option
  const priceCache = {
    get: function (key, forceRefresh = false) {
      if (forceRefresh) {
        GM_setValue(`cache_${key}`, "");
        return null;
      }

      const cached = GM_getValue(`cache_${key}`);
      if (!cached) return null;

      const { data, timestamp } = JSON.parse(cached);
      if (Date.now() - timestamp > CACHE_EXPIRY) {
        GM_setValue(`cache_${key}`, "");
        return null;
      }
      return data;
    },
    set: function (key, data) {
      const cacheData = {
        data: data,
        timestamp: Date.now(),
      };
      GM_setValue(`cache_${key}`, JSON.stringify(cacheData));
    },
    getTimestamp: function (key) {
      const cached = GM_getValue(`cache_${key}`);
      if (!cached) return null;
      return JSON.parse(cached).timestamp;
    },
  };

  // Rate limiter with cross-tab synchronization
  async function rateLimitedRequest(url) {
    const now = Date.now();
    const lastRequest = GM_getValue("lastRequestTime", 0);
    const timeToWait = Math.max(0, RATE_LIMIT_DELAY - (now - lastRequest));

    if (timeToWait > 0) {
      await new Promise((resolve) => setTimeout(resolve, timeToWait));
    }

    GM_setValue("lastRequestTime", Date.now());

    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: "GET",
        url: url,
        timeout: 10000,
        onload: resolve,
        onerror: reject,
        ontimeout: reject,
      });
    });
  }

  function createPriceContainer() {
    const container = document.createElement("div");
    // Get the saved compact state
    const isCompact = GM_getValue("compactView", false);
    container.className = "gg-deals-container" + (isCompact ? " compact" : "");
    container.innerHTML = `
            <div class="gg-header">
                <div class="gg-title">
                    <img src="https://gg.deals/favicon.ico" alt="GG.deals">
                    GG.deals Steam Companion
                </div>
            </div>
            <div class="gg-compact-row">
                <img src="https://gg.deals/favicon.ico" alt="GG.deals" class="gg-icon">
                <div class="gg-compact-prices">
                    <div class="gg-compact-price-item" id="gg-compact-official" style="${
                      !toggleStates.official ? "display:none" : ""
                    }">
                        <span>Official:</span>
                        <span class="gg-historical-tooltip">
                            <span class="gg-price-value" id="gg-compact-official-price">Loading...</span>
                            <span class="gg-historical-tooltip-text" id="gg-compact-official-historical"></span>
                        </span>
                    </div>
                    <div class="gg-compact-price-item" id="gg-compact-keyshop" style="${
                      !toggleStates.keyshop ? "display:none" : ""
                    }">
                        <span>Keyshop:</span>
                        <span class="gg-historical-tooltip">
                            <span class="gg-price-value" id="gg-compact-keyshop-price">Loading...</span>
                            <span class="gg-historical-tooltip-text" id="gg-compact-keyshop-historical"></span>
                        </span>
                    </div>
                </div>
                <div class="gg-compact-controls">
                    <button class="gg-icon-button gg-refresh" title="Refresh Prices">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
                        </svg>
                        <span class="gg-tooltip-text">Click to refresh prices</span>
                    </button>
                    <div class="gg-settings-dropdown">
                        <div class="gg-icon-button gg-settings-icon">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M12 15.5A3.5 3.5 0 0 1 8.5 12 3.5 3.5 0 0 1 12 8.5a3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c.04-.32.07-.64.07-.97 0-.33-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.65.07.97l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65z"/>
                            </svg>
                        </div>
                        <div class="gg-settings-content">
                            <label class="gg-toggle ${toggleStates.official ? "active" : ""}" title="Toggle Official Stores">
                                <input type="checkbox" id="gg-toggle-official-compact" ${toggleStates.official ? "checked" : ""}>
                                <label>Official</label>
                            </label>
                            <label class="gg-toggle ${toggleStates.keyshop ? "active" : ""}" title="Toggle Keyshops">
                                <input type="checkbox" id="gg-toggle-keyshop-compact" ${toggleStates.keyshop ? "checked" : ""}>
                                <label>Keyshops</label>
                            </label>
                            <label class="gg-toggle ${toggleStates.compact ? "active" : ""}" title="Toggle Compact View">
                                <input type="checkbox" id="gg-toggle-compact-menu" ${toggleStates.compact ? "checked" : ""}>
                                <label>Compact</label>
                            </label>
                            <label class="gg-toggle ${toggleStates.subDisplay ? "active" : ""}" title="Toggle Sub/Bundle Displays">
                                <input type="checkbox" id="gg-toggle-sub-display-compact" ${toggleStates.subDisplay ? "checked" : ""}>
                                <label>Bundle Display</label>
                            </label>
                        </div>
                    </div>
                    <a href="#" target="_blank" class="gg-view-offers">View Offers</a>
                </div>
            </div>
            <div class="gg-price-sections">
                <div class="gg-price-section ${
                  toggleStates.official ? "" : "hidden"
                }" id="gg-official-section">
                    <div class="gg-price-left">
                        <span class="gg-price-label">
                            <img src="https://gg.deals/favicon.ico" class="gg-icon">
                            Official Stores
                        </span>
                    </div>
                    <div class="gg-price-info">
                        <span class="gg-price-value" id="gg-official-price">Loading...</span>
                        <span class="gg-price-value historical" id="gg-official-historical"></span>
                    </div>
                </div>
                <div class="gg-price-section ${
                  toggleStates.keyshop ? "" : "hidden"
                }" id="gg-keyshop-section">
                    <div class="gg-price-left">
                        <span class="gg-price-label">
                            <img src="https://gg.deals/favicon.ico" class="gg-icon">
                            Keyshops
                        </span>
                    </div>
                    <div class="gg-price-info">
                        <span class="gg-price-value" id="gg-keyshop-price">Loading...</span>
                        <span class="gg-price-value historical" id="gg-keyshop-historical"></span>
                    </div>
                </div>
            </div>
            <div class="gg-controls">
                <label class="gg-toggle ${toggleStates.official ? "active" : ""}" title="Toggle Official Stores">
                    <input type="checkbox" id="gg-toggle-official" ${toggleStates.official ? "checked" : ""}>
                    <label>Official</label>
                </label>
                <label class="gg-toggle ${toggleStates.keyshop ? "active" : ""}" title="Toggle Keyshops">
                    <input type="checkbox" id="gg-toggle-keyshop" ${toggleStates.keyshop ? "checked" : ""}>
                    <label>Keyshops</label>
                </label>
                <label class="gg-toggle ${toggleStates.compact ? "active" : ""}" title="Toggle Compact View">
                    <input type="checkbox" id="gg-toggle-compact" ${toggleStates.compact ? "checked" : ""}>
                    <label>Compact</label>
                </label>
                <label class="gg-toggle ${toggleStates.subDisplay ? "active" : ""}" title="Toggle Sub/Bundle Displays">
                    <input type="checkbox" id="gg-toggle-sub-display" ${toggleStates.subDisplay ? "checked" : ""}>
                    <label>Bundle Display</label>
                </label>
                <button class="gg-icon-button gg-refresh" title="Refresh Prices">
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
                    </svg>
                    <span class="gg-tooltip-text">Click to refresh prices</span>
                </button>
                <a href="#" target="_blank" class="gg-view-offers">View Offers</a>
            </div>
            <div class="gg-attribution">Extension by <a href="https://steamcommunity.com/profiles/76561199186030286">Crimsab</a> <a href="https://github.com/Crimsab/ggdeals-steam-companion" title="View on GitHub"><svg class="github-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg></a> · Data by <a href="https://gg.deals">gg.deals</a></div>
        `;

    // Add toggle listeners for both sets of controls
    const toggleOfficialCompact = container.querySelector(
      "#gg-toggle-official-compact"
    );
    const toggleKeyshopCompact = container.querySelector(
      "#gg-toggle-keyshop-compact"
    );
    const toggleCompactMenu = container.querySelector(
      "#gg-toggle-compact-menu"
    );
    const toggleOfficial = container.querySelector("#gg-toggle-official");
    const toggleKeyshop = container.querySelector("#gg-toggle-keyshop");
    const toggleCompact = container.querySelector("#gg-toggle-compact");
    const toggleSubDisplay = container.querySelector("#gg-toggle-sub-display");

    function updateToggleState(type, checked) {
      toggleStates[type] = checked;
      if (type === "compact") {
        GM_setValue("compactView", checked);
      } else {
        GM_setValue(`show${type.charAt(0).toUpperCase() + type.slice(1)}`, checked);
      }

      if (type === "official" || type === "keyshop") {
        container.querySelector(`#gg-compact-${type}`).style.display = checked
          ? ""
          : "none";
        container
          .querySelector(`#gg-${type}-section`)
          .classList.toggle("hidden", !checked);
      } else if (type === "compact") {
        // Update all containers on the page, preserving sub-display containers
        document.querySelectorAll('.gg-deals-container').forEach(cont => {
          // Skip sub-display containers if we're switching to full view
          if (!checked && cont.classList.contains('bundle-sub-display')) {
            return;
          }
          cont.classList.toggle("compact", checked);
        });
      } else if (type === "subDisplay") {
        document.querySelectorAll('.gg-deals-container.bundle-sub-display').forEach(el => {
          el.style.display = checked ? "" : "none";
        });
      }

      // Update all related toggle buttons
      container.querySelectorAll(`input[id*=toggle-${type}]`).forEach((input) => {
        input.checked = checked;
        input.closest(".gg-toggle").classList.toggle("active", checked);
      });
    }

    // Add event listeners for all toggles
    [toggleOfficialCompact, toggleOfficial].forEach((toggle) => {
      if (toggle) {
        toggle.addEventListener("change", (e) =>
          updateToggleState("official", e.target.checked)
        );
      }
    });

    [toggleKeyshopCompact, toggleKeyshop].forEach((toggle) => {
      if (toggle) {
        toggle.addEventListener("change", (e) =>
          updateToggleState("keyshop", e.target.checked)
        );
      }
    });

    [toggleCompactMenu, toggleCompact].forEach((toggle) => {
      if (toggle) {
        toggle.addEventListener("change", (e) =>
          updateToggleState("compact", e.target.checked)
        );
      }
    });

    const toggleSubDisplayCompact = container.querySelector("#gg-toggle-sub-display-compact");
    [toggleSubDisplay, toggleSubDisplayCompact].forEach((toggle) => {
      if (toggle) {
        toggle.addEventListener("change", (e) => updateToggleState("subDisplay", e.target.checked));
      }
    });

    // Add refresh button listeners to both compact and full view buttons
    container.querySelectorAll(".gg-refresh").forEach(refreshButton => {
      const refreshText = refreshButton.querySelector(".gg-tooltip-text");
      refreshButton.addEventListener("click", async function () {
        refreshButton.classList.add("loading");
        refreshButton.disabled = true;

        try {
          const urlMatch = window.location.pathname.match(/\/(app|sub|bundle)\/(\d+)/);
          if (urlMatch) {
            const [, type, id] = urlMatch;
            await fetchGamePrices(null, container.id, true, { type, id });
            refreshText.textContent = "Updated just now";
            setTimeout(() => {
              refreshText.textContent = "";
            }, 3000);
          }
        } catch (error) {
          console.error("Failed to refresh prices:", error);
          refreshText.textContent = "Refresh failed";
          setTimeout(() => {
            refreshText.textContent = "";
          }, 3000);
        } finally {
          refreshButton.classList.remove("loading");
          refreshButton.disabled = false;
        }
      });
    });

    // Add settings dropdown toggle
    const settingsIcon = container.querySelector(".gg-settings-icon");
    const settingsContent = container.querySelector(".gg-settings-content");

    settingsIcon.addEventListener("click", (e) => {
      e.stopPropagation();
      settingsContent.classList.toggle("show");
    });

    // Close settings dropdown when clicking outside
    document.addEventListener("click", (e) => {
      if (!settingsContent.contains(e.target) && !settingsIcon.contains(e.target)) {
        settingsContent.classList.remove("show");
      }
    });

    // Update last refresh time if cached data exists
    const urlMatch = window.location.pathname.match(/\/(app|sub|bundle)\/(\d+)/);
    if (urlMatch) {
      const [, type, id] = urlMatch;
      const timestamp = priceCache.getTimestamp(`${type}_${id}`);
      if (timestamp) {
        // Update all refresh tooltips with the timestamp
        container.querySelectorAll('.gg-refresh').forEach(refreshButton => {
          const tooltipSpan = refreshButton.querySelector('.gg-tooltip-text');
          if (tooltipSpan) {
            const timeAgo = Math.floor((Date.now() - timestamp) / 60000); // minutes
            if (timeAgo < 60) {
              tooltipSpan.textContent = `Updated ${timeAgo}m ago`;
            } else {
              const hoursAgo = Math.floor(timeAgo / 60);
              tooltipSpan.textContent = `Updated ${hoursAgo}h ago`;
            }
          }
        });
      }
    }

    return container;
  }

  // Improved error handling and retries
  async function fetchWithRetry(url, retries = MAX_RETRIES) {
    try {
      const response = await rateLimitedRequest(url);
      if (response.status === 200) {
        return response;
      }
      throw new Error(`HTTP ${response.status}`);
    } catch (error) {
      if (retries > 0) {
        await new Promise((resolve) => setTimeout(resolve, 1000));
        return fetchWithRetry(url, retries - 1);
      }
      throw error;
    }
  }

  async function fetchGamePrices(gameTitle, containerId, forceRefresh = false, idInfo = null) {
    let type, id;

    if (idInfo) {
        type = idInfo.type;
        id = idInfo.id;
    } else {
        // First try to get ID from the container itself
        const container = document.getElementById(containerId);
        if (container) {
            const purchaseGame = container.closest('.game_area_purchase_game');
            if (purchaseGame) {
                const bundleInput = purchaseGame.querySelector('input[name="bundleid"]');
                const subInput = purchaseGame.querySelector('input[name="subid"]');
                if (bundleInput) {
                    type = 'bundle';
                    id = bundleInput.value;
                } else if (subInput) {
                    type = 'sub';
                    id = subInput.value;
                }
            }
        }

        // If no ID found from container, try URL
        if (!type || !id) {
            const urlMatch = window.location.pathname.match(/\/(app|sub|bundle)\/(\d+)/);
            if (!urlMatch) {
                console.warn("GG.deals: Could not find Steam ID");
                return;
            }
            [, type, id] = urlMatch;
        }
    }

    const cacheKey = `${type}_${id}`;
    const cachedData = priceCache.get(cacheKey, forceRefresh);

    if (cachedData) {
        updatePriceDisplay(cachedData, containerId);
        return;
    }

    // If forcing refresh, clear cache for all containers on the page
    if (forceRefresh) {
        document.querySelectorAll('.gg-deals-container').forEach(container => {
            if (container.id && container.id !== containerId) {
                const match = container.id.match(/gg-deals-(app|sub|bundle)-(\d+)/);
                if (match) {
                    const [, containerType, containerId] = match;
                    priceCache.get(`${containerType}_${containerId}`, true);
                }
            }
        });
    }

    // Function to convert game name to URL slug
    const toUrlSlug = (name) => {
        return name.toLowerCase()
            .replace(/[^a-z0-9]+/g, '-')
            .replace(/^-+|-+$/g, '');
    };

    // Define base URL formats
    const baseFormats = [
        { type: type, id: id },  // Try original type first
        { type: 'sub', id: id }, // Try sub if original was app
        { type: 'app', id: id }  // Try app if original was sub
    ];

    // Filter unique formats
    const urlFormats = baseFormats.filter((format, index) => 
        format.type === type || 
        baseFormats.findIndex(f => f.type === format.type) === index
    );

    // Try each URL format
    for (const format of urlFormats) {
        try {
            const steamUrl = `https://gg.deals/steam/${format.type}/${format.id}/`;
            const response = await fetchWithRetry(steamUrl);
            const data = extractPriceData(response.responseText);
            if (data && data.officialPrice !== "No data") {
                priceCache.set(cacheKey, data);
                updatePriceDisplay(data, containerId);
                return;
            }
        } catch (error) {
            console.warn(`GG.deals ${format.type} URL fetch failed:`, error);
        }
    }

    // If the direct Steam URL didn't work, just show No data
    // Don't try game name based URL anymore
    updatePriceDisplay({
        officialPrice: "No data",
        keyshopPrice: "No data",
        historicalData: [],
        lowestPriceType: null,
        url: `https://gg.deals/steam/${type}/${id}/`,
        isCorrectGame: true
    }, containerId);
  }

  function extractPriceData(html, expectedGameName) {
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, "text/html");

    // Get the actual game name from the page
    const pageGameName = doc.querySelector('.game-info-title')?.textContent?.trim() ||
                        doc.querySelector('.game-header-title')?.textContent?.trim();

    // Check if we got the correct game
    const isCorrectGame = !expectedGameName || !pageGameName || 
                         pageGameName.toLowerCase().includes(expectedGameName.toLowerCase()) ||
                         expectedGameName.toLowerCase().includes(pageGameName.toLowerCase());

    // Check if it's a valid game page
    if (!doc.querySelector('.game-info-price-col')) {
        return {
            officialPrice: "No data",
            keyshopPrice: "No data",
            historicalData: [],
            lowestPriceType: null,
            url: doc.querySelector('link[rel="canonical"]')?.href || "https://gg.deals",
            isCorrectGame
        };
    }

    // Find current prices (non-historical)
    let officialPrice = "No data";
    let keyshopPrice = "No data";

    // Look for current prices in the main price sections (not historical)
    const currentPriceSections = Array.from(doc.querySelectorAll('.game-info-price-col')).filter(
      section => !section.classList.contains('historical')
    );

    currentPriceSections.forEach(section => {
      const label = section.querySelector('.game-info-price-label')?.textContent.trim();
      const price = section.querySelector('.price-inner.numeric')?.textContent.trim();
      
      if (label?.includes('Official Stores')) {
        officialPrice = price || "No data";
      } else if (label?.includes('Keyshops')) {
        keyshopPrice = price || "No data";
      }
    });

    // Historical lows (separate section)
    const historicalPrices = doc.querySelectorAll(
      ".game-info-price-col.historical.game-header-price-box"
    );
    const historicalData = [];
    historicalPrices.forEach((priceBox) => {
      const label = priceBox
        .querySelector(".game-info-price-label")
        ?.textContent.trim();
      const price = priceBox
        .querySelector(".price-inner.numeric")
        ?.textContent.trim();
      let date = priceBox
        .querySelector(".game-price-active-label")
        ?.textContent.trim();
      date = date?.replace("Expired", "").trim();

      if (!price || !date) return;

      const historicalText = `Historical Low: ${price} (${date})`;

      if (label?.includes("Official Stores Low")) {
        historicalData.push({
          type: "official",
          price: price,
          historical: historicalText,
        });
      } else if (label?.includes("Keyshops Low") && keyshopPrice !== "No data") {
        historicalData.push({
          type: "keyshop",
          price: price,
          historical: historicalText,
        });
      }
    });

    // Compare current prices (not historical) to determine the lowest
    const officialPriceNum = parseFloat(
      officialPrice.replace(/[^0-9,.]/g, "").replace(",", ".")
    );
    const keyshopPriceNum = parseFloat(
      keyshopPrice.replace(/[^0-9,.]/g, "").replace(",", ".")
    );

    let lowestPriceType = null;
    if (!isNaN(officialPriceNum) && !isNaN(keyshopPriceNum)) {
      lowestPriceType =
        officialPriceNum <= keyshopPriceNum ? "official" : "keyshop";
    } else if (!isNaN(officialPriceNum)) {
      lowestPriceType = "official";
    } else if (!isNaN(keyshopPriceNum)) {
      lowestPriceType = "keyshop";
    }

    // Get the current URL for the "View Offers" link
    const currentUrl = doc.querySelector('link[rel="canonical"]')?.href || "https://gg.deals";

    return {
      officialPrice: officialPrice,
      keyshopPrice: keyshopPrice,
      historicalData: historicalData,
      lowestPriceType: lowestPriceType,
      url: currentUrl,
      isCorrectGame
    };
  }

  function updatePriceDisplay(data, containerId) {
    const container = document.getElementById(containerId);
    if (!container) return;

    // Update all View Offers links in the container
    const links = container.querySelectorAll(".gg-view-offers");

    if (data) {
        // Update prices based on container type
        if (container.classList.contains('bundle-sub-display')) {
            // Update compact display
            const officialPrice = container.querySelector('.gg-compact-official-price');
            const keyshopPrice = container.querySelector('.gg-compact-keyshop-price');
            const officialHistorical = container.querySelector('.gg-compact-official-historical');
            const keyshopHistorical = container.querySelector('.gg-compact-keyshop-historical');

            if (officialPrice) officialPrice.textContent = data.officialPrice;
            if (keyshopPrice) keyshopPrice.textContent = data.keyshopPrice;

            // Show historical data regardless of current price status
            if (officialHistorical) {
                const officialHistData = data.historicalData.find(h => h.type === 'official');
                officialHistorical.textContent = officialHistData?.historical || '';
            }
            if (keyshopHistorical) {
                const keyshopHistData = data.historicalData.find(h => h.type === 'keyshop');
                keyshopHistorical.textContent = keyshopHistData?.historical || '';
            }

            // Update best price indicators
            if (officialPrice) officialPrice.classList.remove('best-price');
            if (keyshopPrice) keyshopPrice.classList.remove('best-price');

            if (data.lowestPriceType === 'official' && officialPrice) {
                officialPrice.classList.add('best-price');
            } else if (data.lowestPriceType === 'keyshop' && keyshopPrice) {
                keyshopPrice.classList.add('best-price');
            }
        } else {
            // Update full display
            const elements = {
                official: {
                    price: container.querySelector("#gg-official-price"),
                    historical: container.querySelector("#gg-official-historical"),
                    compactPrice: container.querySelector("#gg-compact-official-price"),
                    compactHistorical: container.querySelector("#gg-compact-official-historical")
                },
                keyshop: {
                    price: container.querySelector("#gg-keyshop-price"),
                    historical: container.querySelector("#gg-keyshop-historical"),
                    compactPrice: container.querySelector("#gg-compact-keyshop-price"),
                    compactHistorical: container.querySelector("#gg-compact-keyshop-historical")
                }
            };

            // Update prices
            if (elements.official.price) elements.official.price.textContent = data.officialPrice;
            if (elements.keyshop.price) elements.keyshop.price.textContent = data.keyshopPrice;
            if (elements.official.compactPrice) elements.official.compactPrice.textContent = data.officialPrice;
            if (elements.keyshop.compactPrice) elements.keyshop.compactPrice.textContent = data.keyshopPrice;

            // Update historical data regardless of current price status
            const officialHistData = data.historicalData.find(h => h.type === 'official');
            const keyshopHistData = data.historicalData.find(h => h.type === 'keyshop');

            if (elements.official.historical) {
                elements.official.historical.textContent = officialHistData?.historical || '';
            }
            if (elements.keyshop.historical) {
                elements.keyshop.historical.textContent = keyshopHistData?.historical || '';
            }
            if (elements.official.compactHistorical) {
                elements.official.compactHistorical.textContent = officialHistData?.historical || '';
            }
            if (elements.keyshop.compactHistorical) {
                elements.keyshop.compactHistorical.textContent = keyshopHistData?.historical || '';
            }

            // Update best price indicators
            [elements.official.price, elements.official.compactPrice, elements.keyshop.price, elements.keyshop.compactPrice].forEach(el => {
                if (el) el.classList.remove('best-price');
            });

            if (data.lowestPriceType === 'official') {
                [elements.official.price, elements.official.compactPrice].forEach(el => {
                    if (el) el.classList.add('best-price');
                });
            } else if (data.lowestPriceType === 'keyshop') {
                [elements.keyshop.price, elements.keyshop.compactPrice].forEach(el => {
                    if (el) el.classList.add('best-price');
                });
            }
        }

        // Update all View Offers links
        if (data.url) {
            links.forEach(link => {
                link.href = data.url;
            });
        }
    } else {
        // Handle error state
        const priceElements = container.querySelectorAll('.gg-price-value:not(.historical)');
        priceElements.forEach(el => {
            el.textContent = 'Not found';
        });

        const historicalElements = container.querySelectorAll('.gg-historical-tooltip-text, .gg-price-value.historical');
        historicalElements.forEach(el => {
            el.textContent = '';
        });

        // Set default URL for all View Offers links
        links.forEach(link => {
            link.href = `https://gg.deals/steam/${type}/${id}/`;
        });
    }
  }

  function createCompactPriceDisplay(containerId) {
    const container = document.createElement('div');
    container.className = 'gg-deals-container compact bundle-sub-display';
    container.id = containerId;
    container.style.display = toggleStates.subDisplay ? "" : "none";
    container.innerHTML = `
        <div class="gg-compact-row">
            <img src="https://gg.deals/favicon.ico" alt="GG.deals" class="gg-icon">
            <div class="gg-compact-prices">
                <div class="gg-compact-price-item gg-compact-official" style="${!toggleStates.official ? "display:none" : ""}">
                    <span>Official:</span>
                    <span class="gg-historical-tooltip">
                        <span class="gg-price-value gg-compact-official-price">Loading...</span>
                        <span class="gg-historical-tooltip-text gg-compact-official-historical"></span>
                    </span>
                </div>
                <div class="gg-compact-price-item gg-compact-keyshop" style="${!toggleStates.keyshop ? "display:none" : ""}">
                    <span>Keyshop:</span>
                    <span class="gg-historical-tooltip">
                        <span class="gg-price-value gg-compact-keyshop-price">Loading...</span>
                        <span class="gg-historical-tooltip-text gg-compact-keyshop-historical"></span>
                    </span>
                </div>
            </div>
            <div class="gg-compact-controls">
                <a href="#" target="_blank" class="gg-view-offers">View Offers</a>
            </div>
        </div>
    `;
    return container;
  }

  // Wait for Steam page to fully load (including age gate) and handle tab visibility
  let isInitialized = false;

  function initializeWhenVisible() {
    if (document.visibilityState === "visible" && !isInitialized) {
        const urlMatch = window.location.pathname.match(/\/(app|sub|bundle)\/(\d+)/);
        if (!urlMatch) return;

        const [, pageType, pageId] = urlMatch;
        isInitialized = true;

        // For app pages, show the full container at the top
        if (pageType === 'app') {
            const purchaseSection = document.querySelector("#game_area_purchase");
            if (purchaseSection) {
                const mainContainer = createPriceContainer();
                mainContainer.id = 'gg-deals-main';
                purchaseSection.parentNode.insertBefore(mainContainer, purchaseSection);
                fetchGamePrices(null, 'gg-deals-main', false, { type: pageType, id: pageId });
            }
        }

        // For sub/bundle pages, show only one display at the top
        if (pageType === 'sub' || pageType === 'bundle') {
            // Try to find the first purchase game section
            const firstPurchaseGame = document.querySelector('.game_area_purchase_game');
            if (firstPurchaseGame) {
                const mainContainer = createPriceContainer();
                mainContainer.id = `gg-deals-${pageType}-${pageId}`;
                firstPurchaseGame.parentNode.insertBefore(mainContainer, firstPurchaseGame);
                fetchGamePrices(null, mainContainer.id, false, { type: pageType, id: pageId });
            }
            return; // Exit early to prevent additional displays
        }

        // Handle all purchase games (only for app pages)
        if (pageType === 'app') {
            document.querySelectorAll('.game_area_purchase_game').forEach((element) => {
              // Skip if this is a demo section
              if (element.closest('.demo_above_purchase')) {
                  return;
              }
          
              // Get the ID and type from the inputs
              const bundleInput = element.querySelector('input[name="bundleid"]');
              const subInput = element.querySelector('input[name="subid"]');
          
              if (!bundleInput && !subInput) {
                  // If no inputs found, try to get ID from the element ID
                  const elementId = element.id.match(/\d+$/)?.[0];
          
                  // Skip main app on app pages
                  if (pageType === 'app' && elementId === pageId) {
                      return; // Skip main app on app pages
                  }
              }

                let itemType, itemId;
                if (bundleInput) {
                    itemType = 'bundle';
                    itemId = bundleInput.value;
                } else if (subInput) {
                    itemType = 'sub';
                    itemId = subInput.value;
                } else {
                    // Fallback to page type/id
                    itemType = pageType;
                    itemId = pageId;
                }

                const containerId = `gg-deals-${itemType}-${itemId}`;
                const compactDisplay = createCompactPriceDisplay(containerId);
                
                // Insert before game_purchase_action
                const purchaseAction = element.querySelector('.game_purchase_action');
                if (purchaseAction) {
                    purchaseAction.parentNode.insertBefore(compactDisplay, purchaseAction);
                    // Use Promise to handle the async operation properly
                    (async () => {
                        await fetchGamePrices(null, containerId, false, { type: itemType, id: itemId });
                    })();
                }
            });
        }
    }
  }

  // Check for visibility changes
  document.addEventListener("visibilitychange", initializeWhenVisible);

  // Initial check (in case the tab is already visible)
  const checkTitle = setInterval(() => {
    if (document.visibilityState === "visible") {
      initializeWhenVisible();
      if (isInitialized) {
        clearInterval(checkTitle);
      }
    }
  }, 500);
})();