import { getSquareClient, getSquareLocationId, checkSquareConnection } from "@/lib/square-client" import type { SquareProduct, SquareCategory } from "@/lib/square-types" export async function GET(request: Request) { try { console.log("=== Square Catalog API Request ===") // First, check if Square is properly configured const connectionCheck = await checkSquareConnection() if (!connectionCheck.success) { console.error("Square connection failed:", connectionCheck.error) return Response.json({ success: false, error: "Square API connection failed", details: connectionCheck.error, products: [], categories: [] }, { status: 500 }) } console.log("Square connection verified:", connectionCheck.message) const { searchParams } = new URL(request.url) const categoryId = searchParams.get('categoryId') const includeInventory = searchParams.get('includeInventory') === 'true' console.log("Category filter:", categoryId) console.log("Include inventory:", includeInventory) const client = await getSquareClient() const locationId = getSquareLocationId() const catalogApi = client.catalogApi // Build search request const searchRequest: any = { objectTypes: ["ITEM"], includeDeletedObjects: false, includeRelatedObjects: true, } // Add category filter if specified if (categoryId) { searchRequest.query = { exactQuery: { attributeName: "category_id", attributeValue: categoryId } } } console.log("Searching catalog with request:", searchRequest) // Search catalog items const catalogResponse = await catalogApi.searchCatalogObjects(searchRequest) console.log("Catalog response received:", { objectCount: catalogResponse.result.objects?.length || 0, hasObjects: !!catalogResponse.result.objects }) if (!catalogResponse.result.objects || catalogResponse.result.objects.length === 0) { return Response.json({ success: true, products: [], categories: [], message: "No products found in Square catalog. Add products in your Square Dashboard." }) } // Separate items and categories const items = catalogResponse.result.objects.filter(obj => obj.type === "ITEM") const categories = catalogResponse.result.objects.filter(obj => obj.type === "CATEGORY") console.log("Found items:", items.length, "categories:", categories.length) // Process categories const processedCategories: SquareCategory[] = categories.map(cat => ({ id: cat.id!, name: cat.categoryData?.name || "Unnamed Category", imageUrl: cat.categoryData?.imageIds?.[0] ? `/api/square/catalog/image/${cat.categoryData.imageIds[0]}` : undefined })) // Get inventory data if requested let inventoryData: Record = {} if (includeInventory) { try { const variationIds = items.flatMap(item => item.itemData?.variations?.map(v => v.id!) || [] ).filter(Boolean) if (variationIds.length > 0) { console.log("Fetching inventory for", variationIds.length, "variations") const inventoryApi = client.inventoryApi const inventoryResponse = await inventoryApi.batchRetrieveInventoryCounts({ catalogObjectIds: variationIds, locationIds: [locationId] }) inventoryResponse.result.counts?.forEach(count => { if (count.catalogObjectId) { inventoryData[count.catalogObjectId] = parseInt(count.quantity || "0") } }) console.log("Inventory data loaded for", Object.keys(inventoryData).length, "items") } } catch (inventoryError) { console.warn("Failed to fetch inventory:", inventoryError) // Continue without inventory data } } // Process items into products const products: SquareProduct[] = items .filter(item => { const hasVariations = item.itemData?.variations && item.itemData.variations.length > 0 if (!hasVariations) { console.warn("Skipping item without variations:", item.id, item.itemData?.name) } return hasVariations }) .map(item => { const itemData = item.itemData! const primaryVariation = itemData.variations![0] const variationData = primaryVariation.itemVariationData! const price = variationData.priceMoney // Get inventory for primary variation const inventory = inventoryData[primaryVariation.id!] || 0 // Process all variations const variations = itemData.variations!.map(variation => { const vData = variation.itemVariationData! const vPrice = vData.priceMoney return { id: variation.id!, name: vData.name || itemData.name || "Default", price: vPrice ? Number(vPrice.amount) / 100 : 0, currency: vPrice?.currency || "USD", inventory: inventoryData[variation.id!] || 0, sku: vData.sku } }) return { id: item.id!, variationId: primaryVariation.id!, name: itemData.name || "Unnamed Product", description: itemData.description || "", price: price ? Number(price.amount) / 100 : 0, currency: price?.currency || "USD", imageUrl: itemData.imageIds?.[0] ? `/api/square/catalog/image/${itemData.imageIds[0]}` : "/placeholder.svg?height=400&width=400&text=Product+Image", inventory, category: itemData.categoryId || "uncategorized", categoryName: categories.find(c => c.id === itemData.categoryId)?.categoryData?.name, isAvailable: inventory > 0, variations } }) console.log("Successfully processed", products.length, "products") return Response.json({ success: true, products, categories: processedCategories, message: `Found ${products.length} products and ${processedCategories.length} categories` }) } catch (error) { console.error("=== Square Catalog Error ===") console.error("Error type:", error?.constructor?.name) console.error("Error message:", error instanceof Error ? error.message : String(error)) console.error("Stack trace:", error instanceof Error ? error.stack : "No stack") // Return detailed error information return Response.json({ success: false, error: error instanceof Error ? error.message : "Unknown catalog error", details: { type: error?.constructor?.name || "Unknown", message: error instanceof Error ? error.message : String(error), suggestion: "Check your Square API credentials and ensure products exist in your Square catalog" }, products: [], categories: [] }, { status: 500 }) } }