import { Transform } from 'class-transformer';
import {
  IsArray,
  IsBoolean,
  IsEnum,
  IsInt,
  IsNotEmpty,
  IsString,
  Max,
  MaxLength,
  Min,
} from 'class-validator';
import { TransformBoolean } from '../../../shared/decorators/class-transformer/transform-boolean.decorator';
import { TransformNumber } from '../../../shared/decorators/class-transformer/transform-number.decorator';
import { TransformNumberArray } from '../../../shared/decorators/class-transformer/transform-number-array.decorator';
import { TryToTransformStringInNumber } from '../../../shared/decorators/class-transformer/try-to-transform-string-in-number.decorator';
import { IsOptional } from '../../../shared/decorators/class-validator/is-optional.decorator';
import { MatchesNamesRegex } from '../../../shared/decorators/class-validator/matches-names-regex.decorator';
import { IsUsername } from '../../../shared/decorators/class-validator/is-username.decorator';

export enum RetrieveRecipes_OrderBy {
  LikesAsc = 'likes.asc',
  LikesDesc = 'likes.desc',
  CaloriesAsc = 'calories.asc',
  CaloriesDesc = 'calories.desc',
  ServingsAsc = 'servings.asc',
  ServingsDesc = 'servings.desc',
  NameAsc = 'name.asc',
  NameDesc = 'name.desc',
  IdAsc = 'id.asc',
  IdDesc = 'id.desc',
}

export class RetrieveRecipesQueryParamsDto {
  @IsOptional()
  @TransformNumber()
  @IsInt()
  @Min(1)
  page: number = 1;

  @IsOptional()
  @TransformNumber()
  @IsInt()
  @Min(1)
  @Max(20)
  items_per_page: number = 20;

  @IsOptional()
  @TransformBoolean()
  @IsBoolean()
  self?: boolean;

  @IsOptional()
  @TransformNumber()
  @IsInt()
  @Min(1)
  from_user_id?: number;

  @IsOptional()
  @IsString()
  @IsNotEmpty()
  @MaxLength(30)
  @IsUsername()
  from_username?: string;

  @IsOptional()
  @TransformBoolean()
  @IsBoolean()
  liked_only?: boolean;

  @IsOptional()
  @TransformNumberArray()
  @IsArray()
  @IsInt({ each: true })
  @Min(1, { each: true })
  tags_ids?: number[];

  @IsOptional()
  @TransformNumber()
  @IsInt()
  @Min(1)
  min_calorie_content_per_portion?: number;

  @IsOptional()
  @TransformNumber()
  @IsInt()
  @Min(1)
  max_calorie_content_per_portion?: number;

  @IsOptional()
  @TransformNumber()
  @IsInt()
  @Min(1)
  servings?: number;

  @IsOptional()
  @TransformNumberArray()
  @IsArray()
  @IsInt({ each: true })
  @Min(1, { each: true })
  ingredients_ids?: number[];

  @IsOptional()
  @IsEnum(RetrieveRecipes_OrderBy)
  order_by?: RetrieveRecipes_OrderBy = RetrieveRecipes_OrderBy.IdDesc;

  @IsOptional()
  @IsString()
  @IsNotEmpty()
  @MaxLength(50)
  @MatchesNamesRegex()
  search_by_name?: string;
}

export class RetrieveRecipes_Tag {
  id: number;
  name: string;
}

export class RetrieveRecipes_Recipe {
  id: number;
  name: string;
  creator: string;
  pictureUrl: string;

  @Transform(({ value }) => !!+value)
  isLiked?: boolean;

  @Transform(({ value }) => +value)
  likes: number;

  tags: RetrieveRecipes_Tag[];

  @TryToTransformStringInNumber()
  kcal: number | string;

  constructor(partial: Partial<RetrieveRecipes_Recipe>) {
    Object.assign(this, partial);
  }
}

export class RetrieveRecipesResponseDto {
  data: RetrieveRecipes_Recipe[];
  actualPage?: number;
  totalPages?: number;
}
