import { ProgressReportSemester } from '@/generated/prisma/client';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform, Type, type TransformFnParams } from 'class-transformer';
import {
  IsDateString,
  IsDefined,
  IsEnum,
  IsInt,
  IsNotEmpty,
  IsOptional,
  IsString,
  Max,
  MaxLength,
  Min,
} from 'class-validator';

import { IsEditorContent } from './is-editor-content.validator';

function trimString({ value }: TransformFnParams): unknown {
  return typeof value === 'string' ? value.trim() : value;
}

// The status is not accepted here on purpose: a new report is always a DRAFT
// and only the send endpoint can move it to SENT.
export class CreateProgressReportDto {
  @ApiProperty({ example: 'Semester 1 progress report' })
  @Transform(trimString)
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  title!: string;

  @ApiProperty({
    enum: ProgressReportSemester,
    example: ProgressReportSemester.S1,
  })
  @IsEnum(ProgressReportSemester)
  semester!: ProgressReportSemester;

  @ApiProperty({
    example: 'A short summary of this semester report.',
    description:
      'Editor content. Accepts plain text/HTML or a rich-text JSON document.',
  })
  @Transform(trimString)
  @IsDefined()
  @IsEditorContent()
  description!: string | Record<string, unknown>;

  @ApiProperty({ example: 2026 })
  @Type(() => Number)
  @IsInt()
  @Min(2000)
  @Max(2100)
  year!: number;

  @ApiProperty({
    example: '2026-04-30',
    description:
      'The FIRST deadline in YYYY-MM-DD format. The slot is set by the server.',
  })
  @IsDateString()
  firstDeadline!: string;

  @ApiPropertyOptional({
    type: 'string',
    format: 'binary',
    description: 'Required PDF attachment, uploaded as multipart form data.',
  })
  @IsOptional()
  @Transform(trimString)
  @IsString()
  @MaxLength(500)
  attachment?: string;

  @ApiPropertyOptional({
    type: 'string',
    format: 'binary',
    description: 'Optional draft semester report PDF.',
  })
  @IsOptional()
  @Transform(trimString)
  @IsString()
  @MaxLength(500)
  draftSemesterReport?: string;

  @ApiPropertyOptional({
    type: 'string',
    format: 'binary',
    description: 'Optional final semester report PDF.',
  })
  @IsOptional()
  @Transform(trimString)
  @IsString()
  @MaxLength(500)
  finalSemesterReport?: string;
}
