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

export const STAKEHOLDER_SORT_FIELDS = [
  'id',
  'name',
  'coChair',
  'description',
  'createdAt',
  'updatedAt',
  'active',
  'stakeholderType',
] as const;
export type StakeholderSortField = (typeof STAKEHOLDER_SORT_FIELDS)[number];

export const STAKEHOLDER_SORT_ORDERS = ['asc', 'desc'] as const;
export type StakeholderSortOrder = (typeof STAKEHOLDER_SORT_ORDERS)[number];

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]
        : [];

  const parsedValues = rawValues
    .map((item) => Number(String(item).trim()))
    .filter((item) => Number.isInteger(item));

  return parsedValues.length > 0 ? parsedValues : undefined;
};

export class ListStakeholdersDto {
  @ApiPropertyOptional({
    example: 1,
    default: 1,
    description: 'Page number.',
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  page?: number;

  @ApiPropertyOptional({
    example: 10,
    default: 10,
    description: 'Items per page. Max 100.',
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(100)
  limit?: number;

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

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

  @ApiPropertyOptional({
    example: 1,
    description: 'Filter by stakeholder type ID',
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  stakeholderTypeId?: number;

  @ApiPropertyOptional({ description: 'Filter by active status' })
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  active?: boolean;

  @ApiPropertyOptional({
    example: 27,
    description: 'Filter by exact stakeholder ID (No. column).',
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  id?: number;

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

  @ApiPropertyOptional({
    description: 'Filter stakeholder name (contains, case-insensitive).',
  })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  @Transform(({ value }: { value: unknown }) =>
    typeof value === 'string' ? value.trim() : value,
  )
  name?: string;

  @ApiPropertyOptional({
    description: 'Filter co-chair (contains, case-insensitive).',
  })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  @Transform(({ value }: { value: unknown }) =>
    typeof value === 'string' ? value.trim() : value,
  )
  coChair?: string;

  @ApiPropertyOptional({
    description: 'Filter description (contains, case-insensitive).',
  })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  @Transform(({ value }: { value: unknown }) =>
    typeof value === 'string' ? value.trim() : value,
  )
  description?: string;

  @ApiPropertyOptional({
    description: 'Filter stakeholder type name (contains, case-insensitive).',
  })
  @IsOptional()
  @IsString()
  @MaxLength(100)
  @Transform(({ value }: { value: unknown }) =>
    typeof value === 'string' ? value.trim() : value,
  )
  stakeholderTypeName?: string;

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

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

  @ApiPropertyOptional({
    description: 'true = has assigned users, false = no assigned users.',
  })
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  hasUsers?: boolean;
}
