import { translateChecked } from '@api/helpers/translate.helper';
import { DrizzleService } from '@lib/drizzle/src/drizzle.service';
import { Injectable } from '@nestjs/common';
import dayjs from 'dayjs';
import { and, asc, count, desc, eq, gte, lte, sql, SQL } from 'drizzle-orm';
import { tnAdmin, tnAdminAlarm } from 'drizzle/schema';
import {
  AdminAlarmCheckDto,
  AdminAlarmCreatedDto,
  AdminAlarmListDto,
} from './alarm-admin.dto';
import { AdminAlarmDetailKind, AdminAlarmKind } from './alram-admin.entity';

@Injectable()
export class AdminAlarmRepository {
  constructor(private drizzle: DrizzleService) {}

  private alarmKind() {
    return sql<AdminAlarmKind>`CASE
      WHEN JSON_UNQUOTE(JSON_EXTRACT(${tnAdminAlarm.aadDetail}, '$.kind')) = ${AdminAlarmDetailKind.신규계정업로드} THEN ${AdminAlarmKind.신규계정업로드}
      WHEN JSON_UNQUOTE(JSON_EXTRACT(${tnAdminAlarm.aadDetail}, '$.kind')) = ${AdminAlarmDetailKind.계정수정업로드} THEN ${AdminAlarmKind.계정수정업로드}
      WHEN JSON_UNQUOTE(JSON_EXTRACT(${tnAdminAlarm.aadDetail}, '$.kind')) = ${AdminAlarmDetailKind.상태변경업로드} THEN ${AdminAlarmKind.상태변경업로드}
      WHEN JSON_UNQUOTE(JSON_EXTRACT(${tnAdminAlarm.aadDetail}, '$.kind')) = ${AdminAlarmDetailKind.조직권한업로드} THEN ${AdminAlarmKind.조직권한업로드}
      WHEN ${tnAdminAlarm.aadType} = 'AAD001' AND (${tnAdminAlarm.aadMessage} LIKE '%상태변경업로드%' OR ${tnAdminAlarm.aadMessage} LIKE '%구독상태 일괄업로드%') THEN ${AdminAlarmKind.상태변경업로드}
      WHEN ${tnAdminAlarm.aadType} = 'AAD001' AND ${tnAdminAlarm.aadMessage} LIKE '%조직·권한업로드%' THEN ${AdminAlarmKind.조직권한업로드}
      WHEN ${tnAdminAlarm.aadType} = 'AAD001' AND ${tnAdminAlarm.aadMessage} LIKE '%계정수정업로드%' THEN ${AdminAlarmKind.계정수정업로드}
      WHEN ${tnAdminAlarm.aadType} = 'AAD001' THEN ${AdminAlarmKind.신규계정업로드}
      WHEN ${tnAdminAlarm.aadType} = 'AAD002' AND ${tnAdminAlarm.aadMessage} LIKE '%구독해지%' THEN ${AdminAlarmKind.구독해지처리}
      WHEN ${tnAdminAlarm.aadType} = 'AAD002' AND ${tnAdminAlarm.aadMessage} LIKE '%재구독%' THEN ${AdminAlarmKind.재구독처리}
      WHEN ${tnAdminAlarm.aadType} = 'AAD002' THEN ${AdminAlarmKind.최초구독처리}
      WHEN ${tnAdminAlarm.aadType} = 'AAD003' THEN ${AdminAlarmKind.재분석처리}
      ELSE ${AdminAlarmKind.기타}
    END`;
  }

  private alarmType() {
    return sql<string>`CASE
      WHEN ${tnAdminAlarm.aadType} = 'AAD003' THEN '분석'
      ELSE GET_STATUS(${tnAdminAlarm.aadType})
    END`;
  }

  async create(dto: AdminAlarmCreatedDto) {
    await this.drizzle.insert(tnAdminAlarm).values(dto);
  }

  async delete(dto: AdminAlarmCheckDto) {
    await this.drizzle
      .delete(tnAdminAlarm)
      .where(eq(tnAdminAlarm.aadId, dto.aadId));
  }

  async getDetail(aadId: number, admId: number) {
    const [detail] = await this.drizzle
      .select({
        aadId: tnAdminAlarm.aadId,
        aadType: this.alarmType(),
        alarmKind: this.alarmKind(),
        aadResultType: sql`GET_STATUS(${tnAdminAlarm.aadResultType})`,
        aadMessage: tnAdminAlarm.aadMessage,
        aadChecked: translateChecked(tnAdminAlarm.aadChecked).as('aadChecked'),
        aadRedirectPage: tnAdminAlarm.aadRedirectPage,
        aadDetail: tnAdminAlarm.aadDetail,
        aadCreatedAt: tnAdminAlarm.aadCreatedAt,
        aadUpdatedAt: tnAdminAlarm.aadUpdatedAt,
      })
      .from(tnAdminAlarm)
      .where(and(eq(tnAdminAlarm.aadId, aadId), eq(tnAdminAlarm.admId, admId)));

    return detail;
  }

  async check(dto: AdminAlarmCheckDto) {
    await this.drizzle
      .update(tnAdminAlarm)
      .set({ aadChecked: 1 })
      .where(eq(tnAdminAlarm.aadId, dto.aadId));
  }

  async checkAll(id: number) {
    await this.drizzle
      .update(tnAdminAlarm)
      .set({ aadChecked: 1 })
      .where(eq(tnAdminAlarm.admId, id));
  }
  async getList(
    where: SQL<unknown> | undefined,
    orderBy: SQL<unknown>,
    page: number,
  ) {
    const limit = 10;
    const offset = (+page - 1) * limit;

    return await this.drizzle
      .select({
        aadId: tnAdminAlarm.aadId,
        aadType: this.alarmType(),
        alarmKind: this.alarmKind(),
        aadResultType: sql`GET_STATUS(${tnAdminAlarm.aadResultType})`,
        aadMessage: tnAdminAlarm.aadMessage,
        aadChecked: translateChecked(tnAdminAlarm.aadChecked).as('aadChecked'),
        hasDetail: sql<boolean>`${tnAdminAlarm.aadDetail} IS NOT NULL`,
        // aadRedirectPage: tnAdminAlarm.aadRedirectPage,
        aadCreatedAt: tnAdminAlarm.aadCreatedAt,
        aadUpdatedAt: tnAdminAlarm.aadUpdatedAt,
      })
      .from(tnAdminAlarm)
      .leftJoin(tnAdmin, eq(tnAdmin.admId, tnAdminAlarm.admId))
      .where(where)
      .orderBy(orderBy)
      .limit(limit)
      .offset(offset);
  }

  async count(where: SQL<unknown> | undefined) {
    const [totalCount] = await this.drizzle
      .select({ count: count() })
      .from(tnAdminAlarm)
      .leftJoin(tnAdmin, eq(tnAdmin.admId, tnAdminAlarm.admId))
      .where(where);

    return totalCount.count ?? 0;
  }

  async noCheckCount(id: number) {
    const nowDate = dayjs();
    const subDate = nowDate.subtract(1, 'month').format('YYYY-MM-DD HH:mm:ss');
    const [totalCount] = await this.drizzle
      .select({ count: count() })
      .from(tnAdminAlarm)
      .where(
        and(
          eq(tnAdminAlarm.admId, id),
          eq(tnAdminAlarm.aadChecked, 0),
          gte(tnAdminAlarm.aadCreatedAt, subDate),
        ),
      );

    return totalCount.count ?? 0;
  }

  async whereClause(dto: AdminAlarmListDto, admId: number) {
    const { dateType, startDate, endDate, alarmKind } = dto;
    //* 3개월

    const where: SQL[] = [];

    if (!!admId) {
      const whereId = eq(tnAdminAlarm.admId, admId);
      where.push(whereId);
    }

    if (!!startDate && !!endDate) {
      const dateWhere = this.makeDateWhere(dateType, startDate, endDate);
      where.push(...dateWhere);
    }

    if (alarmKind) {
      where.push(eq(this.alarmKind(), alarmKind));
    }

    return and(...where);
  }

  async adminOrderByClause() {
    return asc(tnAdminAlarm.aadChecked), desc(tnAdminAlarm.aadId);
  }

  makeDateWhere(dateType: string, startDate: string, endDate: string): SQL[] {
    const where: SQL[] = [];

    switch (dateType) {
      case 'aadCreatedAt': {
        where.push(gte(tnAdminAlarm.aadCreatedAt, startDate));
        where.push(lte(tnAdminAlarm.aadCreatedAt, endDate));
        return where;
      }
      default: {
        where.push(gte(tnAdminAlarm.aadCreatedAt, startDate));
        where.push(lte(tnAdminAlarm.aadCreatedAt, endDate));
        return where;
      }
    }
  }
}
