// i18n.js — EN/PT-BR dictionaries + t(key). Every UI string in the app goes
// through t(); static HTML uses data-i18n / data-i18n-aria attributes.
// Language persists in wc2026_prefs.lang; changing it dispatches "langchange"
// so modules can re-render dynamic content.

import { getPrefs, setPref } from './storage.js';

// App version for footer display — bump this after any notable changes
const APP_VERSION = 'v1.0.3';

const dicts = {
  en: {
    'a11y.skip': 'Skip to content',
    'a11y.mainNav': 'Main navigation',
    'a11y.langSwitch': 'Switch language',
    'nav.home': 'Home',
    'nav.matches': 'Matches',
    'nav.groups': 'Groups',
    'nav.bracket': 'Knockout',
    'nav.stadiums': 'Stadiums',
    'nav.stats': 'Stats',
    'hero.live': 'Live',
    'hero.nextMatch': 'Next match',
    'hero.nextMatches': 'Next matches',
    'hero.inProgress': 'In progress',
    'hero.countdownLabel': 'Time until kickoff',
    'hero.vs': 'vs',
    'countdown.days': 'days',
    'countdown.hours': 'hours',
    'countdown.minutes': 'min',
    'countdown.seconds': 'sec',
    'dash.title': 'Tournament overview',
    'dash.total': 'Total matches',
    'dash.completed': 'Completed',
    'dash.upcoming': 'Upcoming',
    'dash.teams': 'Teams',
    'app.loading': 'Loading data…',
    'app.error': 'Could not load tournament data.',
    'app.errorHint': 'If you opened index.html directly from disk, serve the folder instead: python -m http.server',
    'app.comingSoon': 'This section arrives in a later build step.',
    'app.tbd': 'TBD',
    'phase.group': 'Group',
    'phase.r32': 'Round of 32',
    'phase.r16': 'Round of 16',
    'phase.qf': 'Quarterfinals',
    'phase.sf': 'Semifinals',
    'phase.third': 'Third Place',
    'phase.final': 'Final',
    'schedule.searchPlaceholder': 'Search team, city or stadium…',
    'schedule.dateFilter': 'Filter by date',
    'schedule.allGroups': 'All groups',
    'schedule.allPhases': 'All phases',
    'schedule.groupStage': 'Group stage',
    'schedule.allTeams': 'All teams',
    'schedule.allStadiums': 'All stadiums',
    'schedule.sortAsc': 'Date ↑',
    'schedule.sortDesc': 'Date ↓',
    'schedule.match': 'match',
    'schedule.matches': 'matches',
    'schedule.noResults': 'No matches found — adjust the filters.',
    'schedule.clear': 'Clear filters',
    'status.finished': 'Full-time',
    'status.pens': 'pens',
    'standings.team': 'Team',
    'standings.played': 'P',
    'standings.won': 'W',
    'standings.drawn': 'D',
    'standings.lost': 'L',
    'standings.gf': 'GF',
    'standings.ga': 'GA',
    'standings.gd': 'GD',
    'standings.pts': 'Pts',
    'standings.legendTop2': 'Advance to the Round of 32',
    'standings.legendThird': 'In contention for best third place',
    'standings.inProgress': 'In progress',
    'standings.thirdTitle': 'Best third-placed teams',
    'standings.thirdNote': '8 of 12 advance to the Round of 32 — ranked by points, then goal difference, then goals for.',
    'standings.group': 'Group',
    'standings.qualified': 'Qualified',
    'standings.eliminated': 'Eliminated',
    'stadiums.capacity': 'Capacity',
    'stadiums.viewMatches': 'View matches',
    'status.scheduled': 'Scheduled',
    'status.pending': 'Awaiting result',
    'modal.close': 'Close',
    'modal.date': 'Date & time',
    'modal.stadium': 'Stadium',
    'modal.city': 'City',
    'modal.stats': 'Match stats',
    'modal.possession': 'Possession',
    'modal.shots': 'Shots',
    'modal.cards': 'Cards',
    'modal.statsSoon': 'Detailed stats will appear here once available.',
    'bracket.groupWinner': 'Group {g} Winner',
    'bracket.groupRunnerUp': 'Group {g} Runner-up',
    'bracket.bestThird': 'Best 3rd #{n}',
    'bracket.champion': 'Champion',
    'bracket.ft': 'FT',
    'bracket.viewLabel': 'Bracket view',
    'bracket.viewRounds': 'Rounds',
    'bracket.viewWallchart': 'Wallchart',
    'bracket.viewRadial': 'Radial',
    'bracket.zoomIn': 'Zoom in',
    'bracket.zoomOut': 'Zoom out',
    'bracket.zoomReset': 'Reset zoom',
    'sim.mode': 'Simulation',
    'sim.reset': 'Reset picks',
    'sim.hint': 'Simulation on — click a highlighted match to pick its winner. Real results are never changed.',
    'sim.title': 'Simulate',
    'sim.pickWinner': 'Pick the winner. Equal or empty score means penalties.',
    'sim.save': 'Save pick',
    'sim.clear': 'Remove pick',
    'sim.chip': 'SIM',
    'time.local': 'Local time',
    'time.stadium': 'Stadium time',
    'time.toggleAria': 'Toggle between local and stadium time',
    'schedule.myMatches': 'My matches',
    'schedule.occAria': 'Occurrence filter',
    'schedule.occAll': 'All matches',
    'schedule.occPlayed': 'Played',
    'schedule.occUpcoming': 'Upcoming',
    'fav.toggle': 'Favorite',
    'challenge.title': 'Bracket challenge',
    'challenge.correct': '{x} of {y} picks correct',
    'share.button': 'Share prediction',
    'share.copied': 'Link copied!',
    'share.confirm': 'Apply the shared prediction? Your current picks will be replaced.',
    'modal.addCalendar': 'Add to calendar',
    'stats.heroTitle': 'Tournament in progress',
    'stats.heroProgress': '{x} of {y} matches played',
    'stats.tileGoals': 'Goals',
    'stats.tileAvg': 'Goals / match',
    'stats.tileBiggestMargin': 'Biggest margin',
    'stats.tileCleanSheets': 'Clean sheets',
    'stats.sectionsNav': 'Statistics sections',
    'stats.navOverview': 'Overview',
    'stats.navTeams': 'Teams',
    'stats.navPlayers': 'Players',
    'stats.navRecords': 'Records',
    'stats.navComparator': 'Comparator',
    'stats.navArchive': 'Archive',
    'stats.overviewTitle': 'Overview',
    'stats.played': 'Matches played',
    'stats.decisive': 'Decisive',
    'stats.draws': 'Draws',
    'stats.goalsByPhase': 'Goals by stage',
    'stats.goalsByRound': 'Goals by round',
    'stats.matchday': 'Matchday',
    'stats.stageGroup': 'Group stage',
    'stats.verdictTitle': 'Final verdict',
    'stats.runnerUp': 'Runner-up',
    'stats.thirdPlace': 'Third place',
    'stats.fourthPlace': 'Fourth place',
    'stats.teamStatsTitle': 'Team statistics',
    'stats.colGpg': 'G/M',
    'stats.colCS': 'CS',
    'tip.played': 'Matches played',
    'tip.won': 'Wins',
    'tip.drawn': 'Draws',
    'tip.lost': 'Losses',
    'tip.gf': 'Goals for (scored)',
    'tip.ga': 'Goals against (conceded)',
    'tip.gd': 'Goal difference (for − against)',
    'tip.pts': 'Points',
    'tip.gpg': 'Goals per match (average)',
    'tip.cs': 'Clean sheets (no goals conceded)',
    'tip.rank': 'Final ranking — deepest stage reached, then points',
    'stats.rankCol': 'Rank',
    'stats.bestAttack': 'Best attack',
    'stats.bestDefense': 'Best defense',
    'stats.mostCleanSheets': 'Most clean sheets',
    'stats.mostWins': 'Most wins',
    'stats.mostConceded': 'Most goals conceded',
    'stats.bestGoalDiff': 'Best goal difference',
    'stats.leaderPrev': 'Previous team',
    'stats.leaderNext': 'Next team',
    'stats.biggestWin': 'Biggest win',
    'stats.winStreak': 'Longest win streak',
    'stats.championPath': "Champion's path",
    'stats.recordsTitle': 'Records',
    'stats.highScoreMatch': 'Highest-scoring match',
    'stats.formatDebutsTitle': 'Format debuts',
    'stats.debutTeams': 'First 48-team World Cup',
    'stats.debutMatches': 'Matches (up from 64)',
    'stats.debutGroups': 'Groups',
    'stats.debutR32': 'A new knockout round',
    'stats.debutThird': 'Best third-placed teams advance',
    'stats.debutChampion': 'First champion of the 48-team era',
    'stats.comparatorTitle': 'Team comparator',
    'stats.cmpTeamA': 'Team A',
    'stats.cmpTeamB': 'Team B',
    'stats.prevPage': 'Previous page',
    'stats.nextPage': 'Next page',
    'stats.seeAllMatches': 'See all matches',
    'footer.note': `Fan-made static hub ${APP_VERSION}`,
  },
  pt: {
    'a11y.skip': 'Pular para o conteúdo',
    'a11y.mainNav': 'Navegação principal',
    'a11y.langSwitch': 'Trocar idioma',
    'nav.home': 'Início',
    'nav.matches': 'Partidas',
    'nav.groups': 'Grupos',
    'nav.bracket': 'Mata-mata',
    'nav.stadiums': 'Estádios',
    'nav.stats': 'Estatísticas',
    'hero.live': 'Ao vivo',
    'hero.nextMatch': 'Próxima partida',
    'hero.nextMatches': 'Próximas partidas',
    'hero.inProgress': 'Bola rolando!',
    'hero.countdownLabel': 'Tempo até o início da partida',
    'hero.vs': 'vs',
    'countdown.days': 'dias',
    'countdown.hours': 'horas',
    'countdown.minutes': 'min',
    'countdown.seconds': 'seg',
    'dash.title': 'Visão geral do torneio',
    'dash.total': 'Total de partidas',
    'dash.completed': 'Encerradas',
    'dash.upcoming': 'Próximas',
    'dash.teams': 'Seleções',
    'app.loading': 'Carregando dados…',
    'app.error': 'Não foi possível carregar os dados do torneio.',
    'app.errorHint': 'Se você abriu o index.html direto do disco, sirva a pasta: python -m http.server',
    'app.comingSoon': 'Esta seção chega em uma próxima etapa.',
    'app.tbd': 'A definir',
    'phase.group': 'Grupo',
    'phase.r32': '16 avos de final',
    'phase.r16': 'Oitavas de final',
    'phase.qf': 'Quartas de final',
    'phase.sf': 'Semifinais',
    'phase.third': 'Disputa de 3º lugar',
    'phase.final': 'Final',
    'schedule.searchPlaceholder': 'Buscar seleção, cidade ou estádio…',
    'schedule.dateFilter': 'Filtrar por data',
    'schedule.allGroups': 'Todos os grupos',
    'schedule.allPhases': 'Todas as fases',
    'schedule.groupStage': 'Fase de grupos',
    'schedule.allTeams': 'Todas as seleções',
    'schedule.allStadiums': 'Todos os estádios',
    'schedule.sortAsc': 'Data ↑',
    'schedule.sortDesc': 'Data ↓',
    'schedule.match': 'partida',
    'schedule.matches': 'partidas',
    'schedule.noResults': 'Nenhuma partida encontrada — ajuste os filtros.',
    'schedule.clear': 'Limpar filtros',
    'status.finished': 'Encerrado',
    'status.pens': 'pên.',
    'standings.team': 'Seleção',
    'standings.played': 'J',
    'standings.won': 'V',
    'standings.drawn': 'E',
    'standings.lost': 'D',
    'standings.gf': 'GP',
    'standings.ga': 'GC',
    'standings.gd': 'SG',
    'standings.pts': 'Pts',
    'standings.legendTop2': 'Avançam aos 16 avos de final',
    'standings.legendThird': 'Na briga por melhor 3º lugar',
    'standings.inProgress': 'Em andamento',
    'standings.thirdTitle': 'Melhores terceiros colocados',
    'standings.thirdNote': '8 de 12 avançam aos 16 avos de final — ordenados por pontos, depois saldo de gols, depois gols pró.',
    'standings.group': 'Grupo',
    'standings.qualified': 'Classificado',
    'standings.eliminated': 'Eliminado',
    'stadiums.capacity': 'Capacidade',
    'stadiums.viewMatches': 'Ver partidas',
    'status.scheduled': 'Agendada',
    'status.pending': 'Pendente de resultado',
    'modal.close': 'Fechar',
    'modal.date': 'Data e hora',
    'modal.stadium': 'Estádio',
    'modal.city': 'Cidade',
    'modal.stats': 'Estatísticas',
    'modal.possession': 'Posse de bola',
    'modal.shots': 'Finalizações',
    'modal.cards': 'Cartões',
    'modal.statsSoon': 'Estatísticas detalhadas aparecerão aqui quando disponíveis.',
    'bracket.groupWinner': '1º do Grupo {g}',
    'bracket.groupRunnerUp': '2º do Grupo {g}',
    'bracket.bestThird': 'Melhor 3º #{n}',
    'bracket.champion': 'Campeão',
    'bracket.ft': 'FIM',
    'bracket.viewLabel': 'Visualização do mata-mata',
    'bracket.viewRounds': 'Fases',
    'bracket.viewWallchart': 'Chaveamento',
    'bracket.viewRadial': 'Radial',
    'bracket.zoomIn': 'Aproximar',
    'bracket.zoomOut': 'Afastar',
    'bracket.zoomReset': 'Restaurar zoom',
    'sim.mode': 'Simulação',
    'sim.reset': 'Limpar palpites',
    'sim.hint': 'Simulação ativa — clique numa partida destacada para escolher o vencedor. Resultados reais nunca mudam.',
    'sim.title': 'Simular',
    'sim.pickWinner': 'Escolha o vencedor. Placar igual ou vazio indica pênaltis.',
    'sim.save': 'Salvar palpite',
    'sim.clear': 'Remover palpite',
    'sim.chip': 'SIM',
    'time.local': 'Hora local',
    'time.stadium': 'Hora do estádio',
    'time.toggleAria': 'Alternar entre hora local e do estádio',
    'schedule.myMatches': 'Minhas partidas',
    'schedule.occAria': 'Filtro de ocorrência',
    'schedule.occAll': 'Todos os jogos',
    'schedule.occPlayed': 'Já ocorreram',
    'schedule.occUpcoming': 'A ocorrer',
    'fav.toggle': 'Favoritar',
    'challenge.title': 'Bolão do mata-mata',
    'challenge.correct': '{x} de {y} palpites certos',
    'share.button': 'Compartilhar palpites',
    'share.copied': 'Link copiado!',
    'share.confirm': 'Aplicar os palpites compartilhados? Seus palpites atuais serão substituídos.',
    'modal.addCalendar': 'Adicionar à agenda',
    'stats.heroTitle': 'Copa em andamento',
    'stats.heroProgress': '{x} de {y} jogos disputados',
    'stats.tileGoals': 'Gols',
    'stats.tileAvg': 'Gols por jogo',
    'stats.tileBiggestMargin': 'Maior margem',
    'stats.tileCleanSheets': 'Sem sofrer gols',
    'stats.sectionsNav': 'Seções de estatísticas',
    'stats.navOverview': 'Visão geral',
    'stats.navTeams': 'Seleções',
    'stats.navPlayers': 'Jogadores',
    'stats.navRecords': 'Recordes',
    'stats.navComparator': 'Comparador',
    'stats.navArchive': 'Arquivo',
    'stats.overviewTitle': 'Visão geral',
    'stats.played': 'Jogos disputados',
    'stats.decisive': 'Decididas',
    'stats.draws': 'Empates',
    'stats.goalsByPhase': 'Gols por fase',
    'stats.goalsByRound': 'Gols por rodada',
    'stats.matchday': 'Rodada',
    'stats.stageGroup': 'Fase de grupos',
    'stats.verdictTitle': 'Veredito final',
    'stats.runnerUp': 'Vice-campeão',
    'stats.thirdPlace': 'Terceiro lugar',
    'stats.fourthPlace': 'Quarto lugar',
    'stats.teamStatsTitle': 'Estatísticas por time',
    'stats.colGpg': 'G/J',
    'stats.colCS': 'CS',
    'tip.played': 'Jogos disputados',
    'tip.won': 'Vitórias',
    'tip.drawn': 'Empates',
    'tip.lost': 'Derrotas',
    'tip.gf': 'Gols pró (marcados)',
    'tip.ga': 'Gols contra (sofridos)',
    'tip.gd': 'Saldo de gols (pró − contra)',
    'tip.pts': 'Pontos',
    'tip.gpg': 'Gols por jogo (média)',
    'tip.cs': 'Clean sheets (sem sofrer gols)',
    'tip.rank': 'Classificação final — fase alcançada, depois pontos',
    'stats.rankCol': 'Posição',
    'stats.bestAttack': 'Melhor ataque',
    'stats.bestDefense': 'Melhor defesa',
    'stats.mostCleanSheets': 'Mais clean sheets',
    'stats.mostWins': 'Mais vitórias',
    'stats.mostConceded': 'Mais gols sofridos',
    'stats.bestGoalDiff': 'Melhor saldo de gols',
    'stats.leaderPrev': 'Time anterior',
    'stats.leaderNext': 'Próximo time',
    'stats.biggestWin': 'Maior goleada',
    'stats.winStreak': 'Maior sequência de vitórias',
    'stats.championPath': 'Caminho do campeão',
    'stats.recordsTitle': 'Recordes',
    'stats.highScoreMatch': 'Jogo com mais gols',
    'stats.formatDebutsTitle': 'Estreias do formato',
    'stats.debutTeams': 'Primeira Copa com 48 seleções',
    'stats.debutMatches': 'Partidas (eram 64)',
    'stats.debutGroups': 'Grupos',
    'stats.debutR32': 'Uma nova fase eliminatória',
    'stats.debutThird': 'Melhores terceiros avançam',
    'stats.debutChampion': 'Primeiro campeão da era dos 48',
    'stats.comparatorTitle': 'Comparador de times',
    'stats.cmpTeamA': 'Time A',
    'stats.cmpTeamB': 'Time B',
    'stats.prevPage': 'Página anterior',
    'stats.nextPage': 'Próxima página',
    'stats.seeAllMatches': 'Ver todas as partidas',
    'footer.note': `Hub estático feito por fãs ${APP_VERSION}`,
  },
};

let lang = 'en';

export function initI18n() {
  const saved = getPrefs().lang;
  lang = saved ?? (navigator.language?.toLowerCase().startsWith('pt') ? 'pt' : 'en');
  document.documentElement.lang = getLocale();
  applyI18n();
}

export function t(key) {
  return dicts[lang][key] ?? dicts.en[key] ?? key;
}

export function getLang() {
  return lang;
}

export function getLocale() {
  return lang === 'pt' ? 'pt-BR' : 'en-US';
}

export function setLang(next) {
  if (next === lang || !dicts[next]) return;
  lang = next;
  setPref('lang', next);
  document.documentElement.lang = getLocale();
  applyI18n();
  document.dispatchEvent(new CustomEvent('langchange'));
}

export function applyI18n(root = document) {
  for (const el of root.querySelectorAll('[data-i18n]')) {
    el.textContent = t(el.dataset.i18n);
  }
  for (const el of root.querySelectorAll('[data-i18n-aria]')) {
    el.setAttribute('aria-label', t(el.dataset.i18nAria));
  }
}

// Phase labels come from matches.json in English ("Group A", "Round of 32"…);
// translate the known ones, pass anything else through untouched.
const PHASE_KEYS = {
  'Round of 32': 'phase.r32',
  'Round of 16': 'phase.r16',
  Quarterfinals: 'phase.qf',
  Semifinals: 'phase.sf',
  'Third Place': 'phase.third',
  Final: 'phase.final',
};

export function translatePhase(phase) {
  if (phase.startsWith('Group ')) return `${t('phase.group')} ${phase.slice(6)}`;
  const key = PHASE_KEYS[phase];
  return key ? t(key) : phase;
}
