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';

// Validation schema for creating a membership
const createMembershipSchema = z.object({
  clientId: z.string().cuid('Invalid client ID'),
  planId: z.string().cuid('Invalid plan ID'),
  startDate: z.string().datetime({ message: 'Invalid start date format' }),
  endDate: z.string().datetime({ message: 'Invalid end date format' }),
  autoRenew: z.boolean().optional().default(false),
  notes: z.string().max(500).optional(),
});

// GET /api/memberships - List all memberships with filters
export async function GET(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions);

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

    const { searchParams } = new URL(request.url);
    const status = searchParams.get('status');
    const planId = searchParams.get('planId');
    const search = searchParams.get('search');
    const expiringOnly = searchParams.get('expiring') === 'true';
    const limit = searchParams.get('limit');
    const offset = searchParams.get('offset');

    // Build where clause - we need to get memberships from clients in the organization
    interface MembershipWhereClause {
      plan: {
        organizationId: string;
      };
      status?: 'ACTIVE' | 'EXPIRED' | 'CANCELLED' | 'SUSPENDED';
      planId?: string;
      endDate?: {
        gte?: Date;
        lte?: Date;
      };
      client?: {
        OR?: Array<{
          firstName?: { contains: string; mode: 'insensitive' };
          lastName?: { contains: string; mode: 'insensitive' };
          email?: { contains: string; mode: 'insensitive' };
        }>;
      };
    }

    const whereClause: MembershipWhereClause = {
      plan: {
        organizationId: session.user.organizationId,
      },
    };

    // Filter by status
    if (status) {
      const validStatuses = ['ACTIVE', 'EXPIRED', 'CANCELLED', 'SUSPENDED'] as const;
      const upperStatus = status.toUpperCase();
      if (validStatuses.includes(upperStatus as typeof validStatuses[number])) {
        whereClause.status = upperStatus as typeof validStatuses[number];
      }
    }

    // Filter by plan
    if (planId) {
      whereClause.planId = planId;
    }

    // Filter by expiring (within 7 days)
    if (expiringOnly) {
      const now = new Date();
      const sevenDaysFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
      whereClause.status = 'ACTIVE';
      whereClause.endDate = {
        gte: now,
        lte: sevenDaysFromNow,
      };
    }

    // Search by client name or email
    if (search && search.trim().length > 0) {
      const searchTerm = search.trim();
      whereClause.client = {
        OR: [
          { firstName: { contains: searchTerm, mode: 'insensitive' } },
          { lastName: { contains: searchTerm, mode: 'insensitive' } },
          { email: { contains: searchTerm, mode: 'insensitive' } },
        ],
      };
    }

    // Pagination
    const take = limit ? Math.min(parseInt(limit, 10), 100) : 50;
    const skip = offset ? parseInt(offset, 10) : 0;

    // Get total count
    const totalCount = await db.membership.count({
      where: whereClause,
    });

    const memberships = await db.membership.findMany({
      where: whereClause,
      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,
          },
        },
      },
      orderBy: [
        { status: 'asc' },
        { endDate: 'asc' },
      ],
      take,
      skip,
    });

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

    const membershipsWithDetails = memberships.map((membership) => ({
      ...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({
      data: membershipsWithDetails,
      pagination: {
        total: totalCount,
        limit: take,
        offset: skip,
        hasMore: skip + take < totalCount,
      },
    });
  } catch (error) {
    console.error('Error fetching memberships:', error);
    return NextResponse.json(
      { error: 'Failed to fetch memberships' },
      { status: 500 }
    );
  }
}

// POST /api/memberships - Create membership for client
export async function POST(request: NextRequest) {
  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 body = await request.json();

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

    const { clientId, planId, startDate, endDate, autoRenew, notes } = validationResult.data;

    // Verify client belongs to organization
    const client = await db.client.findFirst({
      where: {
        id: clientId,
        organizationId: session.user.organizationId,
      },
    });

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

    // Verify plan belongs to organization and is active
    const plan = await db.membershipPlan.findFirst({
      where: {
        id: planId,
        organizationId: session.user.organizationId,
        isActive: true,
      },
    });

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

    // Check if client already has an active membership
    const existingMembership = await db.membership.findFirst({
      where: {
        clientId,
        status: 'ACTIVE',
        endDate: {
          gte: new Date(),
        },
      },
    });

    if (existingMembership) {
      return NextResponse.json(
        {
          error: 'Client already has an active membership',
          existingMembershipId: existingMembership.id,
          expiresAt: existingMembership.endDate,
        },
        { status: 409 }
      );
    }

    // Create the membership
    const membership = await db.membership.create({
      data: {
        planId,
        clientId,
        startDate: new Date(startDate),
        endDate: new Date(endDate),
        status: 'ACTIVE',
        remainingHours: plan.courtHours || null,
        autoRenew: autoRenew || false,
        notes: notes || null,
      },
      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.endDate <= sevenDaysFromNow,
      daysUntilExpiry: Math.ceil((membership.endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)),
      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, { status: 201 });
  } catch (error) {
    console.error('Error creating membership:', error);
    return NextResponse.json(
      { error: 'Failed to create membership' },
      { status: 500 }
    );
  }
}
