import { d as database, u as user, P as PAGINATION, t as token } from './constants_C_mAa7qs.mjs';
import { countDistinct, eq, sql } from 'drizzle-orm';
import { nanoid } from 'nanoid';
import { genSalt, hash, compare } from 'bcrypt';

const SALT_ROUND = Number(10);
const hashPassword = async (password) => {
  const salt = await genSalt(SALT_ROUND);
  return await hash(password, salt);
};
const verifyPassword = async ({
  password,
  hash: hash2
}) => {
  return await compare(password, hash2);
};
const validateCredentials = async ({
  email,
  password
}) => {
  const user2 = await getOneUserEmail(email);
  const match = user2?.password ? await verifyPassword({ password, hash: user2.password }) : void 0;
  if (!match) {
    return null;
  }
  return user2;
};
const newUser = async ({
  firstName,
  lastName,
  email,
  password,
  username
}) => {
  try {
    return await database.insert(user).values({
      lastName,
      firstName,
      email,
      password,
      username: username ?? firstName.trim().replace(" ", ".").toLowerCase()
    }).prepare().execute();
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};
const updateUser = async (data, id) => {
  try {
    return await database.update(user).set(data).where(eq(user.id, id)).prepare().execute();
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};
const changeUserPassword = async ({
  email,
  password
}) => {
  try {
    const hash2 = await hashPassword(password);
    return await database.update(user).set({ password: hash2 }).where(eq(user.email, email)).prepare().execute();
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};
const getAllUsers = async (page = 1) => {
  try {
    return await database.transaction(async (tx) => {
      const users = await tx.query.user.findMany({
        offset: (page - 1) * PAGINATION,
        limit: page * PAGINATION,
        orderBy: user.createdAt
      }).prepare().execute();
      const amount = await tx.select({ total: countDistinct(user.id) }).from(user).prepare().execute();
      const total = amount.map((e) => e.total).reduce((a, b) => a + b);
      return {
        total,
        users,
        page,
        total_pages: Math.ceil(total / PAGINATION)
      };
    });
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};
const getOneUser = async (id) => {
  try {
    return await database.query.user.findFirst({
      where: (user2, { eq: eq2 }) => eq2(user2.id, id)
    }).prepare().execute();
  } catch (error) {
    console.log(error);
    throw new Error("User was not found");
  }
};
const getOneUserEmail = async (email) => {
  try {
    return await database.query.user.findFirst({
      where: (user2, { eq: eq2 }) => eq2(user2.email, email)
    }).prepare().execute();
  } catch (error) {
    console.log(error);
    throw new Error("User was not found");
  }
};
const createToken = async (email) => {
  try {
    const now = /* @__PURE__ */ new Date();
    const rand = nanoid();
    const reset_token = `${rand}_${now.getTime().toString(16)}`;
    const expiredAt = new Date((/* @__PURE__ */ new Date()).setHours(now.getHours() + 2));
    const t = await database.transaction(async (tx) => {
      await tx.delete(token).where(eq(token.email, email)).prepare().execute();
      await tx.delete(token).where(sql`${token.expiredAt} < ${/* @__PURE__ */ new Date()}`).prepare().execute();
      const u = tx.query.user.findFirst({
        where: (user2, { eq: eq2 }) => eq2(user2.email, email)
      });
      if (!u) {
        throw new Error("User was not found");
      }
      await tx.insert(token).values({
        email,
        expiredAt,
        token: reset_token
      }).prepare().execute();
      return u;
    });
    return { token: reset_token, user: t };
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};
const getToken = async (reset_token) => {
  try {
    const t = await database.query.token.findFirst({
      where: (token2, { eq: eq2 }) => eq2(token2.token, reset_token)
    });
    return t;
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};
const verifyToken = async ({
  token: token2,
  email
}) => {
  try {
    const reset_token = await getToken(token2);
    const now = /* @__PURE__ */ new Date();
    if (!reset_token || reset_token.email !== email || reset_token.expiredAt === null || reset_token.expiredAt < now) {
      return false;
    }
    return true;
  } catch (error) {
    console.log(error);
    throw new Error(JSON.stringify(error, null, 2));
  }
};

export { verifyToken as a, changeUserPassword as b, createToken as c, getOneUser as d, getAllUsers as e, getOneUserEmail as g, hashPassword as h, newUser as n, updateUser as u, validateCredentials as v };
