import { inject, Injectable, InjectionToken } from '@angular/core';
import { z } from 'zod';
import { coerceArray } from '@angular/cdk/coercion';

type JsonPrimitive = string | number | boolean | null | undefined;

export type JsonValue =
  | Array<JsonPrimitive>
  | Record<string, JsonPrimitive>
  | JsonPrimitive;

export const CONFIG_DATA = new InjectionToken<JsonValue>('ConfigData');

@Injectable({ providedIn: 'root' })
export class Config {
  #config = inject(CONFIG_DATA);

  /**
   * @deprecated Use `get` with a Zod schema instead
   */
  get(path: string | string[]): any;
  get<TOut>(path: string | string[], zSchema: z.ZodSchema<TOut>): TOut;
  get<TOut>(path: string | string[], zSchema?: z.ZodSchema<TOut>): TOut | any {
    let result: JsonValue = this.#config;

    if (typeof path === 'string') {
      path = path.split('.');
    }

    for (const p of coerceArray(path)) {
      if (
        typeof result === 'object' &&
        result !== null &&
        !Array.isArray(result)
      ) {
        result = (result as Record<string, JsonPrimitive>)[p];
      } else {
        break;
      }
      if (result === null || result === undefined) {
        break;
      }
    }

    return zSchema ? zSchema.parse(result) : result;
  }
}
