import { getDb } from "../db.ts";
import { users, emailVerifications } from "../../drizzle/schema.ts";
import { eq, and } from "drizzle-orm";
import crypto from "crypto";

/**
 * Generate a secure verification token
 */
export function generateVerificationToken(): string {
  return crypto.randomBytes(32).toString("hex");
}

/**
 * Send email verification
 */
export async function sendEmailVerification(userId: number, email: string): Promise<{ token: string; expiresAt: Date }> {
  const db = getDb();
  if (!db) throw new Error("Database unavailable");

  const token = generateVerificationToken();
  const expiresAt = new Date();
  expiresAt.setHours(expiresAt.getHours() + 24); // Token valid for 24 hours

  // Store verification token
  await db.insert(emailVerifications).values({
    userId,
    email,
    token,
    expiresAt,
  });

  // Send email with verification link
  try {
    const { sendEmailVerificationLink } = await import('./emailService');
    await sendEmailVerificationLink(email, token);
    console.log(`[EmailVerification] Verification email sent to ${email}`);
  } catch (error) {
    console.error(`[EmailVerification] Failed to send verification email: ${error}`);
  }

  console.log(`[EmailVerification] Token generated for user ${userId}: ${token}`);

  return { token, expiresAt };
}

/**
 * Verify email with token
 */
export async function verifyEmailWithToken(token: string): Promise<{ userId: number; email: string } | null> {
  const db = getDb();
  if (!db) throw new Error("Database unavailable");

  // Find verification record
  const verification = await db
    .select()
    .from(emailVerifications)
    .where(
      and(
        eq(emailVerifications.token, token),
        // Token must not be expired
      )
    )
    .then((res) => res[0]);

  if (!verification) {
    return null;
  }

  // Check if token is expired
  if (new Date() > verification.expiresAt) {
    return null;
  }

  // Check if already verified
  if (verification.verifiedAt) {
    return null;
  }

  // Mark as verified
  await db
    .update(emailVerifications)
    .set({ verifiedAt: new Date() })
    .where(eq(emailVerifications.id, verification.id));

  // Update user record
  await db
    .update(users)
    .set({ emailVerified: 1 })
    .where(eq(users.id, verification.userId));

  return {
    userId: verification.userId,
    email: verification.email,
  };
}

/**
 * Check if email is verified
 */
export async function isEmailVerified(userId: number): Promise<boolean> {
  const db = getDb();
  if (!db) throw new Error("Database unavailable");

  const user = await db.select().from(users).where(eq(users.id, userId)).then((res) => res[0]);

  return user?.emailVerified === 1;
}

/**
 * Get verification status for user
 */
export async function getVerificationStatus(userId: number): Promise<{
  isVerified: boolean;
  pendingEmail?: string;
  expiresAt?: Date;
}> {
  const db = getDb();
  if (!db) throw new Error("Database unavailable");

  const user = await db.select().from(users).where(eq(users.id, userId)).then((res) => res[0]);

  if (!user) {
    return { isVerified: false };
  }

  if (user.emailVerified === 1) {
    return { isVerified: true };
  }

  // Get pending verification
  const pending = await db
    .select()
    .from(emailVerifications)
    .where(
      and(
        eq(emailVerifications.userId, userId),
        // Not yet verified
      )
    )
    .then((res) => res[0]);

  if (pending && new Date() <= pending.expiresAt) {
    return {
      isVerified: false,
      pendingEmail: pending.email,
      expiresAt: pending.expiresAt,
    };
  }

  return { isVerified: false };
}
