document.addEventListener("DOMContentLoaded", () => {
  new QWebChannel(qt.webChannelTransport, function (channel) {
    const bridge = channel.objects.bridge;
    window.bridge = bridge;

    // ⬇️ Объявляем переменные после инициализации bridge
    let dict = {};
    let currentCategory = "General";
	let itemsPerPage;
	const resolution = localStorage.getItem("resolution") || "1360x768";
	
	switch (resolution) {
	case "800x600":
	case "IGCN-0":
	case "IGCN-1":
		itemsPerPage = 4;   // panelHeight = 150 → 4 строки
		break;
	
	case "1024x768":
	case "IGCN-2":
		itemsPerPage = 7;   // panelHeight = 318 → ~7 строк
		break;
	
	case "1280x720":
	case "IGCN-3":
		itemsPerPage = 6;   // panelHeight = 270 → ~6 строк
		break;
	
	case "1360x768":
		itemsPerPage = 7;   // panelHeight = 318 → ~7 строк
		break;
	
	case "1280x1024":
		itemsPerPage = 12;  // panelHeight = 574 → ~12 строк
		break;
	
	case "IGCN-4":
		itemsPerPage = 11;  // panelHeight = 510 → ~11 строк
		break;
	
	case "IGCN-5":
		itemsPerPage = 10;  // panelHeight = 450 → ~10 строк
		break;
	
	case "IGCN-6":
		itemsPerPage = 13;  // panelHeight = 600 → ~13 строк
		break;
	
	case "IGCN-7":
		itemsPerPage = 12;  // panelHeight = 540 → ~12 строк
		break;
	
	case "IGCN-8":
		itemsPerPage = 14;  // panelHeight = 630 → ~14 строк
		break;
	
	default:
		itemsPerPage = 10;
	}

    const categories = document.querySelectorAll(".tab");
    const tableContainer = document.getElementById("ranking-table");
    const paginationEl = document.getElementById("pagination");
    const searchInput = document.getElementById("search-input");
    const classFilter = document.getElementById("class-filter");
    bridge.get_allowed_classes_json(function(json) {
      try {
        const allowed = JSON.parse(json);
        if (classFilter) {
          classFilter.innerHTML = ""; // очищаем
          const allOption = document.createElement("option");
          allOption.value = "All";
          allOption.text = dict["class_all"] || "All";
          classFilter.appendChild(allOption);
    
          allowed.forEach(cls => {
            const option = document.createElement("option");
            option.value = cls;
            option.text = dict["class_" + cls] || cls.toUpperCase();
            classFilter.appendChild(option);
          });
        }
      } catch (e) {
        console.error("❌ Failed to load allowed classes:", e);
      }
    });

    const onlineCount = document.getElementById("online-count");
    const fill = document.getElementById("online-fill");

    function showLoading() {
      document.getElementById("loading-indicator").style.display = "block";
      tableContainer.innerHTML = "";
      paginationEl.innerHTML = "";
    }
    
    function hideLoading() {
      document.getElementById("loading-indicator").style.display = "none";
    }

    // ⏳ Debounce чтобы не вызывать loadCategory слишком часто
    let debounceTimer;
    function debounceLoadCategory() {
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(() => {
        loadCategory(currentCategory);
      }, 300); // задержка 300мс
    }

    let allData = {
      characters: {},
      accountcharacter: [],
      cashshop: [],
      guildmember: {},
      membstat: {},
    };

    // ⬇️ Сначала загрузим перевод
    const lang = localStorage.getItem("language") || "en";
    bridge.get_translation(lang, function (raw) {
      try {
        dict = JSON.parse(raw);
    
        // Загружаем классы после перевода
        bridge.get_allowed_classes_json(function(json) {
          try {
            const allowed = JSON.parse(json);
            if (classFilter) {
              classFilter.innerHTML = "";
              const allOption = document.createElement("option");
              allOption.value = "All";
              allOption.text = dict["class_all"] || "All";
              classFilter.appendChild(allOption);
    
              allowed.forEach(cls => {
                const option = document.createElement("option");
                option.value = cls;
                option.text = dict["class_" + cls] || cls.toUpperCase();
                classFilter.appendChild(option);
              });
            }
          } catch (e) {
            console.error("❌ Failed to load allowed classes:", e);
          }
    
          loadCategory("General");
          setTimeout(() => {
            updateOnlineCount();
            applyRankingsTranslations(dict);
          }, 200);
        });
    
      } catch (e) {
        console.error("❌ Failed to parse translation:", e);
      }
    });

    // ⬇️ При смене языка
    window.addEventListener("languageChanged", () => {
      const newLang = localStorage.getItem("language") || "en";
      bridge.get_translation(newLang, function (raw) {
        try {
          dict = JSON.parse(raw);
          applyRankingsTranslations(dict);
          loadCategory(currentCategory);
        } catch (e) {
          console.error("❌ Failed to apply translation:", e);
        }
      });
    });
	
    function getClassKey(cls_code) {
      if (0 <= cls_code && cls_code <= 15) return "dw";
      if (16 <= cls_code && cls_code <= 31) return "dk";
      if (32 <= cls_code && cls_code <= 47) return "elf";
      if (48 <= cls_code && cls_code <= 63) return "mg";
      if (64 <= cls_code && cls_code <= 79) return "dl";
      if (80 <= cls_code && cls_code <= 95) return "sum";
      if (96 <= cls_code && cls_code <= 111) return "rf";
      if (112 <= cls_code && cls_code <= 127) return "gl";
      if (128 <= cls_code && cls_code <= 142) return "rw";
      if (144 <= cls_code && cls_code <= 158) return "sl";
      if (160 <= cls_code && cls_code <= 175) return "gc";
      if (176 <= cls_code && cls_code <= 191) return "lw";
      if (192 <= cls_code && cls_code <= 207) return "lemuria";
      if (208 <= cls_code && cls_code <= 223) return "illusion";
      if (224 <= cls_code && cls_code <= 239) return "alc";
      return "default";
    }

    function getAvatar(classCode) {
      const cls = getClassKey(classCode);
      return `<img src="../images/classes/${cls}.png" class="avatar-icon" alt="${cls}" />`;
    }

    function calculateELO(player) {
      const baseELO = 1000;
      const cLevel = Number(player.cLevel || 0);
      const reset = Number(player.ResetCount || 0);
      const mreset = Number(player.MasterResetCount || 0);
      const kills = Number(player.Kills || 0);
	  const deaths = Number(player.Deads || player.Deaths || 0);
      const online = Number(player.OnlineHours || 0);
    
      let delta = 0;
      delta += mreset * 30;
      delta += reset * 10;
      delta += kills * 1.5;
      delta += online * 0.3;
      delta -= deaths * 2.0;
    
      const finalELO = baseELO + delta;
        
      return Math.max(finalELO, 0);
    }

    function filterPlayers(players) {
      const query = searchInput.value.toLowerCase();
      const selectedClass = classFilter.value;
    
      if (!query && selectedClass === "All") return players;
    
      return players.filter(player => {
        const name = (player.Name || player.G_Name || "").toLowerCase();
        const playerClassKey = getClassKey(player.Class);
        const classMatch = selectedClass === "All" || playerClassKey === selectedClass;
        return name.includes(query) && classMatch;
      });
    }

    function getOnlineCharacters() {
      const result = [];
      const memb = allData.membstat;
      const accChar = allData.accountcharacter;
      const chars = allData.characters;

      Object.values(accChar || {}).forEach(acc => {
        const accId = acc.Id;
        const onlineEntry = memb[accId];
        if (onlineEntry && onlineEntry.ConnectStat === 1) {
          const name = acc.GameIDC;
          const char = chars[name?.toLowerCase()];
          if (char) {
            char.OnlineHours = onlineEntry.OnlineHours;
            result.push(char);
          }
        }
      });

      return result.sort((a, b) => b.OnlineHours - a.OnlineHours);
    }

	function generatePvPRanking() {
	const chars = Object.values(allData.characters || {});
	return chars.map(p => {
		const kills = Number(p.Kills || 0);
		const deaths = Number(p.Deads || 0);
	
		let KD = "0.00";
		let realKD = 0;
	
		if (kills > 0 && deaths > 0) {
		KD = (kills / deaths).toFixed(2);
		realKD = kills / deaths;
		} else if (kills > 0 && deaths === 0) {
		KD = kills.toFixed(2);
		realKD = kills;
		} else if (kills === 0 && deaths > 0) {
		KD = "-" + deaths.toFixed(2);
		realKD = -deaths;
		}
	
		return {
		...p,
		Kills: kills,
		Deaths: deaths,
		KD,
		RealKD: realKD
		};
	}).sort((a, b) => b.RealKD - a.RealKD);
	}

    function generateGuilds() {
      const guilds = {};
      for (const key in allData.guildmember) {
        const p = allData.guildmember[key];
        if (!guilds[p.G_Name]) guilds[p.G_Name] = { G_Name: p.G_Name, G_Master: "", Number: 0 };
        guilds[p.G_Name].Number++;
        if (p.G_Status === 128 || p.Name === p.G_Master) guilds[p.G_Name].G_Master = p.Name;
      }
      return Object.values(guilds).sort((a, b) => b.Number - a.Number);
    }

	let fullList = [];
	
    const cachedLists = {
      "General": null,
      "Top PvP": null,
      "Top Online": null,
      "Guilds": null,
      "ELO": null
    };

    function renderTable(category, fullPlayersList) {
      const filtered = filterPlayers(fullPlayersList);
      const totalPages = Math.ceil(filtered.length / itemsPerPage);
      const start = (currentPage - 1) * itemsPerPage;
      const end = start + itemsPerPage;
      const pagePlayers = filtered.slice(start, end);
    
      let html = `<div class="table-header">`;
      if (category === "Guilds") {
        html += `<div></div>
                 <div>${dict.header_guild || "Guild"}</div>
                 <div>${dict.header_master || "Master"}</div>
                 <div>${dict.header_players || "Players"}</div>`;
      } else if (category === "Top PvP") {
        html += `<div></div>
                 <div>${dict.header_class || "Class"}</div>
                 <div>${dict.header_name || "Name"}</div>
                 <div>${dict.header_kills || "Kills"}</div>
                 <div>${dict.header_deaths || "Deaths"}</div>
                 <div>${dict.header_kd || "K/D"}</div>`;
      } else if (category === "Top Online") {
        html += `<div></div>
                 <div>${dict.header_class || "Class"}</div>
                 <div>${dict.header_name || "Name"}</div>
                 <div>${dict.header_gr || "GR"}</div>
                 <div>${dict.header_rr || "RR"}</div>
                 <div>${dict.header_lvl || "LVL"}</div>
                 <div>${dict.header_hours || "Hours"}</div>`;
      } else if (category === "ELO") {
        html += `<div></div>
                 <div>${dict.header_class || "Class"}</div>
                 <div>${dict.header_name || "Name"}</div>
                 <div>${dict.header_elo || "ELO"}</div>`;
      } else {
        html += `<div></div>
                 <div>${dict.header_class || "Class"}</div>
                 <div>${dict.header_name || "Name"}</div>
                 <div>${dict.header_gr || "GR"}</div>
                 <div>${dict.header_rr || "RR"}</div>
                 <div>${dict.header_lvl || "LVL"}</div>`;
      }
      html += `</div>`;

      pagePlayers.forEach(p => {
        let isOnline = false;
    
		if (category === "Guilds") {
		const master = p.G_Master || "";
		isOnline = Object.values(allData.accountcharacter).some(acc =>
			acc.GameIDC?.toLowerCase() === master.toLowerCase() &&
			allData.membstat?.[acc.Id]?.ConnectStat === 1
		);
		} else {
		const charName = p.Name;
		isOnline = Object.values(allData.accountcharacter).some(acc =>
			acc.GameIDC?.toLowerCase() === charName?.toLowerCase() &&
			allData.membstat?.[acc.Id]?.ConnectStat === 1
		);
		}

    
        const statusDot = `<span class="status-dot ${isOnline ? 'online' : 'offline'}"></span>`;
        const position = p.Position || "-";
    
        html += `<div class="ranking-row">`;
    
        if (category === "Guilds") {
          html += `<div>${statusDot} ${position}</div><div>${p.G_Name}</div><div>${p.G_Master}</div><div>${p.Number}</div>`;
        } else if (category === "Top PvP") {
          html += `<div>${statusDot} ${position}</div><div>${getAvatar(p.Class)}</div><div>${p.Name}</div><div>${p.Kills}</div><div>${p.Deaths}</div><div>${p.KD}</div>`;
        } else if (category === "Top Online") {
          html += `<div>${statusDot} ${position}</div><div>${getAvatar(p.Class)}</div><div>${p.Name}</div><div>${p.MasterResetCount}</div><div>${p.ResetCount}</div><div>${p.cLevel}</div><div>${p.OnlineHours || 0}</div>`;
		} else if (category === "ELO") {
		const elo = p.ELO;
		let eloTier = "max-elo";
		
		if (elo <= 800) eloTier = "1-elo";
		else if (elo <= 1500) eloTier = "2-elo";
		else if (elo <= 2000) eloTier = "3-elo";
		else if (elo <= 2500) eloTier = "4-elo";
		else if (elo <= 3000) eloTier = "5-elo";
		else if (elo <= 3500) eloTier = "6-elo";
		else if (elo <= 4000) eloTier = "7-elo";
		else if (elo <= 4500) eloTier = "8-elo";
		else if (elo <= 5000) eloTier = "9-elo";
		else if (elo <= 5500) eloTier = "10-elo";
		
		const eloImage = `<img src="../images/elo/${eloTier}.webp" alt="${eloTier}" title="ELO: ${elo.toFixed(2)}" class="elo-icon" />`;
		
		html += `<div>${statusDot} ${position}</div><div>${getAvatar(p.Class)}</div><div>${p.Name}</div><div>${eloImage}</div>`;
        } else {
          html += `<div>${statusDot} ${position}</div><div>${getAvatar(p.Class)}</div><div>${p.Name}</div><div>${p.MasterResetCount}</div><div>${p.ResetCount}</div><div>${p.cLevel}</div>`;
        }
    
        html += `</div>`;
      });
    
    tableContainer.innerHTML = html;
    paginationEl.innerHTML = "";

    function createPageButton(label, page = null, disabled = false, active = false) {
      const btn = document.createElement("button");
      btn.textContent = label;
      btn.className = "page-button";
      if (active) btn.classList.add("active");
      if (disabled) btn.disabled = true;
      if (page !== null) {
        btn.addEventListener("click", () => {
          currentPage = page;
          renderTable(currentCategory, fullList);
        });
      }
      return btn;
    }
    
    // totalPages уже объявлена выше — не повторяем
    
    // Prev
    paginationEl.appendChild(createPageButton("<", currentPage - 1, currentPage === 1));
    
    // Always show first
    paginationEl.appendChild(createPageButton(1, 1, false, currentPage === 1));
    
    // Show "..." if currentPage is far from start
    if (currentPage > 3) {
      const dots = document.createElement("span");
      dots.textContent = "...";
      dots.className = "pagination-dots";
      paginationEl.appendChild(dots);
    }
    
    // Show neighbors: currentPage -1, currentPage, currentPage +1
    const paginationStart = Math.max(2, currentPage - 1);
    const paginationEnd = Math.min(totalPages - 1, currentPage + 1);
    for (let i = paginationStart; i <= paginationEnd; i++) {
      paginationEl.appendChild(createPageButton(i, i, false, i === currentPage));
    }
    
    // Show "..." if currentPage is far from end
    if (currentPage < totalPages - 2) {
      const dots = document.createElement("span");
      dots.textContent = "...";
      dots.className = "pagination-dots";
      paginationEl.appendChild(dots);
    }
    
    // Always show last
    if (totalPages > 1) {
      paginationEl.appendChild(createPageButton(totalPages, totalPages, false, currentPage === totalPages));
    }
    
    // Next
    paginationEl.appendChild(
      createPageButton(">", currentPage + 1, currentPage === totalPages, false)
    );

  } // ← ЗАКРЫВАЕМ функцию renderTable ЗДЕСЬ

  // Эти две функции должны быть ВНЕ renderTable:
  function updateOnlineCount() {
    const memb = allData.membstat || {};
    let count = 0;
    Object.values(memb).forEach(m => {
      if (m.ConnectStat === 1) count++;
    });
    onlineCount.textContent = count;
    const percent = Math.min((count / 500) * 100, 100);
    fill.style.width = `${percent}%`;
  }

  function applyRankingsTranslations(dict) {
    // Заголовок окна
    document.title = dict.rankings_title || "Player Rankings";
  
    // ⬅️ Заголовок H1
    const h1 = document.getElementById("rankings-title");
    if (h1 && dict.rankings_title) h1.textContent = dict.rankings_title;
  
    // Верхний статус
    const label = document.getElementById("online-label");
    if (label && dict.online_players) {
      const count = document.getElementById("online-count")?.textContent || "?";
      label.innerHTML = `${dict.online_players} <span id="online-count">${count}</span>/500`;
    }
  
    // Вкладки
    const tabs = document.querySelectorAll(".tab");
    tabs.forEach(tab => {
      const cat = tab.dataset.category;
      if (cat === "General") tab.textContent = dict.tab_general || "General";
      if (cat === "Top Online") tab.textContent = dict.tab_online || "Online";
      if (cat === "Top PvP") tab.textContent = dict.tab_pvp || "PvP";
      if (cat === "Guilds") tab.textContent = dict.tab_guilds || "Guilds";
      if (cat === "ELO") tab.textContent = dict.tab_elo || "ELO";
    });
  
  // Классы
  if (classFilter) {
    for (let opt of classFilter.options) {
      const key = opt.value === "All" ? "class_all" : "class_" + opt.value;
      if (dict[key]) opt.text = dict[key];
    }
  }
    // Поиск
    if (searchInput && dict.search_placeholder) {
      searchInput.placeholder = dict.search_placeholder;
    }
  }

  function loadDataForCategory(category, callback) {
    showLoading();
  
    const tasks = [];
  
    // Загрузка characters — почти для всех категорий
    if (["General", "Top PvP", "ELO", "Top Online"].includes(category)) {
      tasks.push(new Promise(res => bridge.get_characters_cache(json => {
        try { allData.characters = JSON.parse(json); } catch (e) {}
        res();
      })));
    }
  
    // Загрузка accountcharacter — только для Top Online
    if (category === "Top Online") {
      tasks.push(new Promise(res => bridge.get_account_character(json => {
        try { allData.accountcharacter = JSON.parse(json); } catch (e) {}
        res();
      })));
    }
  
    // Загрузка membstat (для online-count) — для всех категорий
    tasks.push(new Promise(res => bridge.get_online_json(json => {
      try { allData.membstat = JSON.parse(json); } catch (e) {}
      res();
    })));
  
    // Загрузка guilds — только для Guilds
    if (category === "Guilds") {
      tasks.push(new Promise(res => bridge.get_guild_member(json => {
        try { allData.guildmember = JSON.parse(json); } catch (e) {}
        res();
      })));
    }
  
    // Загрузка cashshop — только если нужно
    if (category === "ELO") {
      tasks.push(new Promise(res => bridge.get_cashshop_data(json => {
        try { allData.cashshop = JSON.parse(json); } catch (e) {}
        res();
      })));
    }
  
    Promise.all(tasks).then(() => {
      updateOnlineCount();
      callback();
    });
  }

  function loadCategory(category) {
    currentPage = 1;
    currentCategory = category;
    categories.forEach(btn => btn.classList.remove("active"));
    document.querySelector(`.tab[data-category="${category}"]`).classList.add("active");
  
    if (cachedLists[category]) {
      fullList = cachedLists[category];
      renderTable(category, fullList);
      hideLoading();
      return;
    }
  
    loadDataForCategory(category, () => {
      if (category === "Guilds") {
        cachedLists[category] = generateGuilds().map((p, i) => ({ ...p, Position: i + 1 }));
      } else if (category === "Top PvP") {
        const ranked = generatePvPRanking();
        cachedLists[category] = ranked.map((p, i) => ({ ...p, Position: i + 1 }));
      } else if (category === "ELO") {
        const eloSorted = Object.values(allData.characters).map(p => ({
          ...p,
          ELO: calculateELO(p)
        })).sort((a, b) => b.ELO - a.ELO);
        cachedLists[category] = eloSorted.map((p, i) => ({ ...p, Position: i + 1 }));
      } else if (category === "Top Online") {
        const online = getOnlineCharacters();
        cachedLists[category] = online.map((p, i) => ({ ...p, Position: i + 1 }));
      } else {
        const general = Object.values(allData.characters).sort((a, b) => {
          if (b.MasterResetCount !== a.MasterResetCount) return b.MasterResetCount - a.MasterResetCount;
          if (b.ResetCount !== a.ResetCount) return b.ResetCount - a.ResetCount;
          return b.cLevel - a.cLevel;
        });
        cachedLists[category] = general.map((p, i) => ({ ...p, Position: i + 1 }));
      }
  
      fullList = cachedLists[category];
      renderTable(category, fullList);
      hideLoading();
    });
  }
  
  // Подключаем обработчики вкладок и фильтров
  categories.forEach(btn => btn.addEventListener("click", () => loadCategory(btn.dataset.category)));
  searchInput.addEventListener("input", debounceLoadCategory);
  classFilter.addEventListener("input", debounceLoadCategory);
  
  // Загружаем только General при открытии страницы
  loadCategory("General");
  
  });
  });
