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';
import { Prisma } from '@prisma/client';

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

// Validation schema for updating a tournament
const updateTournamentSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  description: z.string().max(500).optional().nullable(),
  date: z.string().datetime().optional(),
  endDate: z.string().datetime().optional().nullable(),
  type: z.enum(['SINGLE_ELIMINATION', 'DOUBLE_ELIMINATION', 'ROUND_ROBIN', 'LEAGUE']).optional(),
  category: z.string().max(50).optional().nullable(),
  maxTeams: z.number().int().min(2).optional(),
  price: z.number().nonnegative().optional(),
  status: z.enum(['DRAFT', 'REGISTRATION_OPEN', 'REGISTRATION_CLOSED', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED']).optional(),
  rules: z.string().max(2000).optional().nullable(),
  isPublic: z.boolean().optional(),
});

// Map API types to database types
function mapTournamentType(type: string): 'AMERICANO' | 'MEXICANO' | 'BRACKET' | 'ROUND_ROBIN' | 'LEAGUE' {
  const mapping: Record<string, 'AMERICANO' | 'MEXICANO' | 'BRACKET' | 'ROUND_ROBIN' | 'LEAGUE'> = {
    'SINGLE_ELIMINATION': 'BRACKET',
    'DOUBLE_ELIMINATION': 'BRACKET',
    'ROUND_ROBIN': 'ROUND_ROBIN',
    'LEAGUE': 'LEAGUE',
  };
  return mapping[type] || 'BRACKET';
}

// GET /api/tournaments/[id] - Get tournament with inscriptions count and matches
export async function GET(
  request: NextRequest,
  context: RouteContext
) {
  try {
    const session = await getServerSession(authOptions);

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

    const { id } = await context.params;

    const tournament = await db.tournament.findFirst({
      where: {
        id,
        organizationId: session.user.organizationId,
      },
      include: {
        site: {
          select: {
            id: true,
            name: true,
            slug: true,
            address: true,
            phone: true,
            email: true,
          },
        },
        inscriptions: {
          include: {
            client: {
              select: {
                id: true,
                firstName: true,
                lastName: true,
                email: true,
                phone: true,
                level: true,
              },
            },
          },
          orderBy: {
            registeredAt: 'asc',
          },
        },
        matches: {
          include: {
            court: {
              select: {
                id: true,
                name: true,
              },
            },
          },
          orderBy: [
            { round: 'asc' },
            { position: 'asc' },
          ],
        },
        _count: {
          select: {
            inscriptions: true,
            matches: true,
          },
        },
      },
    });

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

    return NextResponse.json(tournament);
  } catch (error) {
    console.error('Error fetching tournament:', error);
    return NextResponse.json(
      { error: 'Failed to fetch tournament' },
      { status: 500 }
    );
  }
}

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

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

    // Check if user has admin role
    const allowedRoles = ['SUPER_ADMIN', 'ORG_ADMIN', 'SITE_ADMIN'];
    if (!allowedRoles.includes(session.user.role)) {
      return NextResponse.json(
        { error: 'Forbidden: Insufficient permissions' },
        { status: 403 }
      );
    }

    const { id } = await context.params;

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

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

    // If user is SITE_ADMIN, verify they have access to this site
    if (session.user.role === 'SITE_ADMIN' && existingTournament.siteId && session.user.siteId !== existingTournament.siteId) {
      return NextResponse.json(
        { error: 'Forbidden: You do not have access to this tournament' },
        { status: 403 }
      );
    }

    const body = await request.json();

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

    const { name, description, date, endDate, type, category, maxTeams, price, status, rules, isPublic } = validationResult.data;

    // Build update data
    const updateData: Prisma.TournamentUpdateInput = {};

    if (name !== undefined) updateData.name = name;
    if (description !== undefined) updateData.description = description;
    if (date !== undefined) updateData.startDate = new Date(date);
    if (endDate !== undefined) updateData.endDate = endDate ? new Date(endDate) : null;

    // Build settings update
    let newSettings = existingTournament.settings as Prisma.JsonObject | null;

    if (type !== undefined) {
      updateData.type = mapTournamentType(type);
      // Also update settings with the format
      newSettings = {
        ...(newSettings || {}),
        tournamentFormat: type,
      };
    }
    if (category !== undefined) {
      newSettings = {
        ...(newSettings || {}),
        category,
      };
    }

    if (newSettings && (type !== undefined || category !== undefined)) {
      updateData.settings = newSettings;
    }

    if (maxTeams !== undefined) updateData.maxPlayers = maxTeams;
    if (price !== undefined) updateData.entryFee = new Decimal(price);
    if (status !== undefined) updateData.status = status;
    if (rules !== undefined) updateData.rules = rules;
    if (isPublic !== undefined) updateData.isPublic = isPublic;

    const tournament = await db.tournament.update({
      where: { id },
      data: updateData,
      include: {
        site: {
          select: {
            id: true,
            name: true,
            slug: true,
          },
        },
        _count: {
          select: {
            inscriptions: true,
            matches: true,
          },
        },
      },
    });

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

// DELETE /api/tournaments/[id] - Delete tournament (only if DRAFT status)
export async function DELETE(
  request: NextRequest,
  context: RouteContext
) {
  try {
    const session = await getServerSession(authOptions);

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

    // Check if user has admin role
    const allowedRoles = ['SUPER_ADMIN', 'ORG_ADMIN', 'SITE_ADMIN'];
    if (!allowedRoles.includes(session.user.role)) {
      return NextResponse.json(
        { error: 'Forbidden: Insufficient permissions' },
        { status: 403 }
      );
    }

    const { id } = await context.params;

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

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

    // If user is SITE_ADMIN, verify they have access to this site
    if (session.user.role === 'SITE_ADMIN' && existingTournament.siteId && session.user.siteId !== existingTournament.siteId) {
      return NextResponse.json(
        { error: 'Forbidden: You do not have access to this tournament' },
        { status: 403 }
      );
    }

    // Only allow deletion of DRAFT tournaments
    if (existingTournament.status !== 'DRAFT') {
      return NextResponse.json(
        { error: 'Only tournaments in DRAFT status can be deleted. Consider cancelling instead.' },
        { status: 400 }
      );
    }

    // Delete the tournament (cascades to inscriptions and matches)
    await db.tournament.delete({
      where: { id },
    });

    return NextResponse.json({
      message: 'Tournament deleted successfully',
    });
  } catch (error) {
    console.error('Error deleting tournament:', error);
    return NextResponse.json(
      { error: 'Failed to delete tournament' },
      { status: 500 }
    );
  }
}
