import { Certify, CodefResult, DataDto } from '@lib/codef/src/codef.dto';
import {
  ApiExtraModels,
  ApiProperty,
  IntersectionType,
  OmitType,
  PickType,
} from '@nestjs/swagger';
import { Expose, Transform, Type } from 'class-transformer';
import {
  IsInt,
  IsObject,
  IsOptional,
  IsString,
  ValidateNested,
} from 'class-validator';
import { Member } from '../fc/fc.entity';
import { OrderDetail } from '../order/order-detail/order-detail.entity';
import { User } from '../user/user.entity';

export class CertiftDto {
  @ApiProperty({
    description: '진료정보 URL 엔드포인트 code (알림톡 코드 또는 B2C 기업코드)',
    example: 'ae4955c1733test',
  })
  @IsString()
  altCode!: string;

  @ApiProperty({
    description: 'B2C 플로우 여부',
    example: false,
    required: false,
  })
  @IsOptional()
  isB2c?: boolean;

  @ApiProperty({
    description: '광고 동의 여부 (B2C only)',
    example: '0',
    required: false,
  })
  @IsOptional()
  @IsString()
  marketingAgree?: string;

  @ApiProperty({ description: '진료정보요청 고객명', example: '홍길동' })
  @IsString()
  usrName!: string;

  @ApiProperty({
    description: '진료정보요청 고객핸드폰번호 (-)제외',
    example: '01011112222',
  })
  @IsString()
  @Transform(({ value }) => {
    return value.replace(/[^0-9]/g, '');
  })
  usrPhone!: string;

  @ApiProperty({
    description: '진료정보요청 고객 생년월일',
    example: '910801',
  })
  @IsString()
  @Transform(({ value }) => {
    return value.replace(/[^0-9]/g, '');
  })
  usrBirth!: string;

  @ApiProperty({
    description: '진료정보요청 고객 주민번호뒷자리',
    example: '1111111',
  })
  @IsString()
  @Transform(({ value }) => {
    return value.replace(/[^0-9]/g, '');
  })
  identityNo!: string;

  @ApiProperty({
    description: `인증구분 
                  2 :인증서 또는 휴대폰인증
                  5 :간편인증`,
    example: '5',
    type: String,
  })
  @IsString()
  loginType!: '2' | '5';

  /** 인증상세구분 */
  @ApiProperty({
    description: `인증상세구분
                  loginType="2" 의 경우 
                  "0": 인증서
                  "1": 휴대폰 (사용)
                  loginType="5" 의 경우
                  "1":카카오톡 (사용)
                  "2":페이코
                  "3":삼성패스
                  "4":KB모바일
                  "5":통신사(PASS) (사용)
                  "6":네이버 (사용)
                  "7":신한인증서
                  "8": toss (사용)`,
    example: '1',

    type: String,
  })
  @IsString()
  loginTypeLevel!: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';

  @ApiProperty({
    description: `인증방법
                  loginType="2" 이고 loginTypeLevel="1" 이라면 필수
                  "0":SMS인증
                  "1":PASS인증 (default=0)`,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  authMethod?: '0' | '1' = '0';

  @ApiProperty({
    description: `통신사
                  authMethod="1" 필수,
                  loginType=“5”이고 loginTypeLevel=“5” 필수
                  "0":SKT
                  "1":KT
                  "2":LG U+
                  "3":알뜰폰 (SKT)
                  "4":알뜰폰(KT)
                  "5":알뜰폰(LG U+)`,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  telecom?: '0' | '1' | '2' | '3' | '4' | '5';

  @ApiProperty({
    description: `제한시간 
                  loginType="2" 이고 loginTypeLevel="1" 의 경우 선택 입력
                  SMS 제한시간, 단위 초
                  (default:170s, 30s~170s)`,
    example: '170',
    type: String,
  })
  @IsString()
  @IsOptional()
  timeout?: string;

  @ApiProperty({
    description: `보안문자 실행여부
                  loginType="2"(인증서, SMS)이고, loginTypeLevel="1"(휴대폰)인 경우 선택
                  "0":미적용
                  "1":적용 (default : 0))`,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  secureNoYN?: '0' | '1' = '0';

  //* [1단계] 대기열 재요청 시 기존 큐 ID — 만석이어도 순번 유지(맨뒤 추락 방지). 멀티 디스패처만 사용.
  @ApiProperty({ required: false, description: '대기열 재요청 시 기존 대기열 ID(순번 유지용)' })
  @IsString()
  @IsOptional()
  queueId?: string;
}

//* 심평원인증요청후 진료내역 요청 시 추가 항목
export class TreatDto extends OmitType(CertiftDto, []) {
  @IsString()
  @IsOptional()
  reminderAttempt?: string;

  @ApiProperty({ description: '인증후 반환받은 주문상세Id', example: 1 })
  @IsInt()
  oddId!: number;

  @ApiProperty({
    description: `보안문자 이미지정보 
                  (다른인증 확인후 필요없을 시 삭제예정)
                  `,
    example: '66d7c644ec82a9a95',
    type: String,
  })
  @IsString()
  @IsOptional()
  secureNo?: string;

  @ApiProperty({
    description: `(다른인증 확인후 필요없을 시 삭제예정)
                  보안문자 새로고침	
                  "0": 기본, "1": 재요청, "2" : 입력취소(default:0)
                  `,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  secureNoRefresh?: string;

  @ApiProperty({
    description: `(다른인증 확인후 디폴트 1일시 삭제예정)
                  간편인증
                  "0": cancel , "1": ok
                  `,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  smsAuthNo?: string;

  @ApiProperty({
    description: `(다른인증 확인후 디폴트 1일시 삭제예정)
                  간편인증
                  "0": cancel , "1": ok
                  `,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  simpleAuth?: string;

  @ApiProperty({
    description: `추가 요청임을 알리는 설정값
                  인증요청후 진료정보요청시 필수값 (필수값고정 : 1)
                  값: O or 1 
                  `,
    example: 1,
  })
  @IsInt()
  is2Way!: number;

  @ApiProperty({
    description: `잡 인덱스
                  인증요청후 반환값의 잡인덱스
                  인증완료후 진료정보요청 시 필수값   
                  `,
    example: 0,
  })
  @IsInt()
  jobIndex!: number;

  @ApiProperty({
    description: `스레드 인덱스
                  인증요청후 반환값의 스레드인덱스
                  인증완료후 진료정보요청 시 필수값   
                  `,
    example: 0,
  })
  @IsInt()
  threadIndex!: number;

  @ApiProperty({
    description: `트렌잭션 아이디 
                  인증요청후 반환값의 트렌잭션 아이디
                  인증완료후 진료정보요청시 필수값   
                  `,
    example: '66d7c644ec82a9a95',
    type: String,
  })
  @IsString()
  jti!: string;

  @ApiProperty({
    description: `추가인증시간 
                  인증요청후 반환값은 추가인증시간
                  인증완료후 진료정보요청 시 필수값   
                  `,
    example: 1725417030279,
  })
  @IsInt()
  twoWayTimestamp!: number;
}

export class CodefTreatResultDto extends IntersectionType(
  OmitType(CodefResult, []),
  PickType(OrderDetail, ['oddId']),
  PickType(Member, ['memId']),
  PickType(User, ['usrName']),
) {}

export class CompareDto {
  @ApiProperty({ description: '주문상세Id', example: 1 })
  @IsInt()
  oddId!: number;
}

export class TreatmentInfoDto extends PickType(DataDto, [
  'resBasicTreatList',
  'resDetailTreatList',
  'resPrescribeDrugList',
]) {}

export class TreatmentInfoCarDto extends PickType(DataDto, [
  'resBasicTreatList',
  'resDetailTreatList',
]) {}

//* 심평원인증요청후 진료내역 요청 시 추가 항목
export class TreatCompareDto extends OmitType(CertiftDto, []) {
  @IsString()
  @IsOptional()
  reminderAttempt?: string;

  @ApiProperty({ description: '인증후 반환받은 주문상세Id', example: 1 })
  @IsInt()
  oddId!: number;

  @ApiProperty({
    description: `보안문자 이미지정보 
                  (다른인증 확인후 필요없을 시 삭제예정)
                  `,
    example: '66d7c644ec82a9a95',
    type: String,
  })
  @IsString()
  @IsOptional()
  secureNo?: string;

  @ApiProperty({
    description: `(다른인증 확인후 필요없을 시 삭제예정)
                  보안문자 새로고침	
                  "0": 기본, "1": 재요청, "2" : 입력취소(default:0)
                  `,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  secureNoRefresh?: string;

  @ApiProperty({
    description: `(다른인증 확인후 디폴트 1일시 삭제예정)
                  간편인증
                  "0": cancel , "1": ok
                  `,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  smsAuthNo?: string;

  @ApiProperty({
    description: `(다른인증 확인후 디폴트 1일시 삭제예정)
                  간편인증
                  "0": cancel , "1": ok
                  `,
    example: '0',
    type: String,
  })
  @IsString()
  @IsOptional()
  simpleAuth?: string;

  @ApiProperty({
    description: `추가 요청임을 알리는 설정값
                  인증요청후 진료정보요청시 필수값 (필수값고정 : 1)
                  값: O or 1 
                  `,
    example: 1,
  })
  @IsInt()
  is2Way!: number;

  @ApiProperty({
    description: `잡 인덱스
                  인증요청후 반환값의 잡인덱스
                  인증완료후 진료정보요청 시 필수값   
                  `,
    example: 0,
  })
  @IsInt()
  jobIndex!: number;

  @ApiProperty({
    description: `스레드 인덱스
                  인증요청후 반환값의 스레드인덱스
                  인증완료후 진료정보요청 시 필수값   
                  `,
    example: 0,
  })
  @IsInt()
  threadIndex!: number;

  @ApiProperty({
    description: `트렌잭션 아이디 
                  인증요청후 반환값의 트렌잭션 아이디
                  인증완료후 진료정보요청시 필수값   
                  `,
    example: '66d7c644ec82a9a95',
    type: String,
  })
  @IsString()
  jti!: string;

  @ApiProperty({
    description: `추가인증시간 
                  인증요청후 반환값은 추가인증시간
                  인증완료후 진료정보요청 시 필수값   
                  `,
    example: 1725417030279,
  })
  @IsInt()
  twoWayTimestamp!: number;
}

//--------------------- ResponseDto ---------------------//
class OrderDetailTreatDto extends PickType(OrderDetail, ['oddId']) {}

@ApiExtraModels(OrderDetailTreatDto, Certify)
export class GetCertifyResponseDto {
  @Expose()
  @ApiProperty({ type: OrderDetailTreatDto, description: '주문상세정보' })
  @ValidateNested({ each: true })
  @Type(() => OrderDetailTreatDto)
  @IsObject()
  orderDetail!: OrderDetailTreatDto;

  @Expose()
  @ApiProperty({ type: Certify, description: '주문상세정보' })
  @ValidateNested({ each: true })
  @Type(() => Certify)
  @IsObject()
  data!: Certify;

  //* 대기열 진입(multi 만석) 시에만 채워짐 — 이 값으로 순번 폴링 후 certify 재요청
  @Expose()
  @ApiProperty({ required: false, description: '대기열 ID (만석 시)' })
  @IsString()
  @IsOptional()
  queueId?: string;
}
