import crypto from "crypto";
import { getDb, getUserByOpenId, upsertUser } from "../db.ts";
import { eq } from "drizzle-orm";

/**
 * Hash a password using PBKDF2
 */
export async function hashPassword(password: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const salt = crypto.randomBytes(16).toString("hex");
    crypto.pbkdf2(password, salt, 100000, 64, "sha512", (err, derivedKey) => {
      if (err) reject(err);
      const hash = derivedKey.toString("hex");
      resolve(`${salt}:${hash}`);
    });
  });
}

/**
 * Verify a password against a hash
 */
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return new Promise((resolve, reject) => {
    const [salt, key] = hash.split(":");
    crypto.pbkdf2(password, salt, 100000, 64, "sha512", (err, derivedKey) => {
      if (err) reject(err);
      resolve(key === derivedKey.toString("hex"));
    });
  });
}

/**
 * Register a new user with email and password
 */
export async function registerUser(email: string, password: string, name: string) {
  // Check if user already exists
  const existingUser = await getUserByOpenId(`email_${email}`);
  if (existingUser) {
    throw new Error("User with this email already exists");
  }

  // Hash password
  const passwordHash = await hashPassword(password);

  // Create user
  const user = await upsertUser({
    openId: `email_${email}`,
    email,
    name,
    loginMethod: "email",
    passwordHash,
    lastSignedIn: new Date(),
  });

  return user;
}

/**
 * Authenticate user with email and password
 */
export async function authenticateUser(email: string, password: string) {
  const user = await getUserByOpenId(`email_${email}`);
  
  if (!user) {
    throw new Error("Invalid email or password");
  }

  // Check if user has password hash (email login enabled)
  if (!user.passwordHash) {
    throw new Error("This account uses OAuth login. Please use Manus OAuth to sign in.");
  }

  // Verify password
  const isValid = await verifyPassword(password, user.passwordHash);
  if (!isValid) {
    throw new Error("Invalid email or password");
  }

  // Update last signed in
  const updatedUser = await upsertUser({
    openId: `email_${email}`,
    lastSignedIn: new Date(),
  });

  return updatedUser;
}

/**
 * Generate password reset token
 */
export async function generatePasswordResetToken(email: string): Promise<string> {
  const user = await getUserByOpenId(`email_${email}`);
  if (!user) {
    throw new Error("User not found");
  }

  // Generate token
  const token = crypto.randomBytes(32).toString("hex");
  const expiresAt = new Date(Date.now() + 1 * 60 * 60 * 1000); // 1 hour

  // Store token in database
  const db = await getDb();
  if (!db) throw new Error("Database not available");

  // We'll use a simple approach: store in a password_reset_tokens table
  // For now, return token (in production, send via email)
  return token;
}

/**
 * Reset password with token
 */
export async function resetPassword(email: string, newPassword: string): Promise<void> {
  const user = await getUserByOpenId(`email_${email}`);
  if (!user) {
    throw new Error("User not found");
  }

  // Hash new password
  const passwordHash = await hashPassword(newPassword);

  // Update user
  await upsertUser({
    openId: `email_${email}`,
    passwordHash,
  });
}
