import type { MySql2Database } from 'drizzle-orm/mysql2';
import { int, mysqlTable, varchar } from 'drizzle-orm/mysql-core';
import { user } from '@db/schema/user.ts';
import { eq } from 'drizzle-orm';
import { generateRandomString } from '@util/random.ts';
import { BASE_PATH } from 'astro:env/server';

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

export const directSignup = mysqlTable('direct_signup', {
  hash: varchar('hash', { length: 255 }).unique().notNull(),
  userId: int('user_id').references(() => user.id)
});

export type AddDirectSignupReq = {};

export type SetDirectSignupUserReq = {
  hash: string;
  userId: number;
};

export type DeleteDirectSignupReq = {
  hash: string;
};

export type GetDirectSignupsReq = {};

export type GetDirectSignupByHashReq = {
  hash: string;
};

export async function addDirectSignup(db: Database, _values: AddDirectSignupReq) {
  const hash = generateRandomString(16);

  await db.insert(directSignup).values({
    hash: hash
  });

  return { hash: hash, url: `${BASE_PATH}/signup/${hash}` };
}

export async function setDirectSignupUser(db: Database, values: SetDirectSignupUserReq) {
  return db
    .update(directSignup)
    .set({
      userId: values.userId
    })
    .where(eq(directSignup.hash, values.hash));
}

export async function deleteDirectSignup(db: Database, values: DeleteDirectSignupReq) {
  return db.delete(directSignup).where(eq(directSignup.hash, values.hash));
}

export async function getDirectSignups(db: Database, _values: GetDirectSignupsReq) {
  const directSignups = await db
    .select({
      hash: directSignup.hash,
      user: user
    })
    .from(directSignup)
    .leftJoin(user, eq(directSignup.userId, user.id));

  return directSignups.map((d) => ({ ...d, url: `${BASE_PATH}/signup/${d.hash}` }));
}

export async function getDirectSignupByHash(db: Database, values: GetDirectSignupByHashReq) {
  const directSignups = await db
    .select({
      hash: directSignup.hash,
      user: user
    })
    .from(directSignup)
    .leftJoin(user, eq(directSignup.userId, user.id))
    .where(eq(directSignup.hash, values.hash))
    .limit(1);

  return directSignups[0] ?? null;
}
