// app.jsx — 16x0 state machine
const { useState: useAppSt, useEffect: useAppEf, useCallback: useAppCb } = React;

function resultStageLabel(stage) {
  if (stage === 'swiss') return 'Fase suíça';
  if (stage === 'qf') return 'Quartas';
  if (stage === 'sf') return 'Semifinal';
  if (stage === 'final') return 'Grande final';
  return 'Série';
}

function resultMapName(mapId) {
  return window.MAPS?.find(m => m.id === mapId)?.name || mapId || 'Mapa';
}

function buildUserSeriesSummary({ series, mapResults, mySide, opponent, stage, matchFormat }) {
  const myWins = mySide === 'A' ? series.wA : series.wB;
  const oppWins = mySide === 'A' ? series.wB : series.wA;
  const format = window.getMatchFormat(matchFormat || series.matchFormat || 'MR16');
  const maps = (mapResults || []).map((result, index) => {
    const mine = mySide === 'A' ? result.scoreA : result.scoreB;
    const theirs = mySide === 'A' ? result.scoreB : result.scoreA;
    const winScore = result.winScore || format.winScore;
    const overtime = Math.max(result.scoreA || 0, result.scoreB || 0) > winScore;
    return {
      mapId: result.mapId || series.maps?.[index],
      name: resultMapName(result.mapId || series.maps?.[index]),
      score:[mine, theirs],
      won: result.winner === mySide,
      overtime,
    };
  });
  return {
    stage,
    stageLabel: resultStageLabel(stage),
    bo: series.bo,
    matchFormat: format.id,
    opponentName: opponent?.name || 'Adversário',
    opponentYear: opponent?.year,
    score:[myWins, oppWins],
    won: myWins > oppWins,
    maps,
  };
}

function userSwissRecord(swissState, myTeamId) {
  const my = swissState?.teams?.find(t => t.id === myTeamId);
  if (!my?.swiss) return null;
  return `${my.swiss.wins}-${my.swiss.losses}`;
}

function userSwissSeriesRecord(swissState, myTeamId) {
  let wins = 0, losses = 0;
  swissState?.history?.forEach(round => {
    round.matches?.forEach(match => {
      if (!match.user) return;
      if (match.winnerId === myTeamId) wins++;
      else losses++;
    });
  });
  return wins || losses ? `${wins}-${losses}` : null;
}

function playoffMatchesForTeam(bracketState, myTeamId) {
  if (!bracketState || !myTeamId) return [];
  return [...(bracketState.qf || []), ...(bracketState.sf || []), bracketState.final]
    .filter(match => match?.result && (match.teamA?.id === myTeamId || match.teamB?.id === myTeamId));
}

function buildCampaignSummary({ type, swissState, bracketState, myTeamId, seriesSummary }) {
  const playoffMatches = playoffMatchesForTeam(bracketState, myTeamId);
  const playoffWins = playoffMatches.filter(match => {
    const mySide = match.teamA?.id === myTeamId ? 'A' : 'B';
    return match.result?.winner === mySide;
  }).length;
  const playoffLosses = playoffMatches.length - playoffWins;
  const swissRecord = userSwissRecord(swissState, myTeamId);
  const swissSeries = userSwissSeriesRecord(swissState, myTeamId) || swissRecord;
  const totalWins = (swissSeries ? parseInt(swissSeries.split('-')[0], 10) || 0 : 0) + playoffWins;
  const totalLosses = (swissSeries ? parseInt(swissSeries.split('-')[1], 10) || 0 : 0) + playoffLosses;
  const path = [];
  if (swissRecord) path.push({ label:'Suíço', value:swissRecord });
  if (playoffMatches.some(m => m.id?.startsWith('qf'))) path.push({ label:'Quartas', value:'V' });
  if (playoffMatches.some(m => m.id?.startsWith('sf'))) path.push({ label:'Semi', value:'V' });
  if (type === 'champion') path.push({ label:'Final', value:'V' });
  else if (seriesSummary?.stage && seriesSummary.stage !== 'swiss') path.push({ label:seriesSummary.stageLabel, value:'D' });
  return {
    outcome:type === 'champion' ? 'Campeão do Major' : 'Campanha encerrada',
    stageLabel:seriesSummary?.stageLabel,
    swissRecord,
    swissSeries,
    playoffRecord:playoffMatches.length ? `${playoffWins}-${playoffLosses}` : null,
    totalRecord:(totalWins || totalLosses) ? `${totalWins}-${totalLosses}` : null,
    path,
  };
}

function App() {
  const [t, setTweak] = useTweaks({ accent:'#f4a523', speed:'Normal' });
  const [locale, setLocaleState] = useAppSt(window.I18N?.getLocale?.() || 'pt-BR');
  const [phase, setPhase] = useAppSt('home');

  // Draft state
  const [session,   setSession]   = useAppSt(null);
  const [myPlayers, setMyPlayers] = useAppSt([]);
  const [draftMode, setDraftMode] = useAppSt('scout');
  const [matchFormat, setMatchFormat] = useAppSt('MR16');
  const [matchSpeed, setMatchSpeed] = useAppSt('Normal');
  const [draftReady, setDraftReady] = useAppSt(false);
  const [teamName, setTeamName] = useAppSt(window.I18N?.text?.('team.default') || 'Meu Time');

  // Bracket state
  const [bracket,   setBracket]   = useAppSt(null);
  const [myTeamObj, setMyTeamObj] = useAppSt(null);
  const [opTeams,   setOpTeams]   = useAppSt([]);
  const [bracketStage, setBracketStage] = useAppSt('qf');
  const [swiss, setSwiss] = useAppSt(null);

  // Match state
  const [matchCtx,  setMatchCtx]  = useAppSt(null);
  const [series,    setSeries]    = useAppSt(null); // { matchId, mapResults, maps, wA, wB }

  // Result state
  const [resultCtx, setResultCtx] = useAppSt(null);
  const [campaignSeed, setCampaignSeed] = useAppSt(null);
  const [routeShareData, setRouteShareData] = useAppSt(() => window.readShareRoute?.() || null);
  const screenKey = [
    phase,
    phase === 'draft' ? (draftReady ? 'summary' : 'recruit') : '',
    phase === 'swiss' ? `${swiss?.round || 0}-${swiss?.status || ''}` : '',
    phase === 'bracket' ? bracketStage : '',
    phase === 'match' ? `${matchCtx?.matchId || ''}-${matchCtx?.mapIndex || 0}-${matchCtx?.map || ''}` : '',
    phase === 'result' ? resultCtx?.type || '' : '',
  ].join('|');

  // Sync accent
  useAppEf(() => {
    document.documentElement.style.setProperty('--accent', t.accent);
  }, [t.accent]);

  useAppEf(() => {
    const unsubscribe = window.I18N?.subscribe?.(setLocaleState);
    window.I18N?.apply?.();
    return unsubscribe;
  }, []);

  useAppEf(() => {
    window.scrollToTopOnMobile?.();
    window.I18N?.scheduleApply?.();
  }, [screenKey]);

  useAppEf(() => {
    window.I18N?.scheduleApply?.();
  }, [locale]);

  useAppEf(() => {
    const syncRoute = (event) => setRouteShareData(event.detail || null);
    const syncHash = () => setRouteShareData(window.readShareRoute?.() || null);
    window.addEventListener('share-route-change', syncRoute);
    window.addEventListener('hashchange', syncHash);
    window.addEventListener('popstate', syncHash);
    syncHash();
    return () => {
      window.removeEventListener('share-route-change', syncRoute);
      window.removeEventListener('hashchange', syncHash);
      window.removeEventListener('popstate', syncHash);
    };
  }, []);

  function defaultTeamName() {
    return window.I18N?.text?.('team.default') || 'Meu Time';
  }

  function changeLocale(nextLocale) {
    window.I18N?.setLocale?.(nextLocale);
    setLocaleState(window.I18N?.getLocale?.() || nextLocale);
  }

  // ── Start draft ──────────────────────────────────────────────────────────
  function startDraft(options = {}) {
    window.clearShareRoute?.();
    setRouteShareData(null);
    const mode = options.draftMode || 'scout';
    const cleanTeamName = String(options.teamName || defaultTeamName()).trim().slice(0, 28) || defaultTeamName();
    const sess = mode === 'builder' ? null : window.createDraftSession();
    const nextCampaignSeed = sess?.seed || (Date.now() % 0xFFFFFF);
    const selectedFormat = window.getMatchFormat(options.matchFormat || 'MR16').id;
    setDraftMode(mode);
    setMatchFormat(selectedFormat);
    setMatchSpeed('Normal');
    setDraftReady(false);
    setTeamName(cleanTeamName);
    setCampaignSeed(nextCampaignSeed);
    setMyPlayers([]);
    setSession(sess);
    setPhase(mode === 'builder' ? 'builder' : 'draft');
  }

  // ── Draft complete → build bracket ──────────────────────────────────────
  function onDraftComplete(players, selectedFormat = 'MR16') {
    setDraftReady(false);
    const format = window.getMatchFormat(selectedFormat).id;
    const overall = window.calcTeamOverall(players);
    const activeCampaignSeed = campaignSeed || session?.seed || (Date.now() % 0xFFFFFF);
    setCampaignSeed(activeCampaignSeed);
    const myTeam = { id:'my_team', name:teamName || defaultTeamName(), year:'Mix', era:'Mix',
      region:'🌍 Mix', isMyTeam:true, overall, players };

    myTeam.campaignSeed = activeCampaignSeed;

    // Swiss field: keep a realistic spread, including weaker teams.
    const selectedTeamIds = new Set(players.map(p => p.team));
    const candidates = [];
    for (const t of window.DRAFT_TEAMS) {
      if (selectedTeamIds.has(t.id)) continue;
      const ps = window.getTeamPlayers(t.id);
      candidates.push({ ...t, players: ps, overall: window.calcTeamOverall(ps) });
    }
    const rankedCandidates = candidates.sort((a, b) => b.overall - a.overall);
    const lowerSeeds = rankedCandidates.slice(-5);
    const upperPool = rankedCandidates.slice(0, -5);
    for (let i = upperPool.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [upperPool[i], upperPool[j]] = [upperPool[j], upperPool[i]];
    }
    const all = [...upperPool.slice(0, Math.max(0, 15 - lowerSeeds.length)), ...lowerSeeds];
    myTeam.matchFormat = format;
    const sw = window.buildSwissStage(myTeam, all, Number(activeCampaignSeed) % 0xFFFF, format);
    setMatchFormat(format);
    setMyPlayers(players);
    setMyTeamObj(myTeam);
    setOpTeams(all);
    setSwiss(sw);
    setBracket(null);
    setBracketStage('qf');
    setPhase('swiss');
  }

  function onPlaySwissMatch(matchNode) {
    if (!matchNode?.teamA || !matchNode?.teamB) return;
    const format = swiss?.matchFormat || matchFormat || 'MR16';
    const maps = window.pickMaps(Date.now() % 99999, 3);
    const seed = (Date.now() % 0xFFFF) + matchNode.id.length * 173;
    const ctx = {
      matchId: matchNode.id,
      teamA: matchNode.teamA,
      teamB: matchNode.teamB,
      bo: matchNode.bo,
      map: maps[0],
      mapIndex: 0,
      seriesScore: [0, 0],
      maps,
      seed,
      matchFormat:format,
    };
    setSeries({ matchId: matchNode.id, maps, wA:0, wB:0,
      mapResults:[], bo:matchNode.bo, stage:'swiss', matchNode, matchFormat:format });
    setMatchCtx(ctx);
    setPhase('match');
  }

  function onAdvanceSwiss() {
    const finishedSwiss = window.finishSwissForPlayoffs(swiss);
    const playoffTeams = window.getSwissPlayoffTeams(finishedSwiss);
    const br = {
      ...window.buildPlayoffBracket(playoffTeams, myTeamObj.id),
      matchFormat: finishedSwiss.matchFormat || matchFormat || 'MR16',
    };
    setSwiss(finishedSwiss);
    setBracket(br);
    setBracketStage('qf');
    setPhase('bracket');
  }

  // ── Play a bracket match ─────────────────────────────────────────────────
  function onPlayMatch(matchNode, stage) {
    if (!matchNode.teamA || !matchNode.teamB) return;
    const format = bracket?.matchFormat || matchFormat || 'MR16';
    const maps = window.pickMaps(Date.now() % 99999, 3);
    const ctx = {
      matchId: matchNode.id,
      teamA: matchNode.teamA,
      teamB: matchNode.teamB,
      bo: matchNode.bo,
      map: maps[0],
      mapIndex: 0,
      seriesScore: [0, 0],
      maps,
      seed: (Date.now() % 0xFFFF) + matchNode.id.charCodeAt(0) * 137,
      matchFormat:format,
    };
    setSeries({ matchId: matchNode.id, maps, wA:0, wB:0, mapResults:[], bo:matchNode.bo, stage, matchFormat:format });
    setMatchCtx(ctx);
    setPhase('match');
  }

  // ── Map ends ─────────────────────────────────────────────────────────────
  function onMatchComplete(mapResult) {
    const newResults = [...series.mapResults, mapResult];
    const newWA = series.wA + (mapResult.winner === 'A' ? 1 : 0);
    const newWB = series.wB + (mapResult.winner === 'B' ? 1 : 0);
    const bo = series.bo;
    const needed = Math.ceil(bo / 2);
    const seriesDone = newWA >= needed || newWB >= needed;
    const completedSeries = { ...series, wA:newWA, wB:newWB, mapResults:newResults };

    if (seriesDone) {
      if (series.stage === 'swiss') {
        const current = series.matchNode;
        const mySide = current.teamA?.id === myTeamObj?.id ? 'A' : 'B';
        const opponent = mySide === 'A' ? current.teamB : current.teamA;
        const normalizedMapResult = { ...mapResult, mySide };
        const seriesSummary = buildUserSeriesSummary({
          series:completedSeries,
          mapResults:newResults,
          mySide,
          opponent,
          stage:'swiss',
          matchFormat:series.matchFormat || matchFormat,
        });
        const nextSwiss = window.completeSwissRound(
          swiss,
          mapResult,
          { bo, wA:newWA, wB:newWB, mapResults:newResults }
        );
        setSwiss(nextSwiss);
        setSeries(null);
        setMatchCtx(null);

        const myAfter = nextSwiss.teams.find(t => t.id === myTeamObj?.id);
        if (myAfter?.swiss?.losses >= 3) {
          setResultCtx({ type:'eliminated', opponent,
            matchResult: normalizedMapResult, isPerfect:false,
            seriesSummary,
            campaignSummary:buildCampaignSummary({
              type:'eliminated',
              swissState:nextSwiss,
              bracketState:null,
              myTeamId:myTeamObj?.id,
              seriesSummary,
            }) });
          setPhase('result');
          return;
        }

        setPhase('swiss');
        return;
      }

      // Update bracket
      const seriesWinner = newWA >= needed ? 'A' : 'B';
      const match = findMatch(bracket, series.matchId);
      const winningTeam = seriesWinner === 'A' ? match.teamA : match.teamB;
      const losingTeam  = seriesWinner === 'A' ? match.teamB : match.teamA;
      const mySide = match.teamA?.id === myTeamObj?.id ? 'A' : 'B';
      const opponent = mySide === 'A' ? match.teamB : match.teamA;
      const normalizedMapResult = { ...mapResult, mySide };
      const seriesSummary = buildUserSeriesSummary({
        series:completedSeries,
        mapResults:newResults,
        mySide,
        opponent,
        stage:series.stage,
        matchFormat:series.matchFormat || matchFormat,
      });

      const updatedBracket = applyResult(bracket, series.matchId, {
        winner: seriesWinner, wA: newWA, wB: newWB,
        scoreA: mapResult.scoreA, scoreB: mapResult.scoreB, bo,
        maps:series.maps,
        mapResults:newResults,
        matchFormat:series.matchFormat || matchFormat,
      });

      // Check if player's team lost
      const myLost = losingTeam?.id === myTeamObj?.id;
      if (myLost) {
        setBracket(updatedBracket);
        setResultCtx({ type:'eliminated', opponent,
          matchResult: normalizedMapResult, isPerfect: false,
          seriesSummary,
          campaignSummary:buildCampaignSummary({
            type:'eliminated',
            swissState:swiss,
            bracketState:updatedBracket,
            myTeamId:myTeamObj?.id,
            seriesSummary,
          }) });
        setPhase('result');
        return;
      }

      // Check if my team won the final
      if (series.matchId === 'final' && winningTeam?.id === myTeamObj?.id) {
        setBracket(updatedBracket);
        const perfect = newResults.some(r => r.isPerfect && r.winner === mySide);
        setResultCtx({ type:'champion', opponent, matchResult: normalizedMapResult, isPerfect: perfect,
          seriesSummary,
          campaignSummary:buildCampaignSummary({
            type:'champion',
            swissState:swiss,
            bracketState:updatedBracket,
            myTeamId:myTeamObj?.id,
            seriesSummary,
          }) });
        setPhase('result');
        return;
      }

      // Auto-resolve the OTHER matches of this stage (CPU vs CPU) so the
      // next round always has concrete opponents — no TBD dead-ends.
      let working = updatedBracket;
      const stageList = series.stage === 'qf' ? working.qf
                      : series.stage === 'sf' ? working.sf
                      : [working.final];
      stageList.forEach(m => {
        if (m.id === series.matchId || m.result || !m.teamA || !m.teamB) return;
        working = applyResult(working, m.id, simulateCpuSeries(m, series.matchFormat || matchFormat));
      });
      setBracket(working);

      // Determine next stage
      const nextStage = series.stage === 'qf' ? 'sf' : series.stage === 'sf' ? 'final' : 'done';
      setBracketStage(nextStage === 'done' ? 'final' : nextStage);
      setPhase('bracket');
    } else {
      // Next map in series
      const nextIdx = (matchCtx.mapIndex || 0) + 1;
      setMatchCtx({
        ...matchCtx, map: series.maps[nextIdx], mapIndex: nextIdx,
        seriesScore: [newWA, newWB],
      });
      setSeries({ ...series, wA: newWA, wB: newWB, mapResults: newResults });
    }
  }

  function restart() {
    window.clearShareRoute?.();
    setRouteShareData(null);
    setPhase('home'); setSession(null); setMyPlayers([]); setBracket(null);
    setMyTeamObj(null); setOpTeams([]); setSwiss(null); setMatchCtx(null);
    setSeries(null); setResultCtx(null); setDraftMode('scout'); setMatchFormat('MR16');
    setMatchSpeed('Normal'); setDraftReady(false); setTeamName(defaultTeamName()); setCampaignSeed(null);
  }

  const subLabel =
    phase === 'builder' ? 'LABORATÓRIO' :
    phase === 'draft'   ? (draftReady ? 'ELENCO FECHADO' : 'DRAFT — SORTEIO') :
    phase === 'swiss'   ? 'MAJOR · FASE SUÍÇA' :
    phase === 'bracket' ? ('MAJOR · ' + bracketStage.toUpperCase()) :
    phase === 'match'   ? (matchCtx ? matchCtx.teamA.name + ' vs ' + matchCtx.teamB.name : 'PARTIDA') :
    phase === 'result'  ? 'RESULTADO' : null;

  return (
    <div style={{ minHeight:'100vh', background:'var(--bg-1)' }}>
      <window.GameHeader phase={phase} subLabel={subLabel}
        locale={locale} onLocaleChange={changeLocale} />

      {phase === 'home'    && <window.HomeView    onStart={startDraft} />}
      {phase === 'builder' && (
        <window.FreeBuilderView
          teamName={teamName}
          defaultMatchFormat={matchFormat}
          onComplete={onDraftComplete}
        />
      )}
      {phase === 'draft'   && session && (
        <window.DraftView session={session} onDraftComplete={onDraftComplete}
          draftMode={draftMode} defaultMatchFormat={matchFormat}
          teamName={teamName}
          onSummaryStateChange={setDraftReady} />
      )}
      {phase === 'swiss' && swiss && (
        <window.SwissView swiss={swiss} myTeamId={myTeamObj?.id}
          onPlayMatch={onPlaySwissMatch} onAdvance={onAdvanceSwiss} />
      )}
      {phase === 'bracket' && bracket && (
        <window.MajorView bracket={bracket} myTeamId={myTeamObj?.id}
          onPlayMatch={onPlayMatch} stage={bracketStage} />
      )}
      {phase === 'match'   && matchCtx && (
        <window.MatchView
          key={`${matchCtx.matchId}-${matchCtx.mapIndex || 0}-${matchCtx.map}`}
          matchContext={matchCtx}
          onMatchComplete={onMatchComplete}
          speedPreference={matchSpeed}
          onSpeedChange={setMatchSpeed}
        />
      )}
      {phase === 'result'  && resultCtx && (
        <window.ResultView
          type={resultCtx.type}
          myTeam={myTeamObj}
          opponent={resultCtx.opponent}
          matchResult={resultCtx.matchResult}
          isPerfect={resultCtx.isPerfect}
          seriesSummary={resultCtx.seriesSummary}
          campaignSummary={resultCtx.campaignSummary}
          onPlayAgain={startDraft}
          onHome={restart}
        />
      )}

      {routeShareData && window.ShareOverlay && (
        <window.ShareOverlay
          data={routeShareData}
          standalone
          onClose={() => {
            window.clearShareRoute?.();
            setRouteShareData(null);
          }}
        />
      )}

      <TweaksPanel>
        <TweakSection label="Aparência" />
        <TweakColor label="Acento" value={t.accent}
          options={['#f4a523','#4a9eff','#3ec9a7','#d45ad4']}
          onChange={v => setTweak('accent', v)} />
      </TweaksPanel>
    </div>
  );
}

// ── Bracket helpers ──────────────────────────────────────────────────────────

function simulateCpuSeries(m, formatId = 'MR16') {
  const seed = (m.id.charCodeAt(0) * 131 + (m.id.charCodeAt(2) || 7) * 17 + Date.now()) % 0xFFFF;
  const maps = window.pickMaps(seed, 3);
  if (m.bo === 1) {
    const r = window.simulateMatch(m.teamA.players, m.teamB.players, maps[0], seed, formatId);
    return { winner: r.winner, wA: r.winner === 'A' ? 1 : 0, wB: r.winner === 'B' ? 1 : 0,
      scoreA: r.scoreA, scoreB: r.scoreB, bo: 1 };
  }
  const r = window.simulateBO3(m.teamA.players, m.teamB.players, maps, seed, formatId);
  const last = r.results[r.results.length - 1];
  return { winner: r.seriesWinner, wA: r.wA, wB: r.wB,
    scoreA: last.scoreA, scoreB: last.scoreB, bo: 3 };
}

function findMatch(bracket, matchId) {
  return [...bracket.qf, ...bracket.sf, bracket.final].find(m => m?.id === matchId);
}

function applyResult(bracket, matchId, result) {
  const qf    = bracket.qf.map(m => m.id === matchId ? { ...m, result } : m);
  const sf    = bracket.sf.map(m => m.id === matchId ? { ...m, result } : m);
  const final = bracket.final.id === matchId ? { ...bracket.final, result } : bracket.final;

  // Propagate winners to next round
  function winner(m) {
    if (!m.result) return null;
    return m.result.winner === 'A' ? m.teamA : m.teamB;
  }

  // SF gets winners from QF
  const sf2 = sf.map(s => {
    const srcs = s.sources.map(sid => qf.find(q => q.id === sid) || sf.find(x => x.id === sid));
    const w0 = srcs[0] ? winner(srcs[0]) : null;
    const w1 = srcs[1] ? winner(srcs[1]) : null;
    return { ...s, teamA: w0 || s.teamA, teamB: w1 || s.teamB };
  });

  // Final gets winners from SF
  const finalSrcs = final.sources.map(sid => sf2.find(s => s.id === sid));
  const fw0 = finalSrcs[0] ? winner(finalSrcs[0]) : null;
  const fw1 = finalSrcs[1] ? winner(finalSrcs[1]) : null;
  const final2 = { ...final, teamA: fw0 || final.teamA, teamB: fw1 || final.teamB };

  return { ...bracket, qf, sf: sf2, final: final2 };
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
