import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsString, IsOptional, IsEnum, IsInt, Min, Max, IsArray, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
import { CharacterType, AbilityType, Proficiency, FeatSource, SpellTradition } from '../../../generated/prisma/client.js';

export class CreateCharacterDto {
  @ApiProperty({ description: 'Character name' })
  @IsString()
  name: string;

  @ApiPropertyOptional({ enum: ['PC', 'NPC'], default: 'PC' })
  @IsOptional()
  @IsEnum(CharacterType)
  type?: CharacterType = CharacterType.PC;

  @ApiPropertyOptional({ default: 1 })
  @IsOptional()
  @IsInt()
  @Min(1)
  @Max(20)
  level?: number = 1;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  avatarUrl?: string;

  @ApiProperty({ description: 'Current HP' })
  @IsInt()
  @Min(0)
  hpCurrent: number;

  @ApiProperty({ description: 'Maximum HP' })
  @IsInt()
  @Min(1)
  hpMax: number;

  @ApiPropertyOptional({ default: 0 })
  @IsOptional()
  @IsInt()
  @Min(0)
  hpTemp?: number = 0;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  ancestryId?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  heritageId?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  classId?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  backgroundId?: string;

  @ApiPropertyOptional({ default: 0 })
  @IsOptional()
  @IsInt()
  @Min(0)
  experiencePoints?: number = 0;

  @ApiPropertyOptional({ description: 'Raw Pathbuilder JSON data' })
  @IsOptional()
  pathbuilderData?: unknown;
}

export class CreateAbilityDto {
  @ApiProperty({ enum: ['STR', 'DEX', 'CON', 'INT', 'WIS', 'CHA'] })
  @IsEnum(AbilityType)
  ability: AbilityType;

  @ApiProperty()
  @IsInt()
  @Min(1)
  @Max(30)
  score: number;
}

export class CreateSkillDto {
  @ApiProperty()
  @IsString()
  skillName: string;

  @ApiPropertyOptional({ enum: ['UNTRAINED', 'TRAINED', 'EXPERT', 'MASTER', 'LEGENDARY'], default: 'UNTRAINED' })
  @IsOptional()
  @IsEnum(Proficiency)
  proficiency?: Proficiency = Proficiency.UNTRAINED;
}

export class CreateFeatDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  featId?: string;

  @ApiProperty()
  @IsString()
  name: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  nameGerman?: string;

  @ApiProperty()
  @IsInt()
  level: number;

  @ApiProperty({ enum: ['CLASS', 'ANCESTRY', 'GENERAL', 'SKILL', 'BONUS', 'ARCHETYPE'] })
  @IsEnum(FeatSource)
  source: FeatSource;
}

export class CreateSpellDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  spellId?: string;

  @ApiProperty()
  @IsString()
  name: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  nameGerman?: string;

  @ApiProperty({ enum: ['ARCANE', 'DIVINE', 'OCCULT', 'PRIMAL'] })
  @IsEnum(SpellTradition)
  tradition: SpellTradition;

  @ApiProperty()
  @IsInt()
  @Min(0)
  @Max(10)
  spellLevel: number;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  prepared?: boolean = false;
}

export class CreateItemDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  equipmentId?: string;

  @ApiProperty()
  @IsString()
  name: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  nameGerman?: string;

  @ApiPropertyOptional({ default: 1 })
  @IsOptional()
  @IsInt()
  @Min(1)
  quantity?: number = 1;

  @ApiPropertyOptional({ default: 0 })
  @IsOptional()
  bulk?: number = 0;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  equipped?: boolean = false;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  invested?: boolean = false;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  containerId?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  notes?: string;
}

export class UpdateItemDto {
  // Player-editable fields
  @ApiPropertyOptional()
  @IsOptional()
  @IsInt()
  @Min(1)
  quantity?: number;

  @ApiPropertyOptional()
  @IsOptional()
  equipped?: boolean;

  @ApiPropertyOptional()
  @IsOptional()
  invested?: boolean;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  notes?: string;

  @ApiPropertyOptional({ description: 'Player-editable alias/nickname for the item' })
  @IsOptional()
  @IsString()
  alias?: string;

  // GM-only editable fields (will be validated in service)
  @ApiPropertyOptional({ description: 'GM-only: Custom display name override' })
  @IsOptional()
  @IsString()
  customName?: string;

  @ApiPropertyOptional({ description: 'GM-only: Custom damage dice override (e.g. "2d6")' })
  @IsOptional()
  @IsString()
  customDamage?: string;

  @ApiPropertyOptional({ description: 'GM-only: Custom damage type override' })
  @IsOptional()
  @IsString()
  customDamageType?: string;

  @ApiPropertyOptional({ description: 'GM-only: Custom traits override', type: [String] })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  customTraits?: string[];

  @ApiPropertyOptional({ description: 'GM-only: Custom range override' })
  @IsOptional()
  @IsString()
  customRange?: string;

  @ApiPropertyOptional({ description: 'GM-only: Custom hands requirement override' })
  @IsOptional()
  @IsString()
  customHands?: string;
}

export class CreateConditionDto {
  @ApiProperty()
  @IsString()
  name: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  nameGerman?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsInt()
  value?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  duration?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  source?: string;
}

export class CreateResourceDto {
  @ApiProperty()
  @IsString()
  name: string;

  @ApiProperty()
  @IsInt()
  @Min(0)
  current: number;

  @ApiProperty()
  @IsInt()
  @Min(1)
  max: number;
}
