import { and, eq, type InferSelectModel } 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';

type Params = { params: Promise<{ id: string }> };

function toProductResponse(product: InferSelectModel<typeof products>) {
  return {
    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()
  };
}

export async function GET(request: NextRequest, { params }: Params) {
  try {
    const { organization } = await requireOrganizationAccess();
    const { id } = await params;

    const product = await db.query.products.findFirst({
      where: and(eq(products.id, Number(id)), eq(products.organizationId, organization.id))
    });

    if (!product) {
      return NextResponse.json(
        { success: false, message: `Product with ID ${id} not found` },
        { status: 404 }
      );
    }

    return NextResponse.json({
      success: true,
      time: new Date().toISOString(),
      message: `Product with ID ${id} found`,
      product: toProductResponse(product)
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

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

export async function PATCH(request: NextRequest, { params }: Params) {
  try {
    const { organization } = await requireOrganizationAccess();
    const { id } = await params;
    const body = (await request.json()) as ProductMutationPayload;

    const existingProduct = await db.query.products.findFirst({
      where: and(eq(products.id, Number(id)), eq(products.organizationId, organization.id))
    });

    if (!existingProduct) {
      return NextResponse.json(
        { success: false, message: `Product with ID ${id} not found` },
        { status: 404 }
      );
    }

    const [product] = await db
      .update(products)
      .set({
        name: body.name,
        category: body.category,
        price: body.price,
        description: body.description,
        photoUrl: body.photoDataUrl || existingProduct.photoUrl,
        updatedAt: new Date()
      })
      .where(and(eq(products.id, Number(id)), eq(products.organizationId, organization.id)))
      .returning();

    return NextResponse.json({
      success: true,
      time: new Date().toISOString(),
      message: 'Product updated successfully',
      product: toProductResponse(product)
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

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

export async function DELETE(request: NextRequest, { params }: Params) {
  try {
    const { organization } = await requireOrganizationAccess();
    const { id } = await params;

    const [deletedProduct] = await db
      .delete(products)
      .where(and(eq(products.id, Number(id)), eq(products.organizationId, organization.id)))
      .returning({ id: products.id });

    if (!deletedProduct) {
      return NextResponse.json(
        { success: false, message: `Product with ID ${id} not found` },
        { status: 404 }
      );
    }

    return NextResponse.json({
      success: true,
      message: 'Product deleted successfully'
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

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