import { TypeOrmMediaSchemaError } from '../errors/TypeOrmMediaSchemaError';

export function assertNonEmptyString(entityName: string, fieldName: string, value: unknown): asserts value is string {
  if (typeof value !== 'string') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_string' });
  }

  if (value.trim().length === 0) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'empty_string' });
  }
}

export function assertDate(entityName: string, fieldName: string, value: unknown): asserts value is Date {
  if (!(value instanceof Date)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_date' });
  }
  if (Number.isNaN(value.getTime())) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'invalid_date' });
  }
}

export function assertNumber(entityName: string, fieldName: string, value: unknown): asserts value is number {
  if (typeof value !== 'number') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_number' });
  }
  if (Number.isNaN(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_number' });
  }
}

export function assertInteger(entityName: string, fieldName: string, value: unknown): asserts value is number {
  if (typeof value !== 'number') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_number' });
  }
  if (!Number.isInteger(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_integer' });
  }
}

export function assertBoolean(entityName: string, fieldName: string, value: unknown): asserts value is boolean {
  if (typeof value !== 'boolean') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_boolean' });
  }
}

export function assertOptionalStringOrNull(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is string | null | undefined {
  if (value === null || value === undefined) {
    return;
  }

  if (typeof value !== 'string') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_string' });
  }
}

export function assertOptionalNumberOrNull(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is number | null | undefined {
  if (value === null || value === undefined) {
    return;
  }

  if (typeof value !== 'number') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_number' });
  }
  if (Number.isNaN(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_number' });
  }
}

export function assertStringArray(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is string[] {
  if (!Array.isArray(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_array' });
  }
  if (!value.every(item => typeof item === 'string')) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_array' });
  }
}

export function assertMediaType(entityName: string, fieldName: string, value: unknown): asserts value is 'image' | 'video' | 'document' {
  if (typeof value !== 'string') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_string' });
  }
  if (!['image', 'video', 'document'].includes(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'invalid_enum_value' });
  }
}

export function assertRacingSuitColor(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is 'red' | 'blue' | 'green' | 'yellow' | 'orange' | 'purple' | 'black' | 'white' | 'pink' | 'cyan' {
  if (typeof value !== 'string') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_string' });
  }
  if (
!['red', 'blue', 'green', 'yellow', 'orange', 'purple', 'black', 'white', 'pink', 'cyan'].includes(value)
) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'invalid_enum_value' });
  }
}

export function assertAvatarStyle(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is 'realistic' | 'cartoon' | 'pixel-art' {
  if (typeof value !== 'string') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_string' });
  }
  if (!['realistic', 'cartoon', 'pixel-art'].includes(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'invalid_enum_value' });
  }
}

export function assertAvatarGenerationStatus(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is 'pending' | 'validating' | 'generating' | 'completed' | 'failed' {
  if (typeof value !== 'string') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_string' });
  }
  if (!['pending', 'validating', 'generating', 'completed', 'failed'].includes(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'invalid_enum_value' });
  }
}

export function assertOptionalIntegerOrNull(
  entityName: string,
  fieldName: string,
  value: unknown,
): asserts value is number | null | undefined {
  if (value === null || value === undefined) {
    return;
  }

  if (typeof value !== 'number') {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_number' });
  }
  if (!Number.isInteger(value)) {
    throw new TypeOrmMediaSchemaError({ entityName, fieldName, reason: 'not_integer' });
  }
}
