import * as bus from './bus.js';
import * as store from './store.js';

const worlds = ['rank', 'social', 'play', 'tournaments', 'profile'];
const sceneStacks = { rank: [], social: [], play: [], tournaments: [], profile: [] };
const sceneRegistry = {};
let currentWorld = 'play';
let container = null;
let isTransitioning = false;
let pendingPush = null; // queued navigation during transition

export function init() {
  container = document.getElementById('scene-container');
  currentWorld = store.get('activeWorld') || 'play';

  bus.on('navigate', ({ world, scene, params }) => {
    if (world && world !== currentWorld) {
      switchWorld(world);
    }
    if (scene) {
      push(scene, params);
    }
  });
}

export function register(id, mountFn, unmountFn) {
  sceneRegistry[id] = { mount: mountFn, unmount: unmountFn };
}

export function switchWorld(world, resetToRoot = false) {
  if (!worlds.includes(world)) return;
  if (world === currentWorld && !resetToRoot) return;

  // Unmount current scene before switching
  const prevStack = sceneStacks[currentWorld];
  const prevScene = prevStack[prevStack.length - 1];
  if (prevScene && sceneRegistry[prevScene.id]?.unmount) {
    sceneRegistry[prevScene.id].unmount();
  }

  const prev = currentWorld;
  currentWorld = world;
  store.set('activeWorld', world);
  bus.emit('world:changed', { from: prev, to: world });

  const stack = sceneStacks[world];
  if (resetToRoot && stack.length > 1) {
    sceneStacks[world] = [stack[0]];
    renderScene(stack[0]);
  } else if (stack.length > 0) {
    renderScene(stack[stack.length - 1]);
  }
}

export function push(sceneId, params = {}) {
  if (!sceneRegistry[sceneId]) return;

  // Queue navigation if a transition is in progress
  if (isTransitioning) {
    pendingPush = { sceneId, params };
    return;
  }

  const stack = sceneStacks[currentWorld];
  const prev = stack[stack.length - 1];
  stack.push({ id: sceneId, params });

  transitionTo(sceneId, params, prev?.id);
}

export function pop() {
  if (isTransitioning) return;
  const stack = sceneStacks[currentWorld];
  if (stack.length <= 1) return;

  const leaving = stack.pop();
  const target = stack[stack.length - 1];
  transitionTo(target.id, target.params, leaving.id, true);
}

export function replace(sceneId, params = {}) {
  const stack = sceneStacks[currentWorld];
  const prev = stack[stack.length - 1];
  if (prev && sceneRegistry[prev.id]?.unmount) {
    sceneRegistry[prev.id].unmount();
  }
  stack[stack.length - 1] = { id: sceneId, params };
  renderScene({ id: sceneId, params });
}

export function setRoot(world, sceneId, params = {}) {
  sceneStacks[world] = [{ id: sceneId, params }];
  if (world === currentWorld) {
    renderScene({ id: sceneId, params });
  }
}

export function getCurrentWorld() { return currentWorld; }
export function getWorlds() { return worlds; }

function transitionTo(sceneId, params, prevId, isBack = false) {
  isTransitioning = true;

  if (prevId && sceneRegistry[prevId]?.unmount) {
    sceneRegistry[prevId].unmount();
  }

  renderScene({ id: sceneId, params }, isBack);

  const sceneEl = container.querySelector('.scene');
  if (sceneEl) {
    sceneEl.addEventListener('animationend', () => { finishTransition(); }, { once: true });
    setTimeout(() => { finishTransition(); }, 400);
  } else {
    finishTransition();
  }
}

function finishTransition() {
  if (!isTransitioning) return; // already finished (animationend + timeout race)
  isTransitioning = false;

  // Flush any queued navigation
  if (pendingPush) {
    const { sceneId, params } = pendingPush;
    pendingPush = null;
    push(sceneId, params);
  }
}

function renderScene(entry, isBack = false) {
  if (!entry || !sceneRegistry[entry.id]) return;

  container.innerHTML = '';
  const el = document.createElement('div');
  el.className = `scene scene-enter`;
  container.appendChild(el);

  sceneRegistry[entry.id].mount(el, entry.params || {});
}

export function enterGameMode() {
  container.classList.add('game-mode');
  bus.emit('gamemode:enter');
}

export function exitGameMode() {
  container.classList.remove('game-mode');
  bus.emit('gamemode:exit');
}
