import {
  ApiProperty,
  ApiPropertyOptional,
  IntersectionType,
} from '@nestjs/swagger';
import { Expose, Type } from 'class-transformer';
import {
  IsArray,
  IsBoolean,
  IsEnum,
  IsInt,
  IsOptional,
  IsString,
  Min,
} from 'class-validator';
import { CountDto, PaginationDto } from '../common/common.dto';
import { MedicationCategory, MedicationStandard } from './medication-standard.entity';

// ==================== A. 대분류 (Category) API ====================

// A-1. 대분류 목록 조회 Response
export class GetCategoryListResponseDto {
  @Expose()
  @ApiProperty({ description: '성공 여부' })
  success!: boolean;

  @Expose()
  @ApiProperty({ type: [MedicationCategory], description: '대분류 목록' })
  @Type(() => MedicationCategory)
  list!: MedicationCategory[];
}

// ==================== B. 중분류 (Standard) API ====================

// B-1. 중분류 목록 조회 (페이지네이션 + 필터)
export class GetMedicationStandardFlatDto extends IntersectionType(
  PaginationDto,
) {
  @ApiPropertyOptional({ description: '페이지당 항목 수 (default: 10)' })
  @IsInt()
  @Type(() => Number)
  @IsOptional()
  limit: number = 10;

  @ApiPropertyOptional({ description: '대분류 ID' })
  @IsInt()
  @Type(() => Number)
  @IsOptional()
  categoryId?: number;

  // 개별 필터 필드 (프론트엔드 호환)
  @ApiPropertyOptional({ description: '대분류명으로 필터링' })
  @IsString()
  @IsOptional()
  mcName?: string;

  @ApiPropertyOptional({ description: '중분류 코드로 필터링' })
  @IsString()
  @IsOptional()
  mscCode?: string;

  @ApiPropertyOptional({ description: '중분류명으로 필터링' })
  @IsString()
  @IsOptional()
  mscName?: string;

  @ApiPropertyOptional({
    description: '검색 키',
    enum: ['mcName', 'mscCode', 'mscName'],
  })
  @IsEnum(['mcName', 'mscCode', 'mscName'])
  @IsOptional()
  searchKey?: 'mcName' | 'mscCode' | 'mscName';

  @ApiPropertyOptional({ description: '검색어' })
  @IsString()
  @IsOptional()
  searchText?: string;

  @ApiPropertyOptional({
    description: '시작일 (YYYY-MM-DD)',
    example: '2024-01-01',
  })
  @IsString()
  @IsOptional()
  startDate?: string;

  @ApiPropertyOptional({
    description: '종료일 (YYYY-MM-DD)',
    example: '2024-12-31',
  })
  @IsString()
  @IsOptional()
  endDate?: string;

  @ApiPropertyOptional({ description: '정렬 기준' })
  @IsString()
  @IsOptional()
  sortBy?: string;

  @ApiPropertyOptional({
    description: '정렬 방향',
    enum: ['ASC', 'DESC'],
  })
  @IsEnum(['ASC', 'DESC'])
  @IsOptional()
  sortOrder?: 'ASC' | 'DESC';
}

// B-1. Response
export class GetMedicationStandardFlatResponseDto extends CountDto {
  @Expose()
  @ApiProperty({ type: [MedicationStandard], description: '중분류 목록' })
  @Type(() => MedicationStandard)
  list!: MedicationStandard[];
}

// B-2. 중분류 상세 조회 Response
export class GetMedicationStandardDetailResponseDto {
  @Expose()
  @ApiProperty({ description: '중분류 ID' })
  mscId!: number;

  @Expose()
  @ApiProperty({ description: '대분류 ID' })
  mscCategoryId!: number;

  @Expose()
  @ApiProperty({ description: '대분류명' })
  mscCategory!: string;

  @Expose()
  @ApiProperty({ description: '중분류 코드' })
  mscCode!: string;

  @Expose()
  @ApiProperty({ description: '중분류명' })
  mscName!: string;

  @Expose()
  @ApiProperty({ description: '등록일시' })
  mscCreatedAt!: string;

  @Expose()
  @ApiProperty({ description: '수정일시' })
  mscUpdatedAt!: string;
}

// B-3. 중분류 등록
export class CreateMedicationStandardDto {
  @ApiProperty({ description: '대분류 ID', example: 1 })
  @IsInt()
  @Type(() => Number)
  mscCategoryId!: number;

  @ApiProperty({
    description: '중분류 코드',
    example: '아모닐정150밀리그램(아모다피닐(미분화))_(0.15g/1정)',
  })
  @IsString()
  mscCode!: string;

  @ApiProperty({
    description: '중분류명',
    example: '중추신경계 질환 증상 완화(통증, 수면, 경련, 정신질환)',
  })
  @IsString()
  mscName!: string;
}

// B-3. Response
export class CreateMedicationStandardResponseDto {
  @Expose()
  @ApiProperty({ description: '성공 여부' })
  success!: boolean;

  @Expose()
  @ApiProperty({ description: '생성된 중분류 ID' })
  mscId!: number;
}

// B-4. 중분류 수정
export class UpdateMedicationStandardDto {
  @ApiProperty({ description: '대분류 ID', example: 1 })
  @IsInt()
  @Type(() => Number)
  mscCategoryId!: number;

  @ApiProperty({
    description: '중분류 코드',
    example: '아모닐정150밀리그램(아모다피닐(미분화))_(0.15g/1정)',
  })
  @IsString()
  mscCode!: string;

  @ApiProperty({
    description: '중분류명',
    example: '중추신경계 질환 증상 완화(통증, 수면, 경련, 정신질환)',
  })
  @IsString()
  mscName!: string;
}

// B-5. 중분류 삭제 (일괄)
export class DeleteMedicationStandardDto {
  @ApiProperty({ description: '삭제할 ID 목록', type: [Number], example: [1, 2, 3] })
  @IsArray()
  @IsInt({ each: true })
  ids!: number[];
}

// ==================== C. 투약기준 추천 API ====================

// C-1. 투약기준 추천 조회 Request
export class GetRecommendedMedicationDto {
  @ApiProperty({
    description: '주문 상세 ID (정회원)',
    example: 123,
    required: false
  })
  @IsInt()
  @IsOptional()
  @Type(() => Number)
  @Min(1)
  oddId?: number;

  @ApiProperty({
    description: 'B2C 주문 상세 ID',
    example: 456,
    required: false
  })
  @IsInt()
  @IsOptional()
  @Type(() => Number)
  @Min(1)
  bodId?: number;

  @ApiProperty({
    description: '고객사 주문 상세 ID',
    example: 789,
    required: false
  })
  @IsInt()
  @IsOptional()
  @Type(() => Number)
  @Min(1)
  codId?: number;
}

// C-2. 투약기준 추천 항목
export class RecommendedMedicationItemDto {
  @Expose()
  @ApiProperty({
    description: '분류항목명(약품명)',
    example: '아모닐정250밀리그램(아모다피닐(미분화))_(0.25g/1정)'
  })
  itemName!: string;

  @Expose()
  @ApiProperty({
    description: '분류효능',
    example: '중추신경계 질환 증상 완화(통증,수면,경련,정신질환)'
  })
  efficacy!: string;

  @Expose()
  @ApiProperty({ description: '항목 일수', example: 90 })
  itemDay!: number;
}

// C-2-1. 투약기준 카테고리 (그룹화된 데이터)
export class RecommendedMedicationCategoryDto {
  @Expose()
  @ApiProperty({ description: '분류명', example: '중추 신경계용 약' })
  categoryName!: string;

  @Expose()
  @ApiProperty({ description: '카테고리 총 일수', example: 180 })
  totalDay!: number;

  @Expose()
  @ApiProperty({
    type: [RecommendedMedicationItemDto],
    description: '투약 항목 목록'
  })
  @Type(() => RecommendedMedicationItemDto)
  items!: RecommendedMedicationItemDto[];
}

// C-3. 투약기준 추천 조회 Response
export class GetRecommendedMedicationResponseDto {
  @Expose()
  @ApiProperty({ description: '성공 여부', default: true })
  success!: boolean;

  @Expose()
  @ApiProperty({
    type: [RecommendedMedicationCategoryDto],
    description: '투약기준 추천 목록 (카테고리별 그룹화)'
  })
  @Type(() => RecommendedMedicationCategoryDto)
  data!: RecommendedMedicationCategoryDto[];
}

// ==================== D. 5년 내 30일이상 투약 그룹 API ====================

export class Dosing30DayDiagnosisDto {
  @Expose()
  @ApiProperty({ description: '진단코드', nullable: true })
  diseaseCode!: string | null;

  @Expose()
  @ApiProperty({ description: '진단명', nullable: true })
  diseaseName!: string | null;
}

// D-2. 처방 기록 항목
export class Dosing30DayGroupRecordDto {
  @Expose()
  @ApiProperty({ description: '진료 시작일' })
  treatStartDate!: string | null;

  @Expose()
  @ApiProperty({ description: '병·의원' })
  hospitalName!: string | null;

  @Expose()
  @ApiProperty({ type: [Dosing30DayDiagnosisDto], description: '동일 진료시작일·병의원의 기본진료 진단 목록' })
  @Type(() => Dosing30DayDiagnosisDto)
  diagnoses!: Dosing30DayDiagnosisDto[];

  @Expose()
  @ApiProperty({ description: '약품명' })
  drugName!: string | null;

  @Expose()
  @ApiProperty({ description: '성분' })
  ingredients!: string | null;

  @Expose()
  @ApiProperty({ description: '1회투약량' })
  oneDose!: number | null;

  @Expose()
  @ApiProperty({ description: '1회투여횟수' })
  dailyDosesNumber!: number | null;

  @Expose()
  @ApiProperty({ description: '총 투약일수' })
  totalDosingDays!: number | null;
}

// D-2-1. 30일이상 투약 카테고리 그룹 항목
export class Dosing30DayGroupItemDto {
  @Expose()
  @ApiProperty({ description: '약효 카테고리명 (예: 혈압강하제)' })
  categoryName!: string;

  @Expose()
  @ApiProperty({ description: '총 투약일수' })
  totalDosingDays!: number;

  @Expose()
  @ApiProperty({ description: '최초 진료일' })
  startDate!: string;

  @Expose()
  @ApiProperty({ description: '최종 진료일' })
  endDate!: string;

  @Expose()
  @ApiProperty({ type: [Dosing30DayGroupRecordDto], description: '진료 기록 목록 (약국 제외)' })
  @Type(() => Dosing30DayGroupRecordDto)
  records!: Dosing30DayGroupRecordDto[];
}

// D-3. 30일이상 투약 그룹 조회 Response
export class GetDosing30DayGroupsResponseDto {
  @Expose()
  @ApiProperty({ description: '성공 여부', default: true })
  @IsBoolean()
  success!: boolean;

  @Expose()
  @ApiProperty({ type: [Dosing30DayGroupItemDto], description: '30일이상 투약 카테고리 그룹 목록' })
  @Type(() => Dosing30DayGroupItemDto)
  data!: Dosing30DayGroupItemDto[];
}
