import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { db } from '@/lib/db';
import { z } from 'zod';
import { Decimal } from '@prisma/client/runtime/library';

interface RouteContext {
  params: Promise<{ id: string; inscriptionId: string }>;
}

// Validation schema for updating an inscription
const updateInscriptionSchema = z.object({
  player1Id: z.string().cuid('Invalid player 1 ID').optional(),
  player2Id: z.string().cuid('Invalid player 2 ID').optional().nullable(),
  teamName: z.string().max(100).optional().nullable(),
  isPaid: z.boolean().optional(),
  paidAmount: z.number().nonnegative().optional(),
  seedNumber: z.number().int().positive().optional(),
  notes: z.string().max(500).optional().nullable(),
});

// PUT /api/tournaments/[id]/inscriptions/[inscriptionId] - Update inscription
export async function PUT(
  request: NextRequest,
  context: RouteContext
) {
  try {
    const session = await getServerSession(authOptions);

    if (!session?.user) {
      return NextResponse.json(
        { error: 'Unauthorized' },
        { status: 401 }
      );
    }

    const { id, inscriptionId } = await context.params;

    // Verify tournament exists and belongs to user's organization
    const tournament = await db.tournament.findFirst({
      where: {
        id,
        organizationId: session.user.organizationId,
      },
    });

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

    // Verify inscription exists
    const existingInscription = await db.tournamentInscription.findFirst({
      where: {
        id: inscriptionId,
        tournamentId: id,
      },
    });

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

    const body = await request.json();

    // Validate input
    const validationResult = updateInscriptionSchema.safeParse(body);
    if (!validationResult.success) {
      return NextResponse.json(
        {
          error: 'Invalid inscription data',
          details: validationResult.error.flatten().fieldErrors,
        },
        { status: 400 }
      );
    }

    const { player1Id, player2Id, teamName, isPaid, paidAmount, seedNumber, notes } = validationResult.data;

    // Build update data
    interface InscriptionUpdateData {
      clientId?: string;
      partnerId?: string | null;
      teamName?: string | null;
      isPaid?: boolean;
      paidAmount?: Decimal;
      seedNumber?: number;
      notes?: string | null;
    }

    const updateData: InscriptionUpdateData = {};

    // Validate player 1 if changing
    if (player1Id !== undefined && player1Id !== existingInscription.clientId) {
      const player1 = await db.client.findFirst({
        where: {
          id: player1Id,
          organizationId: session.user.organizationId,
        },
      });

      if (!player1) {
        return NextResponse.json(
          { error: 'Player 1 not found or does not belong to your organization' },
          { status: 404 }
        );
      }

      // Check player 1 is not already registered in another inscription
      const existingPlayer1 = await db.tournamentInscription.findFirst({
        where: {
          tournamentId: id,
          id: { not: inscriptionId },
          OR: [
            { clientId: player1Id },
            { partnerId: player1Id },
          ],
        },
      });

      if (existingPlayer1) {
        return NextResponse.json(
          { error: 'Player 1 is already registered in another team' },
          { status: 400 }
        );
      }

      updateData.clientId = player1Id;
    }

    // Validate player 2 if changing
    if (player2Id !== undefined) {
      if (player2Id === null) {
        updateData.partnerId = null;
      } else if (player2Id !== existingInscription.partnerId) {
        const player2 = await db.client.findFirst({
          where: {
            id: player2Id,
            organizationId: session.user.organizationId,
          },
        });

        if (!player2) {
          return NextResponse.json(
            { error: 'Player 2 not found or does not belong to your organization' },
            { status: 404 }
          );
        }

        // Check player 2 is not already registered in another inscription
        const existingPlayer2 = await db.tournamentInscription.findFirst({
          where: {
            tournamentId: id,
            id: { not: inscriptionId },
            OR: [
              { clientId: player2Id },
              { partnerId: player2Id },
            ],
          },
        });

        if (existingPlayer2) {
          return NextResponse.json(
            { error: 'Player 2 is already registered in another team' },
            { status: 400 }
          );
        }

        updateData.partnerId = player2Id;
      }
    }

    if (teamName !== undefined) updateData.teamName = teamName;
    if (isPaid !== undefined) updateData.isPaid = isPaid;
    if (paidAmount !== undefined) updateData.paidAmount = new Decimal(paidAmount);
    if (seedNumber !== undefined) updateData.seedNumber = seedNumber;
    if (notes !== undefined) updateData.notes = notes;

    const inscription = await db.tournamentInscription.update({
      where: { id: inscriptionId },
      data: updateData,
      include: {
        client: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
            email: true,
            phone: true,
            level: true,
          },
        },
      },
    });

    // Get partner info if exists
    let partner = null;
    if (inscription.partnerId) {
      partner = await db.client.findUnique({
        where: { id: inscription.partnerId },
        select: {
          id: true,
          firstName: true,
          lastName: true,
          email: true,
          phone: true,
          level: true,
        },
      });
    }

    return NextResponse.json({
      ...inscription,
      partner,
    });
  } catch (error) {
    console.error('Error updating inscription:', error);
    return NextResponse.json(
      { error: 'Failed to update inscription' },
      { status: 500 }
    );
  }
}

// DELETE /api/tournaments/[id]/inscriptions/[inscriptionId] - Remove inscription
export async function DELETE(
  request: NextRequest,
  context: RouteContext
) {
  try {
    const session = await getServerSession(authOptions);

    if (!session?.user) {
      return NextResponse.json(
        { error: 'Unauthorized' },
        { status: 401 }
      );
    }

    const { id, inscriptionId } = await context.params;

    // Verify tournament exists and belongs to user's organization
    const tournament = await db.tournament.findFirst({
      where: {
        id,
        organizationId: session.user.organizationId,
      },
    });

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

    // Only allow removing inscriptions if tournament is still in registration phase
    if (!['DRAFT', 'REGISTRATION_OPEN'].includes(tournament.status)) {
      return NextResponse.json(
        { error: 'Cannot remove inscriptions after tournament has started' },
        { status: 400 }
      );
    }

    // Verify inscription exists
    const existingInscription = await db.tournamentInscription.findFirst({
      where: {
        id: inscriptionId,
        tournamentId: id,
      },
    });

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

    // Delete inscription
    await db.tournamentInscription.delete({
      where: { id: inscriptionId },
    });

    return NextResponse.json({
      message: 'Inscription removed successfully',
    });
  } catch (error) {
    console.error('Error removing inscription:', error);
    return NextResponse.json(
      { error: 'Failed to remove inscription' },
      { status: 500 }
    );
  }
}
