// ── Custom Matchmaker (ported from Crankshaft) ──
// Fetches live lobby list from matchmaker.krunker.io, filters by user criteria,
// presents a popup to join a random matching game.

import type { Keybind } from '../main/config';
import type { SavedConsole } from './utils';

export const MATCHMAKER_GAMEMODES = ['Free for All', 'Team Deathmatch', 'Hardpoint', 'Capture the Flag', 'Parkour', 'Hide & Seek', 'Infected', 'Race', 'Last Man Standing', 'Simon Says', 'Gun Game', 'Prop Hunt', 'Boss Hunt', 'Classic FFA', 'Deposit', 'Stalker', 'King of the Hill', 'One in the Chamber', 'Trade', 'Kill Confirmed', 'Defuse', 'Sharp Shooter', 'Traitor', 'Raid', 'Blitz', 'Domination', 'Squad Deathmatch', 'Kranked FFA', 'Team Defender', 'Deposit FFA', 'Chaos Snipers', 'Bighead FFA'];
export const MATCHMAKER_REGIONS = ['MBI', 'NY', 'FRA', 'SIN', 'DAL', 'SYD', 'MIA', 'BHN', 'TOK', 'BRZ', 'AFR', 'LON', 'CHI', 'SV', 'STL', 'MX'];
export const MATCHMAKER_REGION_NAMES: Record<string, string> = { MBI: 'Mumbai', NY: 'New York', FRA: 'Frankfurt', SIN: 'Singapore', DAL: 'Dallas', SYD: 'Sydney', MIA: 'Miami', BHN: 'Middle East', TOK: 'Tokyo', BRZ: 'Brazil', AFR: 'South Africa', LON: 'London', CHI: 'China', SV: 'Silicon Valley', STL: 'Seattle', MX: 'Mexico' };
const MAP_ICON_INDICES = ['Burg', 'Littletown', 'Sandstorm', 'Subzero', 'Undergrowth', 'Shipment', 'Freight', 'Lostworld', 'Citadel', 'Oasis', 'Kanji', 'Industry', 'Lumber', 'Evacuation', 'Site', 'SkyTemple', 'Lagoon', 'Bureau', 'Tortuga', 'Tropicano', 'Krunk_Plaza', 'Arena', 'Habitat', 'Atomic', 'Old_Burg', 'Throwback', 'Stockade', 'Facility', 'Clockwork', 'Laboratory', 'Shipyard', 'Soul Sanctum', 'Bazaar', 'Erupt', 'HQ', 'Khepri', 'Lush', 'Vivo', 'Slide Moonlight', 'Eterno Sim'];

interface MatchmakerGame {
  gameID: string;
  region: string;
  playerCount: number;
  playerLimit: number;
  map: string;
  gamemode: string;
  remainingTime: number;
}

export interface MatchmakerConfig {
  enabled: boolean;
  regions: string[];
  gamemodes: string[];
  minPlayers: number;
  maxPlayers: number;
  minRemainingTime: number;
  openServerBrowser: boolean;
  acceptKey: Keybind;
  cancelKey: Keybind;
}

function secondsToTimestring(num: number): string {
  const minutes = Math.floor(num / 60);
  const seconds = num % 60;
  if (minutes < 1) return `${num}s`;
  return `${minutes}m ${seconds}s`;
}

// ── Popup DOM (created once, reused) ──
const POPUP_ID = 'matchmakerPopupContainer';
const popupElement = document.createElement('div');
popupElement.id = POPUP_ID;

const popupTitle = document.createElement('div');
popupTitle.id = 'matchmakerPopupTitle';
popupElement.appendChild(popupTitle);

const popupDescription = document.createElement('div');
popupDescription.id = 'matchmakerPopupDescription';
popupElement.appendChild(popupDescription);

const popupOptions = document.createElement('div');
popupOptions.id = 'matchmakerPopupOptions';

const popupConfirmBtn = document.createElement('div');
popupConfirmBtn.id = 'matchmakerConfirmButton';
popupConfirmBtn.className = 'matchmakerPopupButton bigShadowT';
popupConfirmBtn.textContent = 'Join';
popupConfirmBtn.setAttribute('onmouseenter', 'playTick()');
popupConfirmBtn.addEventListener('click', () => decideMatchmakerDecision(true));

const popupCancelBtn = document.createElement('div');
popupCancelBtn.id = 'matchmakerCancelButton';
popupCancelBtn.className = 'matchmakerPopupButton bigShadowT';
popupCancelBtn.textContent = 'Cancel';
popupCancelBtn.setAttribute('onmouseenter', 'playTick()');
popupCancelBtn.addEventListener('click', () => decideMatchmakerDecision(false));

popupOptions.appendChild(popupConfirmBtn);
popupOptions.appendChild(popupCancelBtn);
popupElement.appendChild(popupOptions);

// ── State ──
let currentMatch = '';
let openServerBrowser = true;
let confirmKey: Keybind = { key: 'Enter', ctrl: false, shift: false, alt: false };
let cancelKey: Keybind = { key: 'Escape', ctrl: false, shift: false, alt: false };

function decideMatchmakerDecision(accept: boolean): void {
  const w = window as any;
  if (typeof w.playSelect === 'function') w.playSelect();

  if (accept && currentMatch !== 'none') {
    window.location.href = `https://krunker.io/?game=${currentMatch}`;
  } else {
    if (popupElement.parentNode) popupElement.remove();
    if (currentMatch === 'none' && openServerBrowser && typeof w.openServerWindow === 'function') {
      w.openServerWindow(0);
    }
  }
}

function matchesKey(bind: Keybind, event: KeyboardEvent): boolean {
  if ((document.activeElement as HTMLElement)?.tagName === 'INPUT') return false;
  return event.key === bind.key
    && event.shiftKey === bind.shift
    && event.altKey === bind.alt
    && event.ctrlKey === bind.ctrl;
}

function handleMatchmakerBind(event: KeyboardEvent): void {
  if (document.pointerLockElement) return;
  const isAccept = matchesKey(confirmKey, event);
  const isCancel = matchesKey(cancelKey, event);
  if (isAccept || isCancel) {
    document.removeEventListener('keydown', handleMatchmakerBind, true);
    decideMatchmakerDecision(isAccept);
  }
}

function createFetchedGamePopup(game: MatchmakerGame): void {
  const mapIdx = MAP_ICON_INDICES.indexOf(game.map);
  popupElement.style.backgroundImage = `url(https://assets.krunker.io/img/maps/map_${mapIdx >= 0 ? mapIdx : 0}.png)`;

  currentMatch = game.gameID;
  if (game.gameID === 'none') {
    popupTitle.innerText = 'No Games Found...';
    popupDescription.innerHTML = 'Check the server browser to see other lobbies.';
    popupConfirmBtn.style.display = 'none';
  } else {
    popupTitle.innerText = 'Game Found!';
    const regionName = MATCHMAKER_REGION_NAMES[game.region] ?? 'Unknown Region';
    popupDescription.innerHTML = `${game.gamemode} on ${game.map} (${regionName})<br/>${game.playerCount}/${game.playerLimit} Players, ${secondsToTimestring(game.remainingTime)} Left`;
    popupConfirmBtn.style.display = 'block';
  }

  document.addEventListener('keydown', handleMatchmakerBind, true);
  const uiBase = document.getElementById('uiBase');
  if (uiBase) uiBase.appendChild(popupElement);
}

export async function fetchGame(mmConfig: MatchmakerConfig, _con?: SavedConsole): Promise<void> {
  openServerBrowser = mmConfig.openServerBrowser;
  confirmKey = mmConfig.acceptKey;
  cancelKey = mmConfig.cancelKey;

  // Dismiss existing popup if active
  if (document.getElementById(POPUP_ID)) decideMatchmakerDecision(false);

  _con?.log('[KCC-MM] Fetching game list...');

  const response = await fetch(`https://matchmaker.krunker.io/game-list?hostname=${window.location.hostname}`);
  const result = await response.json();
  const games: MatchmakerGame[] = [];

  for (const game of result.games) {
    const gameID: string = game[0];
    const region = gameID.split(':')[0];
    const playerCount: number = game[2];
    const playerLimit: number = game[3];
    const map: string = game[4].i;
    const gamemode = MATCHMAKER_GAMEMODES[game[4].g] ?? 'Unknown Gamemode';
    const remainingTime: number = game[5];

    // Apply filters — empty arrays mean "all selected" (no filter)
    if (mmConfig.regions.length > 0 && !mmConfig.regions.includes(region)) continue;
    if (mmConfig.gamemodes.length > 0 && !mmConfig.gamemodes.includes(gamemode)) continue;
    if (playerCount < mmConfig.minPlayers) continue;
    if (playerCount > mmConfig.maxPlayers) continue;
    if (remainingTime < mmConfig.minRemainingTime) continue;
    if (playerCount === playerLimit) continue;
    if (window.location.href.includes(gameID)) continue;
    if (currentMatch === gameID) continue;

    games.push({ gameID, region, playerCount, playerLimit, map, gamemode, remainingTime });
  }

  _con?.log('[KCC-MM] Received', result.games?.length ?? 0, 'games,', games.length, 'passed filters');

  if (games.length > 0) {
    const selected = games[Math.floor(Math.random() * games.length)];
    _con?.log('[KCC-MM] Selected:', selected.gameID, selected.region, selected.map);
    createFetchedGamePopup(selected);
  } else {
    _con?.log('[KCC-MM] No matching games found');
    createFetchedGamePopup({
      gameID: 'none',
      region: 'none',
      playerCount: 0,
      playerLimit: 0,
      map: MAP_ICON_INDICES[0],
      gamemode: MATCHMAKER_GAMEMODES[0],
      remainingTime: 0,
    });
  }
}

