import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { sanitizeString, isValidId, isValidLength, isValidPhone, isValidOrderStatus } from '@/lib/validation';
import { checkRateLimit, getRateLimitIdentifier, rateLimitError, RATE_LIMITS } from '@/lib/rate-limit';

export async function POST(request: NextRequest) {
  try {
    // Rate limit order creation
    const identifier = `orders:${getRateLimitIdentifier(request)}`;
    const rateLimit = checkRateLimit(identifier, RATE_LIMITS.api);
    if (!rateLimit.allowed) return rateLimitError(rateLimit.resetTime);

    const body = await request.json();
    const { userId, items, address, phone, notes } = body;

    if (!userId || !items || !Array.isArray(items) || items.length === 0 || !address || !phone) {
      return NextResponse.json(
        { error: 'Missing required fields: userId, items, address, phone' },
        { status: 400 }
      );
    }

    if (!isValidId(userId)) {
      return NextResponse.json(
        { error: 'Invalid user ID format' },
        { status: 400 }
      );
    }

    if (!isValidLength(address, 1, 500)) {
      return NextResponse.json(
        { error: 'Address must be between 1 and 500 characters' },
        { status: 400 }
      );
    }

    if (!isValidPhone(phone)) {
      return NextResponse.json(
        { error: 'Invalid phone number format' },
        { status: 400 }
      );
    }

    // Limit items per order
    if (items.length > 50) {
      return NextResponse.json(
        { error: 'Maximum 50 items per order' },
        { status: 400 }
      );
    }

    // Validate each item
    for (const item of items) {
      if (!item.productId || typeof item.productId !== 'string' || !isValidId(item.productId)) {
        return NextResponse.json(
          { error: 'Invalid product ID in items' },
          { status: 400 }
        );
      }
      if (item.quantity && (typeof item.quantity !== 'number' || item.quantity < 1 || item.quantity > 100)) {
        return NextResponse.json(
          { error: 'Invalid quantity in items (must be 1-100)' },
          { status: 400 }
        );
      }
    }

    // Calculate total amount from items
    const productIds = items.map((item: { productId: string }) => item.productId);
    const products = await db.product.findMany({
      where: { id: { in: productIds } },
    });

    const productMap = new Map(products.map((p) => [p.id, p]));

    let totalAmount = 0;
    const orderItemsData = items.map((item: { productId: string; quantity?: number }) => {
      const product = productMap.get(item.productId);
      if (!product) {
        throw new Error(`Product not found: ${item.productId}`);
      }
      const quantity = item.quantity || 1;
      const price = product.price * quantity;
      totalAmount += price;
      return {
        productId: item.productId,
        quantity,
        price: product.price,
      };
    });

    const order = await db.order.create({
      data: {
        userId,
        totalAmount,
        status: 'pending',
        address: sanitizeString(address),
        phone: sanitizeString(phone),
        notes: notes ? sanitizeString(notes) : null,
        items: {
          create: orderItemsData,
        },
      },
      include: {
        items: {
          include: {
            product: {
              select: {
                id: true,
                title: true,
                images: true,
                price: true,
              },
            },
          },
        },
      },
    });

    return NextResponse.json({ order }, { status: 201 });
  } catch (error) {
    console.error('Orders POST error:', error);
    if (error instanceof Error && error.message.startsWith('Product not found')) {
      return NextResponse.json({ error: error.message }, { status: 404 });
    }
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const userId = searchParams.get('userId');
    const status = searchParams.get('status');
    const page = Math.max(1, parseInt(searchParams.get('page') || '1'));
    const limit = Math.min(100, Math.max(1, parseInt(searchParams.get('limit') || '10')));

    if (!userId) {
      return NextResponse.json(
        { error: 'userId is required' },
        { status: 400 }
      );
    }

    if (!isValidId(userId)) {
      return NextResponse.json(
        { error: 'Invalid user ID format' },
        { status: 400 }
      );
    }

    const where: Record<string, unknown> = { userId };
    if (status && isValidOrderStatus(status)) where.status = status;

    const skip = (page - 1) * limit;

    const [orders, total] = await Promise.all([
      db.order.findMany({
        where,
        include: {
          items: {
            include: {
              product: {
                select: {
                  id: true,
                  title: true,
                  images: true,
                  price: true,
                },
              },
            },
          },
        },
        orderBy: { createdAt: 'desc' },
        skip,
        take: limit,
      }),
      db.order.count({ where }),
    ]);

    return NextResponse.json({
      orders,
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit),
      },
    });
  } catch (error) {
    console.error('Orders GET error:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}
