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 product
const createProductSchema = z.object({
  siteId: z.string().cuid('Invalid site ID'),
  categoryId: z.string().cuid('Invalid category ID'),
  name: z.string().min(1, 'Product name is required').max(100),
  description: z.string().max(1000).optional(),
  sku: z.string().max(50).optional(),
  price: z.number().nonnegative('Price must be non-negative'),
  costPrice: z.number().nonnegative('Cost price must be non-negative').optional(),
  stock: z.number().int().min(0, 'Stock must be non-negative'),
  minStock: z.number().int().min(0, 'Minimum stock must be non-negative'),
  trackStock: z.boolean().optional().default(true),
  image: z.string().url().optional(),
  isActive: z.boolean().optional().default(true),
});

// GET /api/products - List products 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 siteId = searchParams.get('siteId');
    const categoryId = searchParams.get('categoryId');
    const search = searchParams.get('search');
    const isActiveParam = searchParams.get('isActive');

    // Non-SUPER_ADMIN users must provide a siteId or have a siteId assigned
    if (session.user.role !== 'SUPER_ADMIN' && !siteId && !session.user.siteId) {
      return NextResponse.json(
        { error: 'siteId is required' },
        { status: 400 }
      );
    }

    // Determine effective siteId
    const effectiveSiteId = siteId || session.user.siteId;

    // If siteId is provided, verify it belongs to user's organization
    if (effectiveSiteId) {
      const site = await db.site.findFirst({
        where: {
          id: effectiveSiteId,
          organizationId: session.user.organizationId,
        },
      });

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

    // Build the where clause
    interface ProductWhereClause {
      organizationId: string;
      categoryId?: string;
      isActive?: boolean;
      name?: {
        contains: string;
        mode: 'insensitive';
      };
    }

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

    // Filter by category
    if (categoryId) {
      whereClause.categoryId = categoryId;
    }

    // Filter by active status (default to true)
    if (isActiveParam !== null) {
      whereClause.isActive = isActiveParam !== 'false';
    } else {
      whereClause.isActive = true;
    }

    // Search by name
    if (search) {
      whereClause.name = {
        contains: search,
        mode: 'insensitive',
      };
    }

    const products = await db.product.findMany({
      where: whereClause,
      include: {
        category: {
          select: {
            id: true,
            name: true,
            description: true,
          },
        },
      },
      orderBy: [
        { category: { displayOrder: 'asc' } },
        { name: 'asc' },
      ],
    });

    // Add lowStock indicator to each product
    const productsWithLowStock = products.map((product) => ({
      ...product,
      lowStock: product.trackStock && product.stock < product.minStock,
    }));

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

// POST /api/products - Create a new product
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 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 body = await request.json();

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

    const {
      siteId,
      categoryId,
      name,
      description,
      sku,
      price,
      costPrice,
      stock,
      minStock,
      trackStock,
      image,
      isActive,
    } = validationResult.data;

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

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

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

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

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

    // Check if SKU is unique within the organization (if provided)
    if (sku) {
      const existingProduct = await db.product.findUnique({
        where: {
          organizationId_sku: {
            organizationId: session.user.organizationId,
            sku,
          },
        },
      });

      if (existingProduct) {
        return NextResponse.json(
          { error: 'A product with this SKU already exists' },
          { status: 409 }
        );
      }
    }

    const product = await db.product.create({
      data: {
        organizationId: session.user.organizationId,
        categoryId,
        name,
        description: description || null,
        sku: sku || null,
        price,
        costPrice: costPrice || null,
        stock,
        minStock,
        trackStock,
        image: image || null,
        isActive,
      },
      include: {
        category: {
          select: {
            id: true,
            name: true,
            description: true,
          },
        },
      },
    });

    // Add lowStock indicator
    const productWithLowStock = {
      ...product,
      lowStock: product.trackStock && product.stock < product.minStock,
    };

    return NextResponse.json(productWithLowStock, { status: 201 });
  } catch (error) {
    console.error('Error creating product:', error);
    return NextResponse.json(
      { error: 'Failed to create product' },
      { status: 500 }
    );
  }
}
