/**
 * EasyShip API Client
 * Handles all interactions with EasyShip REST API (v2024-09)
 */

import { randomUUID } from "crypto"
import { env } from "./env"
import { logger } from "./logger"
import type { WooOrder, WooAddress } from "./woo"
import type {
  EasyShipShipmentRequest,
  EasyShipAddress,
  EasyShipItem,
  EasyShipParcel,
  EasyShipShipmentResponse,
  EasyShipShipmentResult,
  EasyShipError,
} from "./types/easyship"

const EASYSHIP_API_BASE = "https://public-api.easyship.com/2024-09"

// Default item dimensions/weight when WooCommerce doesn't provide them
const DEFAULT_ITEM_WEIGHT_LB = 0.5
const DEFAULT_BOX_LENGTH_IN = 10
const DEFAULT_BOX_WIDTH_IN = 10
const DEFAULT_BOX_HEIGHT_IN = 10
const DEFAULT_ITEM_CATEGORY = "health_beauty"

// Default origin address (your warehouse/fulfillment center)
// TODO: Configure these in environment variables or EasyShip dashboard
const DEFAULT_ORIGIN_ADDRESS: EasyShipAddress = {
  line_1: "123 Warehouse Ave",
  city: "Los Angeles",
  state: "CA",
  postal_code: "90001",
  country_alpha2: "US",
  company_name: "Factor Peptides",
  contact_name: "Factor Peptides",
  contact_phone: "+1-555-000-0000",
  contact_email: "shipping@factorpeptides.com",
}

/**
 * EasyShip API Client
 */
export class EasyShip {
  /**
   * Generate Bearer Auth header for EasyShip API
   */
  private static getAuthHeader(): string {
    return `Bearer ${env.EASYSHIP_API_TOKEN}`
  }

  /**
   * Make authenticated request to EasyShip API
   */
  private static async request<T>(
    endpoint: string,
    options: RequestInit = {}
  ): Promise<{ success: boolean; data?: T; error?: string; errorDetails?: any }> {
    const url = `${EASYSHIP_API_BASE}${endpoint}`

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      Authorization: this.getAuthHeader(),
    }

    // Add idempotency key for POST requests
    if (options.method === "POST") {
      headers["Idempotency-Key"] = randomUUID()
    }

    try {
      const response = await fetch(url, {
        ...options,
        headers: {
          ...headers,
          ...options.headers,
        },
      })

      const responseText = await response.text()
      let data: T | EasyShipError

      try {
        data = JSON.parse(responseText)
      } catch {
        if (!response.ok) {
          return {
            success: false,
            error: `EasyShip API error: ${response.status} ${response.statusText}`,
            errorDetails: responseText,
          }
        }
        data = {} as T
      }

      if (!response.ok) {
        const error = data as EasyShipError
        const message =
          error.error?.message || error.message || `HTTP ${response.status}`
        return {
          success: false,
          error: message,
          errorDetails: error,
        }
      }

      return {
        success: true,
        data: data as T,
      }
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : "Unknown error",
        errorDetails: error,
      }
    }
  }

  /**
   * Map WooCommerce address to EasyShip address format
   */
  private static mapAddress(
    wooAddress: WooAddress,
    email?: string
  ): EasyShipAddress {
    return {
      contact_name: `${wooAddress.first_name} ${wooAddress.last_name}`.trim(),
      line_1: wooAddress.address_1,
      line_2: wooAddress.address_2 || undefined,
      city: wooAddress.city,
      state: wooAddress.state,
      postal_code: wooAddress.postcode,
      country_alpha2: wooAddress.country,
      contact_email: email || wooAddress.email || "noreply@example.com",
      contact_phone: "+1-000-000-0000",
    }
  }

  /**
   * Map WooCommerce line items to EasyShip parcel with items
   */
  private static mapParcel(order: WooOrder): EasyShipParcel {
    const currency = order.currency || "USD"

    const items: EasyShipItem[] = order.line_items.map((item) => {
      const unitPrice =
        item.quantity > 0
          ? parseFloat(item.total) / item.quantity
          : parseFloat(item.total)

      return {
        description: item.name,
        sku: String(item.product_id),
        quantity: item.quantity,
        actual_weight: DEFAULT_ITEM_WEIGHT_LB,
        declared_currency: currency,
        declared_customs_value: Math.round(unitPrice * 100) / 100,
        category: DEFAULT_ITEM_CATEGORY,
      }
    })

    // Calculate total weight from all items
    const totalWeight = items.reduce(
      (sum, item) => sum + item.actual_weight * item.quantity,
      0
    )

    return {
      box: {
        length: DEFAULT_BOX_LENGTH_IN,
        width: DEFAULT_BOX_WIDTH_IN,
        height: DEFAULT_BOX_HEIGHT_IN,
      },
      items,
      total_actual_weight: totalWeight,
    }
  }

  /**
   * Check if order already synced to EasyShip
   * Returns EasyShip shipment ID if already synced, null otherwise
   */
  private static getExistingEasyShipShipmentId(order: WooOrder): string | null {
    const easyshipShipmentId = order.meta_data.find(
      (meta) => meta.key === "_easyship_shipment_id"
    )
    return easyshipShipmentId?.value ? String(easyshipShipmentId.value) : null
  }

  /**
   * Create shipment in EasyShip
   * Implements idempotency - checks if shipment already exists before creating
   */
  static async createShipment(order: WooOrder): Promise<EasyShipShipmentResult> {
    try {
      // Check for existing EasyShip shipment ID (idempotency)
      const existingShipmentId = this.getExistingEasyShipShipmentId(order)
      if (existingShipmentId) {
        logger.info("easyship", "Shipment already synced to EasyShip", {
          wooOrderId: order.id,
          easyshipShipmentId: existingShipmentId,
        })
        return {
          success: true,
          shipmentId: existingShipmentId,
          platformOrderNumber: String(order.id),
        }
      }

      // Determine email from billing address
      const customerEmail = order.billing.email || order.billing_email || ""

      // Use shipping address if available, fall back to billing
      const shippingAddress =
        order.shipping.address_1 ? order.shipping : order.billing

      // Build EasyShip shipment payload (v2024-09 schema)
      const shipmentRequest: EasyShipShipmentRequest = {
        origin_address: DEFAULT_ORIGIN_ADDRESS,
        destination_address: this.mapAddress(shippingAddress, customerEmail),
        parcels: [this.mapParcel(order)],
        incoterms: "DDU",
        insurance: {
          is_insured: false,
        },
        courier_settings: {
          allow_fallback: true,
          apply_shipping_rules: true,
        },
        order_data: {
          platform_name: "WooCommerce",
          platform_order_number: String(order.id),
          buyer_notes: order.customer_note || undefined,
        },
        shipping_settings: {
          units: {
            weight: "lb",
            dimensions: "in",
          },
          buy_label: false,
          buy_label_synchronous: false,
        },
      }

      logger.info("easyship", "Creating shipment in EasyShip", {
        wooOrderId: order.id,
        platformOrderNumber: String(order.id),
        itemCount: shipmentRequest.parcels[0].items.length,
        destination: `${shippingAddress.city}, ${shippingAddress.state} ${shippingAddress.country}`,
      })

      // Make API request
      const result = await this.request<EasyShipShipmentResponse>("/shipments", {
        method: "POST",
        body: JSON.stringify(shipmentRequest),
      })

      if (!result.success || !result.data) {
        logger.error("easyship", "Failed to create shipment in EasyShip", {
          wooOrderId: order.id,
          error: result.error,
          errorDetails: result.errorDetails,
        })
        return {
          success: false,
          error: result.error || "Failed to create shipment",
          errorDetails: result.errorDetails,
        }
      }

      const shipment = result.data.shipment

      logger.info("easyship", "Successfully created shipment in EasyShip", {
        wooOrderId: order.id,
        easyshipShipmentId: shipment.easyship_shipment_id,
        courierService: shipment.courier_service?.name,
        trackingPageUrl: shipment.tracking_page_url,
      })

      return {
        success: true,
        shipmentId: shipment.easyship_shipment_id,
        platformOrderNumber: shipment.order_data?.platform_order_number || String(order.id),
      }
    } catch (error) {
      logger.error("easyship", "Unexpected error creating EasyShip shipment", {
        wooOrderId: order.id,
        error: error instanceof Error ? error.message : "Unknown error",
        stack: error instanceof Error ? error.stack : undefined,
      })
      return {
        success: false,
        error: error instanceof Error ? error.message : "Unexpected error",
        errorDetails: error,
      }
    }
  }

  /**
   * Cancel a shipment in EasyShip
   * Used when orders are cancelled after being sent to EasyShip
   */
  static async cancelShipment(
    easyshipShipmentId: string
  ): Promise<EasyShipShipmentResult> {
    try {
      logger.info("easyship", "Cancelling shipment in EasyShip", {
        easyshipShipmentId,
      })

      const result = await this.request(
        `/shipments/${easyshipShipmentId}/cancel`,
        {
          method: "POST",
        }
      )

      if (!result.success) {
        logger.error("easyship", "Failed to cancel shipment in EasyShip", {
          easyshipShipmentId,
          error: result.error,
          errorDetails: result.errorDetails,
        })
        return {
          success: false,
          error: result.error || "Failed to cancel shipment",
          errorDetails: result.errorDetails,
        }
      }

      logger.info("easyship", "Successfully cancelled shipment in EasyShip", {
        easyshipShipmentId,
      })

      return {
        success: true,
      }
    } catch (error) {
      logger.error("easyship", "Unexpected error cancelling EasyShip shipment", {
        easyshipShipmentId,
        error: error instanceof Error ? error.message : "Unknown error",
        stack: error instanceof Error ? error.stack : undefined,
      })
      return {
        success: false,
        error: error instanceof Error ? error.message : "Unexpected error",
        errorDetails: error,
      }
    }
  }

  /**
   * Get shipment details from EasyShip
   * Used for debugging and verification
   */
  static async getShipment(easyshipShipmentId: string): Promise<{
    success: boolean
    shipment?: EasyShipShipmentResponse["shipment"]
    error?: string
  }> {
    try {
      const result = await this.request<EasyShipShipmentResponse>(
        `/shipments/${easyshipShipmentId}`,
        {
          method: "GET",
        }
      )

      if (!result.success || !result.data) {
        return {
          success: false,
          error: result.error || "Failed to get shipment",
        }
      }

      return {
        success: true,
        shipment: result.data.shipment,
      }
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : "Unexpected error",
      }
    }
  }
}
