import { ApiPropertyOptional } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import {
  IsBoolean,
  IsIn,
  IsOptional,
  IsString,
  MaxLength,
} from 'class-validator';

import {
  ALLOWED_SORT_FIELDS,
  ALLOWED_SORT_ORDERS,
  type IssueSortField,
  type IssueSortOrder,
} from './query-working-group-issue.dto';

const toBoolean = ({ value }: { value: unknown }): unknown => {
  if (value === 'true' || value === true || value === 1 || value === '1') {
    return true;
  }
  if (value === 'false' || value === false || value === 0 || value === '0') {
    return false;
  }
  return value;
};

const toNumberArray = ({ value }: { value: unknown }): number[] | undefined => {
  if (value === undefined || value === null || value === '') {
    return undefined;
  }

  const rawValues = Array.isArray(value)
    ? value
    : typeof value === 'string'
      ? value.split(',')
      : typeof value === 'number'
        ? [value]
        : [];

  return rawValues
    .map((item) => Number(String(item).trim()))
    .filter((item) => Number.isInteger(item) && item >= 1);
};

export type ExportLanguage = 'en' | 'km';

export class ExportWorkingGroupIssuesDto {
  @ApiPropertyOptional({
    description: 'Filter by one or more issue status IDs.',
    type: [Number],
    example: [1, 2],
  })
  @IsOptional()
  @Transform(toNumberArray)
  @Type(() => Number)
  issueStatusIds?: number[];

  @ApiPropertyOptional({
    description: 'Filter by one or more issue category IDs.',
    type: [Number],
    example: [1],
  })
  @IsOptional()
  @Transform(toNumberArray)
  @Type(() => Number)
  categoryIds?: number[];

  @ApiPropertyOptional({
    description: 'Filter by one or more primary agency stakeholder IDs.',
    type: [Number],
    example: [5],
  })
  @IsOptional()
  @Transform(toNumberArray)
  @Type(() => Number)
  primaryAgencyIds?: number[];

  @ApiPropertyOptional({
    description: 'Filter by one or more owner working-group stakeholder IDs.',
    type: [Number],
    example: [2, 4],
  })
  @IsOptional()
  @Transform(toNumberArray)
  @Type(() => Number)
  ownerStakeholderIds?: number[];

  @ApiPropertyOptional({
    description: 'Filter by issue creation year(s).',
    type: [Number],
    example: [2025, 2026],
  })
  @IsOptional()
  @Transform(toNumberArray)
  @Type(() => Number)
  years?: number[];

  @ApiPropertyOptional({
    description: 'true → issues with an attachment, false → issues without.',
  })
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  hasAttachment?: boolean;

  @ApiPropertyOptional({
    description:
      'Case-insensitive text search across title, description, and recommendation.',
  })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  @Transform(({ value }: { value: unknown }) =>
    typeof value === 'string' ? value.trim() : value,
  )
  search?: string;

  @ApiPropertyOptional({
    enum: ALLOWED_SORT_FIELDS,
    example: 'createdAt',
    description: 'Column to sort by. Defaults to createdAt.',
  })
  @IsOptional()
  @IsIn(ALLOWED_SORT_FIELDS)
  sortBy?: IssueSortField;

  @ApiPropertyOptional({
    enum: ALLOWED_SORT_ORDERS,
    example: 'desc',
    description: 'Sort direction. Defaults to desc.',
  })
  @IsOptional()
  @IsIn(ALLOWED_SORT_ORDERS)
  sortOrder?: IssueSortOrder;

  @ApiPropertyOptional({
    enum: ['en', 'km'],
    example: 'en',
    description: 'Language for column headers.',
  })
  @IsOptional()
  @IsIn(['en', 'km'])
  lang?: ExportLanguage;
}
