// app/api/push-tokens/update/route.ts
import { NextRequest, NextResponse } from 'next/server';
import pool from '../../../../lib/db/db';
import { ResultSetHeader, RowDataPacket } from 'mysql2';
import { verifyAuthentication } from '../../../utils/verifyAuthentication';

interface TokenInterface {
  id: number;
  userId?: number;
  email?: string;
  role?: string;
}

export async function OPTIONS() {
  return NextResponse.json({}, { status: 200 });
}

export async function PUT(request: NextRequest) {
  const connection = await pool.getConnection();
  
  try {
    // ============ VALIDATION FOR UNAUTHENTICATED ACCESS ============
    const authHeader = request.headers.get('authorization');
    let isAuthenticated = false;
    let authenticatedUserId: number | null = null;
    
    if (authHeader && authHeader.startsWith('Bearer ')) {
      const token = authHeader.substring(7);
      const authResult = await verifyAuthentication(token);
      
      if (!(authResult instanceof NextResponse)) {
        const decoded = authResult as TokenInterface;
        if (decoded && decoded.id) {
          authenticatedUserId = decoded.id;
          isAuthenticated = true;
        }
      }
    } else if (authHeader !== process.env.APP_API_KEY) {
      return NextResponse.json({
        success: false,
        message: "Unauthorized Access"
      }, { status: 401 });
    }

    const body = await request.json();
    const { oldToken, newToken, tokenType } = body;

    if (!oldToken || !newToken) {
      return NextResponse.json({
        success: false,
        message: "Both old and new tokens are required"
      }, { status: 400 });
    }

    await connection.beginTransaction();

    let updateResult: ResultSetHeader;

    if (isAuthenticated && authenticatedUserId) {
      // Update by user ID and old token
      if (tokenType === 'expo') {
        [updateResult] = await connection.query<ResultSetHeader>(
          `UPDATE push_tokens 
           SET expo_push_token = ?, updated_at = ?
           WHERE user_id = ? AND expo_push_token = ?`,
          [newToken, new Date(), authenticatedUserId, oldToken]
        );
      } else {
        [updateResult] = await connection.query<ResultSetHeader>(
          `UPDATE push_tokens 
           SET firebase_token = ?, updated_at = ?
           WHERE user_id = ? AND firebase_token = ?`,
          [newToken, new Date(), authenticatedUserId, oldToken]
        );
      }
    } else {
      // Update by old token only (for guest users)
      if (tokenType === 'expo') {
        [updateResult] = await connection.query<ResultSetHeader>(
          `UPDATE push_tokens 
           SET expo_push_token = ?, updated_at = ?
           WHERE expo_push_token = ? AND user_id IS NULL`,
          [newToken, new Date(), oldToken]
        );
      } else {
        [updateResult] = await connection.query<ResultSetHeader>(
          `UPDATE push_tokens 
           SET firebase_token = ?, updated_at = ?
           WHERE firebase_token = ? AND user_id IS NULL`,
          [newToken, new Date(), oldToken]
        );
      }
    }

    if (updateResult.affectedRows === 0) {
      await connection.rollback();
      return NextResponse.json({
        success: false,
        message: "Token not found or already updated"
      }, { status: 404 });
    }

    await connection.commit();

    return NextResponse.json({
      success: true,
      message: "Push token updated successfully",
      data: {
        affectedRows: updateResult.affectedRows
      }
    }, { status: 200 });

  } catch (err: any) {
    try {
      await connection.rollback();
    } catch (rollbackErr) {
      console.error("Rollback failed:", rollbackErr);
    }

    console.error("Update push token error:", err);
    return NextResponse.json({
      success: false,
      message: "Internal server error",
      error: err.message
    }, { status: 500 });
  } finally {
    connection.release();
  }
}