import { ApiProperty, ApiPropertyOptional, OmitType, PartialType } from '@nestjs/swagger';
import { inm_unidad_tipo } from '@prisma/client';
import {
  ArrayMaxSize,
  IsArray,
  IsBoolean,
  IsEnum,
  IsInt,
  IsNotEmpty,
  IsNumber,
  IsObject,
  IsOptional,
  IsString,
  IsUUID,
  MaxLength,
  Min,
} from 'class-validator';

export class CreateUnidadDto {
  @ApiProperty({ description: 'Proyecto al que pertenece' })
  @IsUUID()
  proyecto_id: string;

  @ApiProperty({ example: 'A-0802', description: 'Único dentro del proyecto' })
  @IsString()
  @IsNotEmpty()
  @MaxLength(30)
  codigo: string;

  @ApiPropertyOptional({ enum: inm_unidad_tipo, example: inm_unidad_tipo.DEPARTAMENTO })
  @IsOptional()
  @IsEnum(inm_unidad_tipo)
  tipo?: inm_unidad_tipo;

  @ApiPropertyOptional() @IsOptional() @IsUUID() etapa_id?: string | null;
  @ApiPropertyOptional({ description: 'Departamento al que está vinculada una cochera o baulera' })
  @IsOptional()
  @IsUUID()
  unidad_padre_id?: string | null;
  @ApiPropertyOptional({ example: 8 }) @IsOptional() @IsInt() piso?: number | null;
  @ApiPropertyOptional({ example: '02' }) @IsOptional() @IsString() @MaxLength(20) numero?: string | null;
  @ApiPropertyOptional({ example: '2 dormitorios' }) @IsOptional() @IsString() @MaxLength(60) tipologia?: string | null;
  @ApiPropertyOptional({ example: 2 }) @IsOptional() @IsInt() @Min(0) dormitorios?: number | null;
  @ApiPropertyOptional({ example: 2 }) @IsOptional() @IsInt() @Min(0) banos?: number | null;
  @ApiPropertyOptional({ example: 72.5 }) @IsOptional() @IsNumber({ maxDecimalPlaces: 2 }) @Min(0) m2_propios?:
    | number
    | null;
  @ApiPropertyOptional({ example: 12.3 }) @IsOptional() @IsNumber({ maxDecimalPlaces: 2 }) @Min(0) m2_comunes?:
    | number
    | null;
  @ApiPropertyOptional({ example: 360 }) @IsOptional() @IsNumber({ maxDecimalPlaces: 2 }) @Min(0) superficie_terreno?:
    | number
    | null;
  @ApiPropertyOptional({ example: 'C' }) @IsOptional() @IsString() @MaxLength(20) manzana?: string | null;
  @ApiPropertyOptional({ example: '14' }) @IsOptional() @IsString() @MaxLength(20) lote?: string | null;
  @ApiPropertyOptional({ example: 'Norte' }) @IsOptional() @IsString() @MaxLength(40) orientacion?: string | null;
  @ApiPropertyOptional() @IsOptional() @IsString() @MaxLength(60) cta_catastral?: string | null;
  @ApiPropertyOptional() @IsOptional() @IsString() @MaxLength(60) finca?: string | null;
  @ApiPropertyOptional({ example: { vista: 'río', balcon: true } }) @IsOptional() @IsObject() atributos?: Record<
    string,
    unknown
  >;

  @ApiPropertyOptional({ example: 85000, description: 'Precio de lista en la moneda de la unidad' })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 2 })
  @Min(0)
  precio_lista?: number;

  @ApiPropertyOptional({ description: 'Por defecto, la moneda del proyecto' })
  @IsOptional()
  @IsUUID()
  moneda_id?: string;

  @ApiPropertyOptional({ default: true, description: 'false = queda en borrador, no visible para ventas' })
  @IsOptional()
  @IsBoolean()
  publicar?: boolean;
}

export class UpdateUnidadDto extends PartialType(
  OmitType(CreateUnidadDto, ['proyecto_id', 'precio_lista', 'publicar'] as const),
) {}

export class CambiarPrecioDto {
  @ApiProperty({ example: 87000 }) @IsNumber({ maxDecimalPlaces: 2 }) @Min(0) precio: number;
  @ApiProperty({ example: 'Ajuste de lista octubre' }) @IsString() @IsNotEmpty() @MaxLength(255) motivo: string;
}

export class BloquearUnidadDto {
  @ApiProperty({ example: 'Reservada para canje con el constructor' })
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  motivo: string;
  @ApiPropertyOptional({ description: 'Versión leída, para el bloqueo optimista' })
  @IsOptional()
  @IsInt()
  version?: number;
}

export class VersionDto {
  @ApiPropertyOptional() @IsOptional() @IsInt() version?: number;
}

export class FilaImportacionUnidadDto extends OmitType(CreateUnidadDto, [
  'proyecto_id',
  'etapa_id',
  'unidad_padre_id',
  'moneda_id',
] as const) {
  @ApiPropertyOptional({ example: 'Torre A', description: 'Nombre de la etapa (debe existir en el proyecto)' })
  @IsOptional()
  @IsString()
  etapa?: string | null;
}

export class ImportarUnidadesDto {
  @ApiProperty() @IsUUID() proyecto_id: string;

  /**
   * Las filas se validan una por una en el servicio: una fila mala no cancela las
   * demás (importar 300 unidades y perderlas por un m² mal escrito es inaceptable).
   */
  @ApiProperty({ type: [FilaImportacionUnidadDto] })
  @IsArray()
  @ArrayMaxSize(2000)
  @IsObject({ each: true })
  filas: Record<string, unknown>[];
}
