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

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

// Validation schema for updating a membership
const updateMembershipSchema = z.object({
  status: z.enum(['ACTIVE', 'EXPIRED', 'CANCELLED', 'SUSPENDED']).optional(),
  planId: z.string().cuid().optional(),
  endDate: z.string().datetime().optional(),
  hoursUsed: z.number().int().min(0).optional(),
  autoRenew: z.boolean().optional(),
  notes: z.string().max(500).optional().nullable(),
});

// GET /api/memberships/[id] - Get membership with plan and client details
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 membership = await db.membership.findFirst({
      where: {
        id,
        plan: {
          organizationId: session.user.organizationId,
        },
      },
      include: {
        plan: {
          select: {
            id: true,
            name: true,
            description: true,
            price: true,
            durationMonths: true,
            courtHours: true,
            discountPercent: true,
            benefits: true,
            isActive: true,
          },
        },
        client: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
            email: true,
            phone: true,
            level: true,
            tags: true,
          },
        },
        payments: {
          select: {
            id: true,
            amount: true,
            paymentType: true,
            createdAt: true,
          },
          orderBy: {
            createdAt: 'desc',
          },
        },
      },
    });

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

    // Calculate computed fields
    const now = new Date();
    const sevenDaysFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);

    const hoursUsed = membership.plan.courtHours && membership.remainingHours !== null
      ? membership.plan.courtHours - membership.remainingHours
      : 0;

    const membershipWithDetails = {
      ...membership,
      isExpiring: membership.status === 'ACTIVE' && membership.endDate <= sevenDaysFromNow,
      isExpired: membership.status === 'ACTIVE' && membership.endDate < now,
      daysUntilExpiry: membership.status === 'ACTIVE'
        ? Math.ceil((membership.endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))
        : null,
      hoursUsed,
      benefitsSummary: {
        freeHours: membership.plan.courtHours || 0,
        hoursRemaining: membership.remainingHours || 0,
        hoursUsed,
        bookingDiscount: membership.plan.discountPercent ? Number(membership.plan.discountPercent) : 0,
        extraBenefits: membership.plan.benefits || [],
      },
      totalPaid: membership.payments.reduce(
        (sum, p) => sum + Number(p.amount),
        0
      ),
    };

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

// PUT /api/memberships/[id] - Update membership (renew, cancel, change plan)
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 appropriate role
    const allowedRoles = ['SUPER_ADMIN', 'ORG_ADMIN', 'SITE_ADMIN', 'RECEPTIONIST'];
    if (!allowedRoles.includes(session.user.role)) {
      return NextResponse.json(
        { error: 'Forbidden: Insufficient permissions' },
        { status: 403 }
      );
    }

    const { id } = await context.params;

    // Verify membership exists and belongs to organization
    const existingMembership = await db.membership.findFirst({
      where: {
        id,
        plan: {
          organizationId: session.user.organizationId,
        },
      },
      include: {
        plan: true,
      },
    });

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

    const body = await request.json();

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

    const { status, planId, endDate, hoursUsed, autoRenew, notes } = validationResult.data;

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

    if (status !== undefined) updateData.status = status;
    if (endDate !== undefined) updateData.endDate = new Date(endDate);
    if (autoRenew !== undefined) updateData.autoRenew = autoRenew;
    if (notes !== undefined) updateData.notes = notes;

    // Handle hours used - update remaining hours
    if (hoursUsed !== undefined && existingMembership.plan.courtHours) {
      const newRemainingHours = Math.max(0, existingMembership.plan.courtHours - hoursUsed);
      updateData.remainingHours = newRemainingHours;
    }

    // Handle plan change
    if (planId !== undefined && planId !== existingMembership.planId) {
      // Verify new plan exists and belongs to organization
      const newPlan = await db.membershipPlan.findFirst({
        where: {
          id: planId,
          organizationId: session.user.organizationId,
          isActive: true,
        },
      });

      if (!newPlan) {
        return NextResponse.json(
          { error: 'New membership plan not found or inactive' },
          { status: 404 }
        );
      }

      updateData.plan = {
        connect: { id: planId },
      };

      // Reset remaining hours to new plan's court hours
      if (newPlan.courtHours !== null) {
        updateData.remainingHours = newPlan.courtHours;
      }
    }

    const membership = await db.membership.update({
      where: { id },
      data: updateData,
      include: {
        plan: {
          select: {
            id: true,
            name: true,
            price: true,
            durationMonths: true,
            courtHours: true,
            discountPercent: true,
            benefits: true,
          },
        },
        client: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
            email: true,
            phone: true,
          },
        },
      },
    });

    // Add computed fields
    const now = new Date();
    const sevenDaysFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);

    const membershipWithDetails = {
      ...membership,
      isExpiring: membership.status === 'ACTIVE' && membership.endDate <= sevenDaysFromNow,
      daysUntilExpiry: membership.status === 'ACTIVE'
        ? Math.ceil((membership.endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))
        : null,
      benefitsSummary: {
        freeHours: membership.plan.courtHours || 0,
        hoursRemaining: membership.remainingHours || 0,
        bookingDiscount: membership.plan.discountPercent ? Number(membership.plan.discountPercent) : 0,
        extraBenefits: membership.plan.benefits || [],
      },
    };

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

// DELETE /api/memberships/[id] - Cancel membership (set status = CANCELLED)
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 appropriate 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 membership exists and belongs to organization
    const existingMembership = await db.membership.findFirst({
      where: {
        id,
        plan: {
          organizationId: session.user.organizationId,
        },
      },
      include: {
        client: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
          },
        },
        plan: {
          select: {
            name: true,
          },
        },
      },
    });

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

    // Already cancelled
    if (existingMembership.status === 'CANCELLED') {
      return NextResponse.json(
        { error: 'Membership is already cancelled' },
        { status: 400 }
      );
    }

    // Cancel the membership
    await db.membership.update({
      where: { id },
      data: {
        status: 'CANCELLED',
        autoRenew: false,
      },
    });

    return NextResponse.json({
      message: 'Membership cancelled successfully',
      membershipId: id,
      client: `${existingMembership.client.firstName} ${existingMembership.client.lastName}`,
      plan: existingMembership.plan.name,
      previousStatus: existingMembership.status,
    });
  } catch (error) {
    console.error('Error cancelling membership:', error);
    return NextResponse.json(
      { error: 'Failed to cancel membership' },
      { status: 500 }
    );
  }
}
