import { plainToInstance } from 'class-transformer';
import {
  IsInt,
  IsNotEmpty,
  IsString,
  IsUrl,
  Max,
  Min,
  validateSync,
} from 'class-validator';

class EnvironmentVariables {
  @IsString()
  @IsNotEmpty()
  NODE_ENV!: string;

  @IsInt()
  @Min(1)
  @Max(65535)
  PORT!: number;

  @IsString()
  @IsNotEmpty()
  DATABASE_URL!: string;

  @IsString()
  @IsNotEmpty()
  STORAGE_ROOT!: string;

  @IsUrl({
    require_tld: false,
    require_protocol: true,
  })
  PUBLIC_BASE_URL!: string;

  @IsString()
  @IsNotEmpty()
  DEVICE_BOOTSTRAP_SECRET!: string;

  @IsInt()
  @Min(1)
  MAX_UPLOAD_SIZE_BYTES!: number;
}

export function validateEnvironment(config: Record<string, unknown>) {
  const validated = plainToInstance(EnvironmentVariables, config, {
    enableImplicitConversion: true,
  });

  const errors = validateSync(validated, {
    skipMissingProperties: false,
  });

  if (errors.length > 0) {
    throw new Error(
      `Invalid environment configuration: ${errors
        .map((error) => Object.values(error.constraints ?? {}).join(', '))
        .join('; ')}`,
    );
  }

  return validated;
}

export type ValidEnvironment = ReturnType<typeof validateEnvironment>;
