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

const toBool = ({ value }: { value: any }) => {
  if (typeof value === 'boolean') return value;
  if (value === 'true') return true;
  if (value === 'false') return false;
  return undefined;
};

export enum UsersSortBy {
  daysInactive = 'daysInactive',
  lastAnyActivity = 'lastAnyActivity',
  userPrincipalName = 'userPrincipalName',
  updatedAt = 'updatedAt',
}

export enum SortOrder {
  asc = 'asc',
  desc = 'desc',
}

export enum UsersFormat {
  json = 'json',
  csv = 'csv',
}

export class ListUsersQueryDto {
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(0)
  inactiveDays?: number = 180;

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(0)
  accountAgeMinDays?: number;

  @IsOptional()
  @Transform(toBool)
  @IsBoolean()
  includeNeverSignedIn?: boolean = true;

  @IsOptional()
  @Transform(toBool)
  @IsBoolean()
  accountEnabled?: boolean;

  @IsOptional()
  @Transform(toBool)
  @IsBoolean()
  hasLicense?: boolean;

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

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

  @IsOptional()
  @Transform(toBool)
  @IsBoolean()
  missingFromLatestSync?: boolean = false;

  @IsOptional()
  @IsEnum(UsersSortBy)
  sortBy?: UsersSortBy = UsersSortBy.daysInactive;

  @IsOptional()
  @IsEnum(SortOrder)
  sortOrder?: SortOrder = SortOrder.desc;

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

  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(200)
  pageSize?: number = 50;

  @IsOptional()
  @IsEnum(UsersFormat)
  format?: UsersFormat = UsersFormat.json;
}

export class UserTimelineQueryDto {
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(500)
  limit?: number = 100;

  @IsOptional()
  @IsEnum(M365UserActivityChangeField)
  field?: M365UserActivityChangeField;

  @IsOptional()
  @IsString()
  since?: string;
}

export class HistoryQueryDto {
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(90)
  limit?: number = 30;

  @IsOptional()
  @IsString()
  status?: string;
}

export interface InactiveDistribution {
  never: number;
  buckets: Array<{ from: number; to: number | null; count: number }>;
}

export interface ExecutionResultPayload {
  totalUsers: number;
  changedUsers: number;
  inactiveDistribution: InactiveDistribution;
}
