import { Transform, Type } from 'class-transformer';
import {
  ArrayUnique,
  IsArray,
  IsBoolean,
  IsIn,
  IsInt,
  IsOptional,
  IsString,
  Max,
  Min,
} from 'class-validator';

import { normalizePlenaryStatus } from './create-plenary.dto';

function parseStringArray(value: unknown): string[] | undefined {
  if (value === undefined || value === null || value === '') return undefined;

  const rawValues = Array.isArray(value) ? value : [value];

  const values = rawValues
    .flatMap((item) => {
      if (typeof item === 'string') return item.split(',');
      if (typeof item === 'number') return [item.toString()];
      return [];
    })
    .map((item) => item.trim())
    .filter(Boolean);

  return values.length > 0 ? [...new Set(values)] : undefined;
}

function parseStatusArray(value: unknown): string[] | undefined {
  const values = parseStringArray(value);

  if (!values) return undefined;

  const statuses = values
    .map((item) => normalizePlenaryStatus(item))
    .filter((item): item is string => Boolean(item));

  return statuses.length > 0 ? [...new Set(statuses)] : undefined;
}

function parseNumberArray(value: unknown): number[] | undefined {
  const values = parseStringArray(value);

  if (!values) return undefined;

  const numbers = values
    .map((item) => Number(item))
    .filter((item) => Number.isInteger(item) && item > 0);

  return numbers.length > 0 ? [...new Set(numbers)] : undefined;
}

function parseBoolean(value: unknown): boolean | undefined {
  if (value === undefined || value === null || value === '') return undefined;
  if (typeof value === 'boolean') return value;
  if (typeof value === 'number') return value === 1;

  if (typeof value === 'string') {
    return ['1', 'true', 'yes'].includes(value.trim().toLowerCase());
  }

  return false;
}

export class PlenaryQueryDto {
  @IsOptional()
  @IsString()
  search?: string;

  @IsOptional()
  @Transform(({ value }: { value: unknown }) => normalizePlenaryStatus(value))
  @IsIn(['DRAFT', 'SENT'])
  status?: string;

  @IsOptional()
  @Transform(({ value }: { value: unknown }) => parseStatusArray(value))
  @IsArray()
  @ArrayUnique()
  @IsString({ each: true })
  @IsIn(['DRAFT', 'SENT'], { each: true })
  statuses?: string[];

  @IsOptional()
  @Transform(({ value }: { value: unknown }) => parseNumberArray(value))
  @IsArray()
  @ArrayUnique()
  @IsInt({ each: true })
  @Min(1, { each: true })
  ministryIds?: number[];

  @IsOptional()
  @Transform(({ value }: { value: unknown }) => parseBoolean(value))
  @IsBoolean()
  ministryOnly?: boolean;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  page?: number = 1;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(100)
  limit?: number = 10;
}
