import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { isValidEmail, sanitizeString } from '@/lib/validation';
import { checkRateLimit, getRateLimitIdentifier, rateLimitError, RATE_LIMITS } from '@/lib/rate-limit';
import { sendVerificationCodeEmail, isSmtpConfigured } from '@/lib/email';

// Simple hash function consistent with the app
function hashPassword(password: string): string {
  return Buffer.from(password).toString('base64');
}

export async function POST(request: NextRequest) {
  try {
    // Rate limit
    const identifier = `forgot-pw:${getRateLimitIdentifier(request)}`;
    const rateLimit = checkRateLimit(identifier, RATE_LIMITS.auth);
    if (!rateLimit.allowed) {
      return rateLimitError(rateLimit.resetTime);
    }

    const body = await request.json();
    const { email } = body;

    if (!email || !isValidEmail(email)) {
      return NextResponse.json(
        { error: 'Valid email is required' },
        { status: 400 }
      );
    }

    const sanitizedEmail = sanitizeString(email);

    // Check if user exists
    const user = await db.user.findUnique({ where: { email: sanitizedEmail } });
    if (!user) {
      // Don't reveal whether user exists - still return success
      return NextResponse.json(
        { message: 'If an account with this email exists, a verification code has been sent' },
        { status: 200 }
      );
    }

    // Delete any existing unused codes for this email
    await db.verificationCode.deleteMany({
      where: { email: sanitizedEmail, isUsed: false, type: 'password_reset' },
    });

    // Generate 6-digit code
    const code = String(Math.floor(100000 + Math.random() * 900000));
    const expiresAt = new Date(Date.now() + 10 * 60 * 1000); // 10 minutes

    // Store code in database
    await db.verificationCode.create({
      data: {
        email: sanitizedEmail,
        code,
        type: 'password_reset',
        expiresAt,
      },
    });

    // Send verification code via email
    const emailResult = await sendVerificationCodeEmail(sanitizedEmail, code);

    if (!emailResult.success) {
      console.error('Failed to send verification email:', emailResult.error);
      // Still return success to not reveal email sending issues
      // But include the code in dev mode for testing
    }

    // In development mode (SMTP not configured), return the code in response
    // so the user can still test the flow. In production, code is NOT returned.
    const smtpReady = isSmtpConfigured();

    return NextResponse.json(
      {
        message: smtpReady
          ? 'Verification code sent to your email'
          : 'Verification code generated (SMTP not configured - check server console)',
        // Only include code in response when SMTP is NOT configured (dev mode)
        ...(smtpReady ? {} : { code }),
        dev: !smtpReady,
      },
      { status: 200 }
    );
  } catch (error) {
    console.error('Forgot password error:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

// PUT: Verify code only (does NOT reset password)
export async function PUT(request: NextRequest) {
  try {
    const body = await request.json();
    const { email, code } = body;

    if (!email || !code) {
      return NextResponse.json(
        { error: 'Email and verification code are required' },
        { status: 400 }
      );
    }

    if (!isValidEmail(email)) {
      return NextResponse.json(
        { error: 'Invalid email format' },
        { status: 400 }
      );
    }

    const sanitizedEmail = sanitizeString(email);

    // Verify code from database
    const storedCode = await db.verificationCode.findFirst({
      where: {
        email: sanitizedEmail,
        code,
        type: 'password_reset',
        isUsed: false,
      },
      orderBy: { createdAt: 'desc' },
    });

    if (!storedCode) {
      return NextResponse.json(
        { error: 'Invalid verification code. Please request a new one.' },
        { status: 400 }
      );
    }

    if (new Date() > storedCode.expiresAt) {
      // Delete expired code
      await db.verificationCode.delete({ where: { id: storedCode.id } });
      return NextResponse.json(
        { error: 'Verification code has expired. Please request a new one.' },
        { status: 400 }
      );
    }

    // Code is valid — return success without marking as used
    // The code will be marked as used when the password is actually reset (PATCH)
    return NextResponse.json(
      { message: 'Verification code is valid' },
      { status: 200 }
    );
  } catch (error) {
    console.error('Verify code error:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

export async function PATCH(request: NextRequest) {
  try {
    // Rate limit
    const identifier = `reset-pw:${getRateLimitIdentifier(request)}`;
    const rateLimit = checkRateLimit(identifier, RATE_LIMITS.auth);
    if (!rateLimit.allowed) {
      return rateLimitError(rateLimit.resetTime);
    }

    const body = await request.json();
    const { email, code, newPassword } = body;

    if (!email || !code || !newPassword) {
      return NextResponse.json(
        { error: 'Email, verification code, and new password are required' },
        { status: 400 }
      );
    }

    if (!isValidEmail(email)) {
      return NextResponse.json(
        { error: 'Invalid email format' },
        { status: 400 }
      );
    }

    if (newPassword.length < 6) {
      return NextResponse.json(
        { error: 'Password must be at least 6 characters' },
        { status: 400 }
      );
    }

    const sanitizedEmail = sanitizeString(email);

    // Verify code from database
    const storedCode = await db.verificationCode.findFirst({
      where: {
        email: sanitizedEmail,
        code,
        type: 'password_reset',
        isUsed: false,
      },
      orderBy: { createdAt: 'desc' },
    });

    if (!storedCode) {
      return NextResponse.json(
        { error: 'Invalid verification code. Please request a new one.' },
        { status: 400 }
      );
    }

    if (new Date() > storedCode.expiresAt) {
      // Delete expired code
      await db.verificationCode.delete({ where: { id: storedCode.id } });
      return NextResponse.json(
        { error: 'Verification code has expired. Please request a new one.' },
        { status: 400 }
      );
    }

    // Update password
    const hashedPassword = hashPassword(newPassword);
    await db.user.update({
      where: { email: sanitizedEmail },
      data: { password: hashedPassword },
    });

    // Mark code as used
    await db.verificationCode.update({
      where: { id: storedCode.id },
      data: { isUsed: true },
    });

    // Also clean up any other unused codes for this email
    await db.verificationCode.deleteMany({
      where: { email: sanitizedEmail, isUsed: false, type: 'password_reset' },
    });

    return NextResponse.json(
      { message: 'Password reset successfully' },
      { status: 200 }
    );
  } catch (error) {
    console.error('Reset password error:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}
