import type { EventBus } from './EventBus';

export interface ClockConfig {
  nightClockMinutes: number; // in-game minutes per night (design: 360 = 9PM→3AM)
  nightRealMinutes: number;  // real minutes a night takes (design: ~13)
  nightDate: string;         // ISO date of the night — anchors ID birthday math
}

export const DEFAULT_CLOCK: ClockConfig = {
  nightClockMinutes: 360,
  nightRealMinutes: 13,
  nightDate: '2026-07-18', // Saturday, night 1
};

// Engine-agnostic clock: feed it real elapsed ms (from Phaser's update or a
// test harness), it emits clock:tick once per in-game minute.
export class GameClock {
  private elapsedRealMs = 0;
  private emittedMin = -1;
  private running = false;

  constructor(
    private readonly bus: EventBus,
    public readonly config: ClockConfig = DEFAULT_CLOCK,
  ) {}

  get clockMin(): number {
    const ratio = this.config.nightClockMinutes / (this.config.nightRealMinutes * 60_000);
    return Math.min(this.config.nightClockMinutes, Math.floor(this.elapsedRealMs * ratio));
  }

  get isOver(): boolean {
    return this.clockMin >= this.config.nightClockMinutes;
  }

  /** "9:47 PM" style label; clock starts at 21:00. */
  get label(): string {
    const total = 21 * 60 + this.clockMin;
    const h24 = Math.floor(total / 60) % 24;
    const m = total % 60;
    const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
    const ampm = h24 < 12 ? 'AM' : 'PM';
    return `${h12}:${String(m).padStart(2, '0')} ${ampm}`;
  }

  get nightDate(): Date {
    return new Date(`${this.config.nightDate}T00:00:00`);
  }

  start(): void {
    this.running = true;
  }

  pause(): void {
    this.running = false;
  }

  update(deltaMs: number): void {
    if (!this.running || this.isOver) return;
    this.elapsedRealMs += deltaMs;
    const min = this.clockMin;
    while (this.emittedMin < min) {
      this.emittedMin++;
      this.bus.emit('clock:tick', { clockMin: this.emittedMin });
    }
  }
}

/** Full years between an ISO DOB and a night date. The ID minigame's math. */
export function ageOn(dobIso: string, nightDate: Date): number {
  const dob = new Date(`${dobIso}T00:00:00`);
  let age = nightDate.getFullYear() - dob.getFullYear();
  const beforeBirthday =
    nightDate.getMonth() < dob.getMonth() ||
    (nightDate.getMonth() === dob.getMonth() && nightDate.getDate() < dob.getDate());
  if (beforeBirthday) age--;
  return age;
}
