import {
  IsBoolean,
  IsDateString,
  IsEnum,
  IsIn,
  IsInt,
  IsOptional,
  IsString,
  IsUUID,
  Max,
  Min,
} from 'class-validator';
import { Transform } from 'class-transformer';
import { LabTaskStatus, LabCaseOrigin } from '@prisma/client';

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

export class UpdateLabTaskDto {
  @IsEnum(LabTaskStatus)
  status: LabTaskStatus;
}

export type TaskSortField =
  | 'date'
  | 'status'
  | 'clinic'
  | 'patient'
  | 'important'
  | 'prosthesis'
  | 'taskType'
  | 'dueDate';

export class ListLabTasksDto {
  @IsOptional()
  @IsString()
  q?: string;

  @IsOptional()
  @IsUUID()
  clinicOrganizationId?: string;

  @IsOptional()
  @IsEnum(LabTaskStatus)
  status?: LabTaskStatus;

  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  completed?: boolean;

  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  important?: boolean;

  /** When true, important lab cases are listed before others (does not hide non-important). */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  pinImportant?: boolean;

  @IsOptional()
  @IsDateString()
  sentFrom?: string;

  @IsOptional()
  @IsDateString()
  sentTo?: string;

  /** Workflow step code (e.g. design) completed within the prosthesis group. */
  @IsOptional()
  @IsString()
  stepCompleted?: string;

  /** Narrow list to a single lab case (e.g. show-in-case navigation). */
  @IsOptional()
  @IsUUID()
  labCaseId?: string;

  /** When true, only tasks assigned to the current user. */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  assignedToMe?: boolean;

  /** Past due date with at least one in-progress task on the case. */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  overdue?: boolean;

  /** When true, only tasks with no assignee. */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  unassignedOnly?: boolean;

  /** Narrow list to a single prosthesis type code. */
  @IsOptional()
  @IsString()
  prosthesisTypeCode?: string;

  /** CLINIC_DISPATCH = received from clinic; LAB_INTERNAL = generated in the lab. */
  @IsOptional()
  @IsEnum(LabCaseOrigin)
  origin?: LabCaseOrigin;

  @IsOptional()
  @IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType', 'dueDate'])
  sortBy?: TaskSortField;

  @IsOptional()
  @IsIn(['asc', 'desc'])
  sortDir?: 'asc' | 'desc';

  @IsOptional()
  @Transform(({ value }) => Number(value))
  @IsInt()
  @Min(1)
  page = 1;

  @IsOptional()
  @Transform(({ value }) => Number(value))
  @IsInt()
  @Min(1)
  @Max(100)
  limit = 50;
}

/** Same filters as list (no page) — used to find which page contains a task. */
export class LocateTaskPageDto {
  @IsUUID()
  taskId: string;

  @IsOptional()
  @IsString()
  q?: string;

  @IsOptional()
  @IsUUID()
  clinicOrganizationId?: string;

  @IsOptional()
  @IsEnum(LabTaskStatus)
  status?: LabTaskStatus;

  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  completed?: boolean;

  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  important?: boolean;

  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  pinImportant?: boolean;

  @IsOptional()
  @IsDateString()
  sentFrom?: string;

  @IsOptional()
  @IsDateString()
  sentTo?: string;

  @IsOptional()
  @IsString()
  stepCompleted?: string;

  /** When true, only tasks assigned to the current user. */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  assignedToMe?: boolean;

  /** Past due date with at least one in-progress task on the case. */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  overdue?: boolean;

  /** When true, only tasks with no assignee. */
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  unassignedOnly?: boolean;

  /** Narrow list to a single prosthesis type code. */
  @IsOptional()
  @IsString()
  prosthesisTypeCode?: string;

  @IsOptional()
  @IsEnum(LabCaseOrigin)
  origin?: LabCaseOrigin;

  @IsOptional()
  @IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType', 'dueDate'])
  sortBy?: TaskSortField;

  @IsOptional()
  @IsIn(['asc', 'desc'])
  sortDir?: 'asc' | 'desc';

  @IsOptional()
  @Transform(({ value }) => Number(value))
  @IsInt()
  @Min(1)
  @Max(100)
  limit = 50;
}
