type PreventNotifications = {
  [key: string]: true | PreventNotifications
}
type RacletteFrontendConfig = {
  name?: string
  meta?: {
    title?: string
  }
  i18n: {
    locales: string[]
    priorities: Record<string, number>
  }
  pleaseLetUsAdvertiseOurselves?: boolean
  advertiseYourself?: string
  preventNotifications?: PreventNotifications
  global?: {
    requireAuthentication: boolean
    authTokenExpiryDays: number
  }
  plugins?: string[]
  additionalPluginPaths?: string[]
}

// Cache for configuration
let cachedConfig: RacletteFrontendConfig

export class ConfigService {
  private config: RacletteFrontendConfig

  constructor() {
    this.config = {}
  }

  async init() {
    await this.refreshConfig()

    return this
  }

  // Refresh the config (useful for hot reloading)
  public async refreshConfig(): Promise<void> {
    try {
      // TODO: revisit caching topic here
      const configModule = await import("../../../raclette.config.js")

      this.config = configModule.racletteConfig

      cachedConfig = this.config
    } catch (error) {
      console.warn(
        `Error loading config: ${error instanceof Error ? error.message : String(error)}`,
      )
      // Keep using cached config if it exists
      this.config = cachedConfig
    }
  }

  // Get the entire config
  public getConfig() {
    if (!this.config) {
      if (!cachedConfig) {
        console.error("Failed to load racletteJS configuration")
      }
      this.config = cachedConfig
    }

    return this.config
  }

  public getPlugins(): string[] {
    return this.config.plugins || []
  }
  public getAuthTokenExpiryDays(): number {
    return this.config.global?.authTokenExpiryDays ?? 30
  }
  public getAdditonalPluginPaths(): string[] {
    return this.config.additionalPluginPaths?.map((e) => `${e}`) || []
  }
  public getPreventNotifications(): PreventNotifications {
    return this.config.preventNotifications || {}
  }
  public getPleaseLetUsAdvertiseOurselves(): boolean {
    return this.config.pleaseLetUsAdvertiseOurselves ?? true
  }
  public getAdvertiseYourself(): string {
    return this.config.advertiseYourself || ""
  }
  public getRequireAuthentication(): boolean {
    return this.config.global?.requireAuthentication || false
  }
  public getApplicationTitle(): string | undefined {
    return this.config.meta?.title ?? this.config.name
  }
  public getI18nConfig(): RacletteFrontendConfig["i18n"] {
    return this.config.i18n || {}
  }
}

const configService = new ConfigService()

export default configService
