import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import NotificationService from '@/lib/notifications';

export async function POST(
  req: NextRequest,
  { params }: { params: Promise<{ projectId: string; bidId: string }> }
) {
  try {
    const { projectId, bidId } = await params;
    
    // Get session to verify access
    const session = await getServerSession(authOptions);
    if (!session) {
      return NextResponse.json(
        { error: 'Unauthorized' },
        { status: 401 }
      );
    }

    if (!projectId || !bidId) {
      return NextResponse.json(
        { error: 'Project ID and Bid ID are required' },
        { status: 400 }
      );
    }

    // Verify the project exists and user has access (is the client)
    const project = await prisma.project.findUnique({
      where: { id: projectId },
      select: {
        id: true,
        clientId: true,
        status: true
      }
    });

    if (!project) {
      return NextResponse.json(
        { error: 'Project not found' },
        { status: 404 }
      );
    }

    // Check if current user is the client of this project
    if (project.clientId !== session.user?.id) {
      return NextResponse.json(
        { error: 'Access denied. Only the project client can accept bids.' },
        { status: 403 }
      );
    }

    // Check if project is still open for bids
    if (project.status !== 'OPEN') {
      return NextResponse.json(
        { error: 'This project is no longer accepting bids.' },
        { status: 400 }
      );
    }

    // Verify the bid exists and belongs to this project
    const bid = await prisma.bid.findUnique({
      where: { id: bidId },
      select: {
        id: true,
        projectId: true,
        freelancerId: true,
        status: true
      }
    });

    if (!bid || bid.projectId !== projectId) {
      return NextResponse.json(
        { error: 'Bid not found' },
        { status: 404 }
      );
    }

    // Check if bid is still pending
    if (bid.status !== 'PENDING') {
      return NextResponse.json(
        { error: 'This bid has already been processed.' },
        { status: 400 }
      );
    }

    // Use transaction to ensure data consistency
    const result = await prisma.$transaction(async (tx) => {
      // Accept the selected bid
      const acceptedBid = await tx.bid.update({
        where: { id: bidId },
        data: { status: 'ACCEPTED' }
      });

      // Reject all other pending bids for this project
      await tx.bid.updateMany({
        where: {
          projectId: projectId,
          id: { not: bidId },
          status: 'PENDING'
        },
        data: { status: 'REJECTED' }
      });

      // Update project status to IN_PROGRESS and set selected bid
      await tx.project.update({
        where: { id: projectId },
        data: {
          status: 'IN_PROGRESS',
          selectedBidId: bidId
        }
      });

      // Enhanced notification will be sent after transaction completes
      // to avoid potential transaction conflicts

      // Get project details for the message
      const projectDetails = await tx.project.findUnique({
        where: { id: projectId },
        select: {
          title: true,
          clientId: true
        }
      });

      // Create a system message in the conversation between client and accepted freelancer
      await tx.message.create({
        data: {
          content: `🎉 Congratulations! Your bid has been accepted for the project "${projectDetails?.title}". The project is now in progress. You can start working and communicate with the client through this chat.`,
          senderId: projectDetails?.clientId || '',
          receiverId: bid.freelancerId,
          projectId: projectId,
          bidId: bidId,
          messageType: 'system',
          isRead: false
        }
      });

      // Get all other freelancers who had pending bids to create rejection messages
      const otherBids = await tx.bid.findMany({
        where: {
          projectId: projectId,
          id: { not: bidId },
          status: 'PENDING'
        },
        select: {
          freelancerId: true,
          id: true
        }
      });

      // Create system messages for rejected freelancers
      for (const otherBid of otherBids) {
        await tx.message.create({
          data: {
            content: `Thank you for your interest in the project "${projectDetails?.title}". Unfortunately, another freelancer has been selected for this project. We encourage you to apply for other projects that match your skills.`,
            senderId: projectDetails?.clientId || '',
            receiverId: otherBid.freelancerId,
            projectId: projectId,
            bidId: otherBid.id,
            messageType: 'system',
            isRead: false
          }
        });
      }

      return acceptedBid;
    });

    // Send enhanced notification to accepted freelancer
    const projectDetails = await prisma.project.findUnique({
      where: { id: projectId },
      select: {
        title: true,
        budget: true,
        client: {
          select: {
            profile: {
              select: {
                firstName: true,
                lastName: true
              }
            }
          }
        }
      }
    });

    const bidDetails = await prisma.bid.findUnique({
      where: { id: bidId },
      select: {
        amount: true,
        freelancerId: true
      }
    });

    if (projectDetails && bidDetails) {
      const clientName = projectDetails.client?.profile ? 
        `${projectDetails.client.profile.firstName} ${projectDetails.client.profile.lastName}`.trim() : 
        session.user?.name || 'Client';
        
      try {
        await NotificationService.notifyBidAccepted(
          bidDetails.freelancerId,
          clientName,
          projectDetails.title,
          projectId,
          bidDetails.amount,
          'EUR' // Default currency - could be made dynamic based on country
        );
      } catch (notificationError) {
        console.error('Failed to create bid acceptance notification:', notificationError);
      }
    }

    // Send notifications to rejected freelancers
    const rejectedBids = await prisma.bid.findMany({
      where: {
        projectId: projectId,
        id: { not: bidId },
        status: 'REJECTED'
      },
      select: {
        freelancerId: true,
        id: true
      }
    });

    if (projectDetails && rejectedBids.length > 0) {
      const clientName = projectDetails.client?.profile ? 
        `${projectDetails.client.profile.firstName} ${projectDetails.client.profile.lastName}`.trim() : 
        session.user?.name || 'Client';
        
      for (const rejectedBid of rejectedBids) {
        try {
          await NotificationService.notifyBidRejected(
            rejectedBid.freelancerId,
            clientName,
            projectDetails.title,
            projectId
          );
        } catch (notificationError) {
          console.error(`Failed to create bid rejection notification for freelancer ${rejectedBid.freelancerId}:`, notificationError);
        }
      }
    }

    // Get updated bid details with freelancer info for response
    const updatedBid = await prisma.bid.findUnique({
      where: { id: bidId },
      include: {
        freelancer: {
          select: {
            id: true,
            email: true,
            profile: {
              select: {
                firstName: true,
                lastName: true
              }
            }
          }
        },
        project: {
          select: {
            title: true,
            status: true
          }
        }
      }
    });

    return NextResponse.json({
      success: true,
      message: 'Bid accepted successfully',
      data: {
        bid: updatedBid,
        projectStatus: 'IN_PROGRESS',
        rejectedBidsCount: await prisma.bid.count({
          where: {
            projectId: projectId,
            status: 'REJECTED'
          }
        })
      }
    });

  } catch (error) {
    console.error('Error accepting bid:', error);
    
    let errorMessage = 'An unexpected error occurred while accepting the bid.';
    let details = 'Unknown error';
    
    if (error instanceof Error) {
      details = error.message;
      
      if (error.message.includes('connect') || error.message.includes('ECONNREFUSED')) {
        errorMessage = 'Database connection failed. Please contact support if this persists.';
      } else if (error.message.includes('not found') || error.message.includes('P2025')) {
        errorMessage = 'The requested bid or project was not found.';
      } else if (error.message.includes('timeout')) {
        errorMessage = 'Request timed out. Please try again.';
      }
    }
    
    return NextResponse.json(
      { 
        error: errorMessage,
        details: details
      },
      { status: 500 }
    );
  }
}