import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/lib/db';
import { eq } from 'drizzle-orm';
import { verifyRefreshToken, rotateRefreshToken, generateAccessToken } from '@/lib/tokens';
import { rateLimit } from '@/lib/rate-limit';
import { ACCESS_TOKEN_MAX_AGE_SECONDS, REFRESH_TOKEN_MAX_AGE_SECONDS } from '@/lib/constants';

export async function POST(request: NextRequest) {
  try {
    // Rate limit: 10 refresh attempts per minute per IP
    const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown';
    const rl = rateLimit(`refresh:${ip}`, { limit: 10, windowSeconds: 60 });
    if (!rl.allowed) {
      return NextResponse.json(
        { error: 'Troppi tentativi. Riprova tra un minuto.' },
        { status: 429, headers: { 'Retry-After': String(Math.ceil((rl.resetAt - Date.now()) / 1000)) } }
      );
    }

    const refreshToken = request.cookies.get('scriba.refresh_token')?.value;
    if (!refreshToken) {
      return NextResponse.json({ error: 'Refresh token mancante' }, { status: 401 });
    }

    // Verify the refresh token
    const tokenData = await verifyRefreshToken(refreshToken);
    if (!tokenData) {
      // Clear invalid refresh token cookie
      const response = NextResponse.json({ error: 'Refresh token non valido' }, { status: 401 });
      response.cookies.set('scriba.refresh_token', '', {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/',
        maxAge: 0,
      });
      response.cookies.set('scriba.access_token', '', {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/',
        maxAge: 0,
      });
      return response;
    }

    // Get user information
    const user = await db.query.users.findFirst({
      where: eq(schema.users.id, tokenData.userId)
    });

    if (!user) {
      return NextResponse.json({ error: 'Utente non trovato' }, { status: 401 });
    }

    // Rotate the refresh token (create new one, revoke old)
    const rotationResult = await rotateRefreshToken(
      tokenData.sessionId,
      request.headers.get('x-forwarded-for') || undefined,
      request.headers.get('user-agent') || undefined
    );

    if (!rotationResult) {
      return NextResponse.json({ error: 'Impossibile ruotare il refresh token' }, { status: 401 });
    }

    // Generate new access token
    const newAccessToken = generateAccessToken({
      userId: user.id,
      email: user.email,
      role: user.role,
      sessionId: rotationResult.sessionId,
    });

    // Set new cookies
    const response = NextResponse.json({
      success: true,
      user: { id: user.id, email: user.email, name: user.name, role: user.role }
    });

    // New access token cookie
    response.cookies.set('scriba.access_token', newAccessToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: ACCESS_TOKEN_MAX_AGE_SECONDS,
    });

    // New refresh token cookie
    response.cookies.set('scriba.refresh_token', rotationResult.refreshToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: REFRESH_TOKEN_MAX_AGE_SECONDS,
    });

    return response;
  } catch (error) {
    console.error('Token refresh error:', error);
    return NextResponse.json({ error: 'Refresh token fallito' }, { status: 500 });
  }
}
