import { eventBus } from '../lib/eventBus.js';
import { normalizeWorldFlag } from '../lib/utils.js';
import { contentLoader } from './ContentLoader.js';
import { saveState } from './SaveState.js';
import { narrativePhaseTracker } from './NarrativePhaseTracker.js';

class QuestEngine {
  constructor() {
    this._quests = new Map();
  }

  initialize(state) {
    this._quests = new Map(
      Object.entries(state.quests ?? {}).map(([questId, entry]) => [questId, this._normalizeEntry(entry)])
    );

    if (this._quests.size === 0) {
      this._activateInitialQuests();
    }
  }

  getState(questId) {
    return this.getEntry(questId)?.state ?? 'locked';
  }

  getEntry(questId) {
    const entry = this._quests.get(questId);
    if (!entry) {
      return null;
    }

    return { ...entry };
  }

  getAllEntries() {
    return [...this._quests.entries()].map(([questId, entry]) => [questId, { ...entry }]);
  }

  isActive(questId) {
    return this.getState(questId) === 'active';
  }

  isCompleted(questId) {
    return this.getState(questId) === 'completed';
  }

  canActivate(questId, state = saveState.get()) {
    const quest = contentLoader.get('quests', questId);
    if (!quest) {
      return false;
    }

    const requirements = Array.isArray(quest.unlock_requirements) ? quest.unlock_requirements : [];
    const worldFlags = new Set(state?.world_flags ?? []);
    return requirements.every((requirement) => worldFlags.has(normalizeWorldFlag(requirement)));
  }

  activate(questId) {
    const currentState = this.getState(questId);
    if (currentState === 'active' || currentState === 'completed' || currentState === 'failed') {
      return currentState;
    }

    const now = new Date().toISOString();
    const existing = this._quests.get(questId);
    this._quests.set(questId, {
      state: 'active',
      started_at: existing?.started_at ?? now
    });
    this._persist();
    eventBus.emit('quest:activated', { questId });
    return 'active';
  }

  complete(questId, metadata = {}) {
    const now = new Date().toISOString();
    const existing = this._quests.get(questId);

    this._quests.set(questId, {
      state: 'completed',
      started_at: existing?.started_at ?? now,
      completed_at: now,
      branch_id: metadata.branchId ?? existing?.branch_id ?? null
    });
    this._persist();
    narrativePhaseTracker.advance(questId);
    eventBus.emit('quest:completed', { questId, branchId: metadata.branchId ?? null });
    return 'completed';
  }

  _activateInitialQuests() {
    for (const [questId, quest] of contentLoader.quests) {
      const requirements = Array.isArray(quest.unlock_requirements) ? quest.unlock_requirements : [];
      if (requirements.length === 0) {
        this.activate(questId);
      }
    }
  }

  _persist() {
    saveState.set({ quests: Object.fromEntries(this._quests) });
  }

  _normalizeEntry(entry) {
    if (typeof entry === 'string') {
      return { state: entry };
    }

    return {
      state: entry?.state ?? 'locked',
      started_at: entry?.started_at ?? null,
      completed_at: entry?.completed_at ?? null,
      branch_id: entry?.branch_id ?? null
    };
  }
}

export const questEngine = new QuestEngine();
