import { plainToClass } from 'class-transformer';
import {
  IsNotEmpty,
  IsNumber,
  IsOptional,
  IsString,
  validateSync,
} from 'class-validator';

/**
 * 環境変数の型定義
 */
export class EnvValidator {
  // .env
  @IsNotEmpty()
  @IsString()
  DB_HOST: string;

  @IsNotEmpty()
  @IsNumber()
  DB_PORT: number;

  @IsNotEmpty()
  @IsString()
  DB_NAME: string;

  @IsNotEmpty()
  @IsString()
  DB_USERNAME: string;

  @IsNotEmpty()
  @IsString()
  DB_PASSWORD: string;

  // .env.local
  @IsOptional()
  @IsString()
  STAGE: string;

  @IsOptional()
  @IsString()
  NO_COLOR: string;

  @IsOptional()
  @IsString()
  CORS: string;

  @IsOptional()
  @IsNumber()
  PORT: number;

  @IsNotEmpty()
  @IsString()
  TENANT_NAME: string;

  @IsNotEmpty()
  @IsString()
  SIGNIN_FLOW_NAME: string;

  @IsNotEmpty()
  @IsString()
  ADB2C_TENANT_ID: string;

  @IsNotEmpty()
  @IsString()
  ADB2C_CLIENT_ID: string;

  @IsNotEmpty()
  @IsString()
  ADB2C_CLIENT_SECRET: string;

  @IsOptional()
  @IsString()
  ADB2C_ORIGIN: string;

  @IsNotEmpty()
  @IsString()
  JWT_PRIVATE_KEY: string;

  @IsNotEmpty()
  @IsString()
  JWT_PUBLIC_KEY: string;

  @IsNotEmpty()
  @IsString()
  SENDGRID_API_KEY: string;

  @IsNotEmpty()
  @IsString()
  MAIL_FROM: string;

  @IsNotEmpty()
  @IsString()
  NOTIFICATION_HUB_NAME: string;

  @IsNotEmpty()
  @IsString()
  NOTIFICATION_HUB_CONNECT_STRING: string;

  @IsNotEmpty()
  @IsString()
  APP_DOMAIN: string;

  @IsNotEmpty()
  @IsNumber()
  STORAGE_TOKEN_EXPIRE_TIME: number;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_NAME_US: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_NAME_AU: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_NAME_EU: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_KEY_US: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_KEY_AU: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_KEY_EU: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_ENDPOINT_US: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_ENDPOINT_AU: string;

  @IsNotEmpty()
  @IsString()
  STORAGE_ACCOUNT_ENDPOINT_EU: string;

  @IsNotEmpty()
  @IsNumber()
  ACCESS_TOKEN_LIFETIME_WEB: number;

  @IsNotEmpty()
  @IsNumber()
  REFRESH_TOKEN_LIFETIME_WEB: number;

  @IsNotEmpty()
  @IsNumber()
  REFRESH_TOKEN_LIFETIME_DEFAULT: number;

  @IsNotEmpty()
  @IsNumber()
  EMAIL_CONFIRM_LIFETIME: number;

  @IsNotEmpty()
  @IsString()
  REDIS_HOST: string;

  @IsNotEmpty()
  @IsNumber()
  REDIS_PORT: number;

  @IsNotEmpty()
  @IsString()
  REDIS_PASSWORD: string;

  @IsNotEmpty()
  @IsNumber()
  ADB2C_CACHE_TTL: number;
}

export function validate(config: Record<string, unknown>) {
  const validatedConfig = plainToClass(EnvValidator, config, {
    enableImplicitConversion: true,
  });

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

  if (errors.length > 0) {
    throw new Error(errors.toString());
  }
  return validatedConfig;
}
