import { and, asc, count, desc, eq, ilike, inArray, or } from 'drizzle-orm';
import { NextRequest, NextResponse } from 'next/server';
import { products } from '@/db/schema';
import type { ProductMutationPayload } from '@/features/products/api/types';
import { AuthError, requireOrganizationAccess } from '@/lib/auth/session';
import { db } from '@/lib/db';

const sortMap = {
  name: products.name,
  category: products.category,
  price: products.price,
  created_at: products.createdAt,
  updated_at: products.updatedAt
} as const;

function buildProductImageUrl(name: string) {
  return `https://placehold.co/120x120/336b4a/ffffff/png?text=${encodeURIComponent(name.slice(0, 12))}`;
}

export async function GET(request: NextRequest) {
  try {
    const { organization } = await requireOrganizationAccess();
    const { searchParams } = request.nextUrl;

    const page = Number(searchParams.get('page') ?? 1);
    const limit = Number(searchParams.get('limit') ?? 10);
    const categories = searchParams.get('categories');
    const search = searchParams.get('search');
    const sort = searchParams.get('sort');
    const categoryValues = categories
      ? categories
          .split(/[.,]/)
          .map((value) => value.trim())
          .filter(Boolean)
      : [];

    const filters = [
      eq(products.organizationId, organization.id),
      ...(categoryValues.length ? [inArray(products.category, categoryValues)] : []),
      ...(search
        ? [
            or(
              ilike(products.name, `%${search}%`),
              ilike(products.description, `%${search}%`),
              ilike(products.category, `%${search}%`)
            )!
          ]
        : [])
    ];

    const where = filters.length === 1 ? filters[0] : and(...filters);

    const [totalResult] = await db.select({ value: count() }).from(products).where(where);

    let orderByClause = desc(products.createdAt);

    if (sort) {
      try {
        const sortItems = JSON.parse(sort) as Array<{ id: keyof typeof sortMap; desc: boolean }>;
        const primarySort = sortItems[0];

        if (primarySort?.id && sortMap[primarySort.id]) {
          orderByClause = primarySort.desc
            ? desc(sortMap[primarySort.id])
            : asc(sortMap[primarySort.id]);
        }
      } catch {
        orderByClause = desc(products.createdAt);
      }
    }

    const offset = (page - 1) * limit;
    const rows = await db.select().from(products).where(where).orderBy(orderByClause).limit(limit).offset(offset);

    return NextResponse.json({
      success: true,
      time: new Date().toISOString(),
      message: 'Products loaded successfully',
      total_products: totalResult?.value ?? 0,
      offset,
      limit,
      products: rows.map((product) => ({
        id: product.id,
        organization_id: product.organizationId,
        photo_url: product.photoUrl,
        name: product.name,
        description: product.description,
        created_at: product.createdAt.toISOString(),
        price: product.price,
        category: product.category,
        updated_at: product.updatedAt.toISOString()
      }))
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    return NextResponse.json({ message: 'Unable to load products' }, { status: 500 });
  }
}

export async function POST(request: NextRequest) {
  try {
    const { organization } = await requireOrganizationAccess();
    const body = (await request.json()) as ProductMutationPayload;

    const [product] = await db
      .insert(products)
      .values({
        organizationId: organization.id,
        name: body.name,
        category: body.category,
        price: body.price,
        description: body.description,
        photoUrl: body.photoDataUrl || buildProductImageUrl(body.name)
      })
      .returning();

    return NextResponse.json(
      {
        success: true,
        time: new Date().toISOString(),
        message: 'Product created successfully',
        product: {
          id: product.id,
          organization_id: product.organizationId,
          photo_url: product.photoUrl,
          name: product.name,
          description: product.description,
          created_at: product.createdAt.toISOString(),
          price: product.price,
          category: product.category,
          updated_at: product.updatedAt.toISOString()
        }
      },
      { status: 201 }
    );
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    return NextResponse.json({ message: 'Unable to create product' }, { status: 500 });
  }
}
