/**
 * POST /api/fedex/webhook
 * Handle FedEx webhook events for tracking notifications
 */

import { type NextRequest, NextResponse } from "next/server"
import { WooCommerce } from "@/lib/woo"
import { logger } from "@/lib/logger"
import { RateLimit, getClientIp } from "@/lib/rate-limit"
import { FedExWebhookSchema } from "@/lib/schemas"

// Rate limit: 100 requests per minute (webhooks can be frequent)
const rateLimiter = new RateLimit(100, 60000)

export async function POST(request: NextRequest) {
  try {
    // Apply rate limiting
    const clientIp = getClientIp(request)
    const rateLimit = rateLimiter.check(clientIp)

    if (!rateLimit.allowed) {
      logger.warn("fedex", "Webhook rate limit exceeded", { ip: clientIp })
      return NextResponse.json(
        { error: "Too many requests" },
        { status: 429 }
      )
    }

    // Parse request body
    const body = await request.json()

    // Validate webhook payload
    const validation = FedExWebhookSchema.safeParse(body)
    if (!validation.success) {
      logger.error("fedex", "Invalid webhook payload", {
        body,
        errors: validation.error.issues,
      })
      // Return 200 to prevent FedEx from retrying invalid payloads
      return NextResponse.json({ received: true })
    }

    const payload = validation.data

    logger.info("fedex", "Webhook event received", {
      trackingNumber: payload.trackingNumber,
      eventType: payload.eventType,
      statusCode: payload.statusCode,
    })

    // Find WooCommerce order by tracking number metadata
    // We store _fedex_tracking_number when creating the shipment
    const trackingNumber = payload.trackingNumber

    if (!trackingNumber) {
      logger.warn("fedex", "Webhook missing tracking number", { payload })
      return NextResponse.json({ received: true })
    }

    // Search for the WooCommerce order with this tracking number
    // We'll look up orders that have the _fedex_tracking_number metadata
    let wooOrderId: number | null = null

    try {
      // Search WooCommerce for order with matching tracking number
      const orders = await WooCommerce.searchOrdersByMeta(
        "_fedex_tracking_number",
        trackingNumber
      )

      if (orders.length > 0) {
        wooOrderId = orders[0].id
      }
    } catch (error) {
      logger.error("fedex", "Failed to search WooCommerce orders by tracking number", {
        trackingNumber,
        error: error instanceof Error ? error.message : "Unknown error",
      })
    }

    if (!wooOrderId) {
      logger.warn("fedex", "No WooCommerce order found for tracking number", {
        trackingNumber,
      })
      return NextResponse.json({ received: true })
    }

    // Fetch order from WooCommerce
    let order
    try {
      order = await WooCommerce.getOrder(wooOrderId)
    } catch (error) {
      logger.error("fedex", "Failed to fetch WooCommerce order", {
        orderId: wooOrderId,
        error: error instanceof Error ? error.message : "Unknown error",
      })
      return NextResponse.json({ received: true })
    }

    // Check if order is in a state that can be updated
    if (order.status !== "processing" && order.status !== "shipped") {
      logger.warn("fedex", "Order not in processable state for shipment update", {
        orderId: wooOrderId,
        currentStatus: order.status,
      })
      return NextResponse.json({ received: true })
    }

    // Determine WooCommerce status based on FedEx event
    const eventType = payload.eventType?.toUpperCase() || ""
    const statusCode = payload.statusCode?.toUpperCase() || ""

    let newStatus: string = order.status
    let customerNote = ""

    if (statusCode === "DL" || eventType.includes("DELIVERED")) {
      // Delivered
      newStatus = "completed"
      customerNote = `Your order has been delivered! Tracking: ${trackingNumber}`
    } else if (
      statusCode === "IT" ||
      eventType.includes("IN_TRANSIT") ||
      eventType.includes("PICKED_UP")
    ) {
      // In transit / picked up
      newStatus = "shipped"
      customerNote = `Your order is in transit! Tracking: ${trackingNumber} | Carrier: FedEx`
    } else if (eventType.includes("EXCEPTION") || statusCode === "DE") {
      // Delivery exception
      customerNote = `Delivery exception for tracking ${trackingNumber}: ${payload.eventDescription || "Contact support"}`
    }

    // Only update if status changed or we have a note to add
    if (newStatus !== order.status || customerNote) {
      const updateData: any = {
        meta_data: [
          ...order.meta_data,
          {
            key: "_fedex_last_event",
            value: payload.eventType || "",
          },
          {
            key: "_fedex_last_status_code",
            value: payload.statusCode || "",
          },
          {
            key: "_fedex_webhook_received_at",
            value: new Date().toISOString(),
          },
        ],
      }

      if (newStatus !== order.status) {
        updateData.status = newStatus
      }

      if (customerNote) {
        updateData.customer_note = customerNote
      }

      // Add tracking metadata on first shipped event
      if (newStatus === "shipped" && order.status === "processing") {
        updateData.meta_data.push(
          {
            key: "_tracking_number",
            value: trackingNumber,
          },
          {
            key: "_shipping_carrier",
            value: "FedEx",
          },
          {
            key: "_shipped_date",
            value: new Date().toISOString(),
          }
        )
      }

      try {
        await WooCommerce.updateOrder(wooOrderId, updateData)

        logger.info("fedex", "Order updated with tracking info", {
          orderId: wooOrderId,
          trackingNumber,
          eventType: payload.eventType,
          newStatus,
        })
      } catch (error) {
        logger.error("fedex", "Failed to update order status", {
          orderId: wooOrderId,
          error: error instanceof Error ? error.message : "Unknown error",
        })
      }
    }

    return NextResponse.json({ received: true })
  } catch (error) {
    logger.error("fedex", "Webhook error", {
      error: error instanceof Error ? error.message : "Unknown error",
      stack: error instanceof Error ? error.stack : undefined,
    })
    // Return 200 even on error to prevent retries
    return NextResponse.json({ received: true })
  }
}
