import { InhouseService } from './inhouse.service';
import { encodeInhouseSession } from './inhouse.types';

/**
 * 자동차보험(diagAuto) 진료 매핑 회귀 테스트.
 * 엔진은 진료일수=resVisitDays, 자동차보험총진료비=resPublicCharge로 내보내지만,
 * createCarTreat는 resTreatDate/resMedicalFee를 읽는다. normalizeTreatment의 자동차 전용
 * alias(isAuto=true)가 그 간극을 메우는지, 건강(isAuto=false)엔 안 새는지 검증한다.
 * 매핑 표준은 octover/hyphen/coocon 3벤더와 동일(진료일수=resTreatDate, 자동차보험총진료비=resMedicalFee).
 */
describe('InhouseService.normalizeTreatment — 자동차 alias (3벤더 표준 정합)', () => {
  const svc = new InhouseService({} as never, {} as never);
  const norm = (t: unknown, isAuto = false): any =>
    (
      svc as never as {
        normalizeTreatment(t: unknown, isAuto: boolean): unknown;
      }
    ).normalizeTreatment(t, isAuto);

  it('자동차(isAuto=true): resVisitDays→resTreatDate, resPublicCharge→resMedicalFee 별칭 채움', () => {
    const out = norm(
      {
        resBasicTreatList: [
          {
            resVisitDays: '3',
            resPublicCharge: '150,000',
            resTotalAmount: '200,000',
          },
        ],
      },
      true,
    );
    const row = out.resBasicTreatList[0];
    expect(row.resTreatDate).toBe('3'); // 진료일수 (3벤더: 내원일수/numberVisitDays)
    expect(row.resMedicalFee).toBe('150,000'); // 자동차보험총진료비 (3벤더: 혜택받은금액/medicalExpensesIPaid)
    expect(row.resTotalAmount).toBe('200,000'); // 청구진료비
    expect(row.resVisitDays).toBe('3'); // 원본 필드도 유지
  });

  it('엔진이 resTreatDate/resMedicalFee를 직접 주면 그 값이 우선(?? fallback)', () => {
    const out = norm(
      {
        resBasicTreatList: [
          {
            resTreatDate: '5',
            resMedicalFee: '99,000',
            resVisitDays: '3',
            resPublicCharge: '150,000',
          },
        ],
      },
      true,
    );
    expect(out.resBasicTreatList[0].resTreatDate).toBe('5');
    expect(out.resBasicTreatList[0].resMedicalFee).toBe('99,000');
  });

  it('건강(isAuto=false): 자동차 alias 미적용 → resTreatDate/resMedicalFee 없음(레코드 청결)', () => {
    const out = norm(
      { resBasicTreatList: [{ resVisitDays: '1', resPublicCharge: '30,000' }] },
      false,
    );
    const row = out.resBasicTreatList[0];
    expect(row.resTreatDate).toBeUndefined();
    expect(row.resMedicalFee).toBeUndefined();
    expect(row.resVisitDays).toBe('1'); // 건강 필드는 그대로
    expect(row.resPublicCharge).toBe('30,000');
  });

  it('비진료 형태(약 요약 등)는 그대로 통과', () => {
    expect(norm({ resMedicineSummaryList: [] }, true)).toEqual({
      resMedicineSummaryList: [],
    });
  });

  it('빈 진료 리스트도 안전(빈 배열 유지)', () => {
    const out = norm({ resBasicTreatList: [] }, true);
    expect(out.resBasicTreatList).toEqual([]);
    expect(out.resDetailTreatList).toEqual([]);
  });
});

describe('InhouseService.cancelCertify', () => {
  it('uses the existing engine cancel endpoint with the sticky cookie', async () => {
    const http = { post: jest.fn().mockResolvedValue({}) };
    const config = {
      get: jest.fn((key: string) =>
        key === 'inhouse.baseUrl' ? 'https://engine.example' : 'key',
      ),
    };
    const svc = new InhouseService(config as never, http as never);
    const jti = encodeInhouseSession({
      sessionId: 'session-1',
      authType: 'mobile',
      albCookie: 'AWSALB=sticky',
    });

    await svc.cancelCertify(jti);

    expect(http.post).toHaveBeenCalledWith(
      'https://engine.example/api/cancel',
      { sessionId: 'session-1' },
      expect.objectContaining({
        timeout: 5000,
        headers: expect.objectContaining({ Cookie: 'AWSALB=sticky' }),
      }),
    );
  });
});

describe('InhouseService 간편인증 전달', () => {
  const config = {
    get: jest.fn((key: string) =>
      key === 'inhouse.baseUrl' ? 'https://engine.example' : 'key',
    ),
  };

  it('1차 loginTypeLevel을 엔진에 전달한다', async () => {
    const http = {
      postWithResponse: jest.fn().mockResolvedValue({
        data: {
          code: 'INH-0001',
          category: 'OK',
          result: {
            sessionId: 'simple-1',
            status: 'cert-screen-ready',
            code: 'INH-0001',
          },
        },
        headers: {},
      }),
    };
    const svc = new InhouseService(config as never, http as never);
    const log = jest.fn();
    (svc as any).logger.log = log;

    await svc.fetchCertifyMultiple([
      {
        loginType: '5',
        loginTypeLevel: '6',
        userName: '테스트',
        identity: '0000000000000',
        phoneNo: '01000000000',
      } as any,
    ]);

    expect(http.postWithResponse).toHaveBeenCalledWith(
      'https://engine.example/api/certify',
      expect.objectContaining({ authMethod: 'simple', loginTypeLevel: '6' }),
      expect.any(Object),
    );
    expect(JSON.stringify(log.mock.calls)).not.toContain('simple-1');
  });

  it('2차 simpleAuth를 엔진에 전달한다', async () => {
    const http = {
      post: jest.fn().mockResolvedValue({
        code: 'INH-0000',
        category: 'OK',
        result: {
          ok: true,
          code: 'INH-0000',
          data: {
            treatment: {
              resBasicTreatList: [],
              resDetailTreatList: [],
              resPrescribeDrugList: [],
            },
          },
        },
      }),
    };
    const svc = new InhouseService(config as never, http as never);
    const jti = encodeInhouseSession({
      sessionId: 'simple-1',
      authType: 'simple',
    });

    await svc.fetchTreatmentMultiple(
      [
        {
          inquiryType: '0',
          simpleAuth: '1',
          twoWayInfo: { jti },
        } as any,
      ],
      1,
    );

    expect(http.post).toHaveBeenCalledWith(
      'https://engine.example/api/treat',
      expect.objectContaining({ sessionId: 'simple-1', simpleAuth: '1' }),
      expect.any(Object),
    );
  });
});

describe('InhouseService 국세청 오류 전달', () => {
  it('엔진 non-2xx 응답의 세션 상태와 사용자 메시지를 보존한다', async () => {
    const engineError = {
      ok: false,
      code: 'INH-2003',
      message: '홈택스 간편인증이 승인되지 않았습니다.',
      result: {
        detailCode: 'NTS_AUTH_REJECTED',
        sessionReusable: false,
      },
    };
    const http = {
      post: jest.fn().mockRejectedValue({
        code: 'ERR_BAD_REQUEST',
        response: { status: 401, data: engineError },
      }),
    };
    const config = {
      get: jest.fn((key: string) =>
        key === 'inhouse.baseUrl' ? 'https://engine.example' : 'key',
      ),
    };
    const svc = new InhouseService(config as never, http as never);

    await expect(
      svc.requestNts('complete', { sessionId: 'session-1' }),
    ).resolves.toEqual(engineError);
  });
});
