import { int, mysqlTable, timestamp } from 'drizzle-orm/mysql-core';
import { strikeReason } from '@db/schema/strikeReason.ts';
import type { MySql2Database } from 'drizzle-orm/mysql2';
import { eq } from 'drizzle-orm';
import { report } from '@db/schema/report.ts';

type Database = MySql2Database<{ strike: typeof strike }>;

export const strike = mysqlTable('strike', {
  at: timestamp('at', { mode: 'date' }).notNull(),
  reportId: int('report_id')
    .notNull()
    .references(() => report.id),
  strikeReasonId: int('strike_reason_id')
    .notNull()
    .references(() => strikeReason.id)
});

export type EditStrikeReq = {
  reportId: number;
  at?: Date;
  strikeReasonId: number;
};

export type DeleteStrikeReq = {
  reportId: number;
};

export type GetStrikeByReportIdReq = {
  reportId: number;
};

export type GetStrikesByUserIdReq = {
  userId: number;
};

export async function editStrike(db: Database, values: EditStrikeReq) {
  return db
    .insert(strike)
    .values({
      at: values.at ?? new Date(),
      reportId: values.reportId,
      strikeReasonId: values.strikeReasonId
    })
    .onDuplicateKeyUpdate({
      set: {
        at: values.at ?? new Date(),
        strikeReasonId: values.strikeReasonId
      }
    });
}

export async function deleteStrike(db: Database, values: DeleteStrikeReq) {
  return db.delete(strike).where(eq(strike.reportId, values.reportId)).limit(1);
}

export async function getStrikeByReportId(db: Database, values: GetStrikeByReportIdReq) {
  const strikes = await db
    .select({
      strike,
      strikeReason
    })
    .from(strike)
    .where(eq(strike.reportId, values.reportId))
    .leftJoin(strikeReason, eq(strike.strikeReasonId, strikeReason.id));

  return strikes[0] ?? null;
}

export async function getStrikesByUserId(db: Database, values: GetStrikesByUserIdReq) {
  return db
    .select({
      at: strike.at,
      report: report,
      reason: strikeReason
    })
    .from(strike)
    .innerJoin(strikeReason, eq(strike.strikeReasonId, strikeReason.id))
    .innerJoin(report, eq(strike.reportId, report.id))
    .where(eq(report.reportedId, values.userId));
}
