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

interface MagicLinkToken {
  token: string;
  email: string;
  expiresAt: number;
  userId?: number;
}

// In-memory store for magic link tokens (in production, use database)
const magicLinkTokens = new Map<string, MagicLinkToken>();

export class MagicLinkAuthService {
  /**
   * Generate a magic link token
   */
  static generateToken(email: string, userId?: number): string {
    const token = crypto.randomBytes(32).toString("hex");
    const expiresAt = Date.now() + 15 * 60 * 1000; // 15 minutes

    magicLinkTokens.set(token, {
      token,
      email,
      expiresAt,
      userId,
    });

    return token;
  }

  /**
   * Verify a magic link token
   */
  static verifyToken(token: string): MagicLinkToken | null {
    const magicLink = magicLinkTokens.get(token);

    if (!magicLink) {
      return null;
    }

    // Check if token has expired
    if (Date.now() > magicLink.expiresAt) {
      magicLinkTokens.delete(token);
      return null;
    }

    return magicLink;
  }

  /**
   * Send magic link email (placeholder)
   */
  static async sendMagicLink(email: string, token: string, origin: string) {
    const magicLink = `${origin}/auth/magic-link/verify?token=${token}`;

    // In production, integrate with SendGrid, Mailgun, or similar
    console.log(`[Magic Link] Sending to ${email}: ${magicLink}`);

    // Placeholder email sending
    const emailContent = `
      <h1>Sign in to CoinKrazy</h1>
      <p>Click the link below to sign in without a password:</p>
      <a href="${magicLink}">Sign in to CoinKrazy</a>
      <p>This link expires in 15 minutes.</p>
      <p>If you didn't request this link, you can safely ignore this email.</p>
    `;

    return {
      success: true,
      messageId: crypto.randomBytes(16).toString("hex"),
      email,
      expiresAt: Date.now() + 15 * 60 * 1000,
    };
  }

  /**
   * Authenticate user with magic link
   */
  static async authenticateWithMagicLink(token: string) {
    const magicLink = this.verifyToken(token);

    if (!magicLink) {
      throw new Error("Invalid or expired magic link");
    }

    // Find or create user by email
    let user = await db.query.users.findFirst({
      where: eq(users.email, magicLink.email),
    });

    if (!user) {
      // In production, you might want to create a new user here
      throw new Error("User not found");
    }

    // Clean up used token
    magicLinkTokens.delete(token);

    return user;
  }

  /**
   * Clean up expired tokens (run periodically)
   */
  static cleanupExpiredTokens() {
    const now = Date.now();
    let cleaned = 0;

    for (const [token, magicLink] of magicLinkTokens.entries()) {
      if (now > magicLink.expiresAt) {
        magicLinkTokens.delete(token);
        cleaned++;
      }
    }

    console.log(`[Magic Link] Cleaned up ${cleaned} expired tokens`);
    return cleaned;
  }

  /**
   * Get token info (for debugging)
   */
  static getTokenInfo(token: string) {
    const magicLink = magicLinkTokens.get(token);
    if (!magicLink) return null;

    return {
      email: magicLink.email,
      expiresAt: new Date(magicLink.expiresAt).toISOString(),
      isExpired: Date.now() > magicLink.expiresAt,
    };
  }
}
