import { Injectable } from '@nestjs/common';

export type SystemRole = string;

@Injectable()
export class AuthorizationService {
  private cache:
    | {
        rolesByUserId: Readonly<Record<string, readonly SystemRole[]>>;
        expiresAtMs: number;
      }
    | null = null;

  getRolesForUser(userId: string): readonly SystemRole[] {
    const now = Date.now();
    if (this.cache && now < this.cache.expiresAtMs) {
      return this.cache.rolesByUserId[userId] ?? [];
    }

    const cacheMs = parseCacheMs(process.env.GRIDPILOT_AUTHZ_CACHE_MS);
    const rolesByUserId = parseUserRolesJson(process.env.GRIDPILOT_USER_ROLES_JSON);

    this.cache = {
      rolesByUserId,
      expiresAtMs: now + cacheMs,
    };

    return rolesByUserId[userId] ?? [];
  }
}

function parseCacheMs(raw: string | undefined): number {
  if (!raw) {
    return 5_000;
  }
  const parsed = Number(raw);
  if (!Number.isFinite(parsed) || parsed < 0) {
    return 5_000;
  }
  return parsed;
}

function parseUserRolesJson(raw: string | undefined): Readonly<Record<string, readonly SystemRole[]>> {
  if (!raw) {
    return {};
  }

  try {
    const parsed = JSON.parse(raw) as unknown;
    if (!parsed || typeof parsed !== 'object') {
      return {};
    }

    const record = parsed as Record<string, unknown>;
    const normalized: Record<string, readonly SystemRole[]> = {};

    for (const [userId, roles] of Object.entries(record)) {
      if (!userId || !Array.isArray(roles)) {
        continue;
      }

      const cleaned = roles
        .filter((v) => typeof v === 'string')
        .map((v) => v.trim())
        .filter(Boolean);

      if (cleaned.length > 0) {
        normalized[userId] = cleaned;
      }
    }

    return normalized;
  } catch {
    return {};
  }
}