import crypto from "crypto";
import jwt from "jsonwebtoken";
import type { StringValue } from "ms";
import type { JwtAuthPayload } from "../@types/auth.js";

const OTP_LENGTH = 6;

export const OTP_EXPIRES_IN_MINUTES = Number(
  process.env.OTP_EXPIRES_IN_MINUTES || 10,
);
export const ACCESS_TOKEN_EXPIRES_IN = (process.env.ACCESS_TOKEN_EXPIRES_IN ||
  process.env.JWT_EXPIRES_IN ||
  "15m") as StringValue;
export const REFRESH_TOKEN_EXPIRES_IN_DAYS = Number(
  process.env.REFRESH_TOKEN_EXPIRES_IN_DAYS || 30,
);

export const getJwtSecret = () => {
  const secret = process.env.JWT_SECRET;
  if (secret) return secret;

  if (process.env.NODE_ENV === "production") {
    throw new Error("JWT_SECRET is required in production.");
  }

  return "dev-only-change-this-jwt-secret";
};

export const generateOtpCode = () => {
  const max = 10 ** OTP_LENGTH;
  return crypto.randomInt(0, max).toString().padStart(OTP_LENGTH, "0");
};

export const hashOtpCode = (code: string) => {
  return crypto.createHash("sha256").update(code).digest("hex");
};

export const generateRefreshToken = () =>
  crypto.randomBytes(64).toString("hex");

export const hashRefreshToken = (token: string) => {
  return crypto.createHash("sha256").update(token).digest("hex");
};

export const refreshTokenExpiryDate = () => {
  return new Date(
    Date.now() + REFRESH_TOKEN_EXPIRES_IN_DAYS * 24 * 60 * 60 * 1000,
  );
};

export const signAccessToken = (payload: JwtAuthPayload) => {
  return jwt.sign(payload, getJwtSecret(), {
    expiresIn: ACCESS_TOKEN_EXPIRES_IN,
  });
};

export const signAuthToken = signAccessToken;

export const verifyAuthToken = (token: string) => {
  return jwt.verify(token, getJwtSecret()) as JwtAuthPayload;
};

export const otpExpiryDate = () =>
  new Date(Date.now() + OTP_EXPIRES_IN_MINUTES * 60 * 1000);
