import { Server } from 'socket.io'
import { appLogger } from '../utilities/logger'
import { getRootPath } from '../utilities/storage'
import { readJsonValue, setJsonValue } from '../utilities/json'

class DateManager {
  private static readonly GAME_SPEED = 8 // 24 game hours / 3 real hours
  private static readonly UPDATE_INTERVAL = 1000 // 1 second

  private io: Server | null = null
  private intervalId: NodeJS.Timeout | null = null
  private currentDate: Date = new Date()

  public async boot(io: Server): Promise<void> {
    this.io = io
    await this.loadDate()
    this.startDateLoop()
    appLogger.info('Date manager loaded')
  }

  public stop(): void {
    if (this.intervalId) {
      clearInterval(this.intervalId)
      this.intervalId = null
    }
  }

  private async loadDate(): Promise<void> {
    try {
      const dateString = await readJsonValue<string>(this.getWorldFilePath(), 'date')
      this.currentDate = new Date(dateString)
    } catch (error) {
      appLogger.error(`Failed to load date: ${error instanceof Error ? error.message : String(error)}`)
      this.currentDate = new Date() // Use current date as fallback
    }
  }

  private startDateLoop(): void {
    this.intervalId = setInterval(() => {
      this.advanceGameTime()
      this.emitDate()
      this.saveDate()
    }, DateManager.UPDATE_INTERVAL)
  }

  private advanceGameTime(): void {
    const advanceMilliseconds = DateManager.GAME_SPEED * DateManager.UPDATE_INTERVAL
    this.currentDate = new Date(this.currentDate.getTime() + advanceMilliseconds)
  }

  private emitDate(): void {
    this.io?.emit('date', this.currentDate)
  }

  private async saveDate(): Promise<void> {
    try {
      await setJsonValue(this.getWorldFilePath(), 'date', this.currentDate)
    } catch (error) {
      appLogger.error(`Failed to save date: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  private getWorldFilePath(): string {
    return getRootPath('data', 'world.json')
  }
}

export default new DateManager()