import type { AchievementDef } from '../types'

type UnlockCallback = (achievement: AchievementDef) => void

export class AchievementSystem {
  private definitions: AchievementDef[] = []
  private unlockedIds: Set<string> = new Set()
  private onUnlock: UnlockCallback | null = null
  private toastQueue: string[] = []
  private toastActive = false

  init(defs: AchievementDef[], alreadyUnlocked: string[]) {
    this.definitions = defs
    this.unlockedIds = new Set(alreadyUnlocked)
    this.toastQueue = []
    this.toastActive = false
  }

  setUnlockCallback(cb: UnlockCallback) {
    this.onUnlock = cb
  }

  check(variables: Record<string, number>) {
    for (const def of this.definitions) {
      if (this.unlockedIds.has(def.id)) continue

      const cond = def.condition
      const val = variables[cond.variable] ?? 0
      let matched = false

      switch (cond.op) {
        case '==': matched = val === cond.value; break
        case '!=': matched = val !== cond.value; break
        case '>': matched = val > (cond.value as number); break
        case '<': matched = val < (cond.value as number); break
        case '>=': matched = val >= (cond.value as number); break
        case '<=': matched = val <= (cond.value as number); break
      }

      if (matched) {
        this.unlockedIds.add(def.id)
        this.onUnlock?.(def)
        this.enqueueToast(def.id)
      }
    }
  }

  private enqueueToast(id: string) {
    this.toastQueue.push(id)
    if (!this.toastActive) {
      this.showNextToast()
    }
  }

  private showNextToast() {
    if (this.toastQueue.length === 0) {
      this.toastActive = false
      return
    }
    this.toastActive = true
    // toast is shown by the UI layer watching toastQueue
    // UI calls toastDismissed() when the toast animation finishes
  }

  getToastQueue(): string[] {
    return [...this.toastQueue]
  }

  toastDismissed(id: string) {
    this.toastQueue = this.toastQueue.filter((i) => i !== id)
    this.showNextToast()
  }

  getUnlockedIds(): string[] {
    return [...this.unlockedIds]
  }

  getDefinitions(): AchievementDef[] {
    return this.definitions
  }
}
