import { AlertSignalService } from '@api/modules/alert/alert-signal.service';
import { SubscribeService } from '@api/modules/subscribe/subscribe/subscribe.service';
import { NestFactory } from '@nestjs/core';
import dayjs from 'dayjs';
import { Logger } from 'nestjs-pino';
import { AppModule } from '../app.module';

/**
 * 일반FC 정기구독결제 스케줄러
 * 동작주기 : 매일 아침 9시 / 저녁 18시
 * 구독상태가 [구독] 또는 [변경]이고 구독결제일의 대상자를 선택하여 정기결제 및 주문처리를 합니다.
 *
 * 해당 로직은 AWS EventBridge에서 실행되도록 설정되어 있습니다.
 */
(async () => {
  const app = await NestFactory.createApplicationContext(AppModule, {
    bufferLogs: true,
  });
  app.useLogger(app.get(Logger));
  const logger = app.get(Logger);
  const subscribeService = app.get(SubscribeService);
  const signals = app.get(AlertSignalService);

  const list = await subscribeService.getSubscriptionInfoForSchedule();
  let flag: boolean = false;
  if (dayjs().hour() == 18) {
    flag = true;
  } else if (dayjs().hour() == 9) {
    flag = false;
  } else {
    logger.fatal(`이상 시간 감지: ${dayjs().hour()}시`);
  }

  const subscribeIds = list.map((item) => item.subId);
  logger.log(subscribeIds);
  logger.log(list);
  for await (const item of list) {
    logger.log(item);
    //* A1 예외 축 분모(M2 §D2) — 호출 **전**에 시도를 계상한다. append-only 라 불변이다.
    await signals.bumpSubscriptionAttempt('fc').catch(() => {});
    await subscribeService
      .addSubscribeScheduler(item, flag, false)
      .catch(async (error) => {
        //* A1 예외 축 분자 — 기존 catch 안에 1줄만 얹는다. 아래 흐름은 무변경(UI14).
        //*  **await 한다**: fire-and-forget 이면 마지막 회차의 INCR 이 아래 process.exit(0) 에
        //*  잘려 분자만 유실된다(분모는 :40 에서 await 되어 남는다). 실패율이 실제보다 낮게
        //*  나오는 미탐 방향이며, §D2 의 "각 시도가 정확히 한 번씩 계상"이 깨진다.
        await signals.bumpSubscriptionException('fc').catch(() => {});
        logger.log(error);
      });
  }

  //* 하트비트(M2 §D4) — 성공 종료 직전에만 남긴다. 중도 throw·비정상 종료는
  //*  자동으로 '하트비트 없음' 이 되어 A3 가 잡는다. 실패가 본 작업을 죽이면 안 된다(UI17).
  await app
    .get(AlertSignalService)
    .markSchedule('regular-subscription')
    .catch(() => {});

  process.exit(0);
})();
