/**
 * ShipStation API Client
 * Handles all interactions with ShipStation REST API
 */

import { env } from "./env"
import { logger } from "./logger"
import type { WooOrder, WooAddress } from "./woo"
import type {
  ShipStationOrder,
  ShipStationAddress,
  ShipStationLineItem,
  ShipStationOrderResponse,
  ShipStationOrderResult,
  ShipStationError,
} from "./types/shipstation"

const SHIPSTATION_API_BASE = "https://ssapi.shipstation.com"
const SHIPSTATION_API_KEY = env.SHIPSTATION_API_KEY
const SHIPSTATION_API_SECRET = env.SHIPSTATION_API_SECRET

/**
 * ShipStation API Client
 */
export class ShipStation {
  /**
   * Generate Basic Auth header for ShipStation API
   */
  private static getAuthHeader(): string {
    const credentials = `${SHIPSTATION_API_KEY}:${SHIPSTATION_API_SECRET}`
    const encoded = Buffer.from(credentials).toString("base64")
    return `Basic ${encoded}`
  }

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

    try {
      const response = await fetch(url, {
        ...options,
        headers: {
          "Content-Type": "application/json",
          Authorization: this.getAuthHeader(),
          ...options.headers,
        },
      })

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

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

      if (!response.ok) {
        const error = data as ShipStationError
        return {
          success: false,
          error: error.message || error.ExceptionMessage || `HTTP ${response.status}`,
          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 ShipStation address format
   */
  private static mapAddress(wooAddress: WooAddress, name?: string): ShipStationAddress {
    return {
      name: name || `${wooAddress.first_name} ${wooAddress.last_name}`.trim(),
      street1: wooAddress.address_1,
      street2: wooAddress.address_2 || undefined,
      city: wooAddress.city,
      state: wooAddress.state,
      postalCode: wooAddress.postcode,
      country: wooAddress.country,
      phone: undefined, // WooCommerce doesn't store phone in address object
      residential: true, // Default to residential
    }
  }

  /**
   * Map WooCommerce line items to ShipStation format
   */
  private static mapLineItems(order: WooOrder): ShipStationLineItem[] {
    return order.line_items.map((item) => {
      const unitPrice = item.quantity > 0 
        ? parseFloat(item.total) / item.quantity 
        : parseFloat(item.total)

      return {
        sku: String(item.product_id), // Use product_id as SKU
        name: item.name,
        quantity: item.quantity,
        unitPrice: Math.round(unitPrice * 100) / 100, // Round to 2 decimal places
        imageUrl: item.image?.src,
        productId: item.product_id,
      }
    })
  }

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

  /**
   * Create order in ShipStation
   * Implements idempotency - checks if order already exists before creating
   */
  static async createOrder(order: WooOrder): Promise<ShipStationOrderResult> {
    try {
      // Check for existing ShipStation order ID (idempotency)
      const existingOrderId = this.getExistingShipStationOrderId(order)
      if (existingOrderId) {
        logger.info("shipstation", "Order already synced to ShipStation", {
          wooOrderId: order.id,
          shipstationOrderId: existingOrderId,
        })
        return {
          success: true,
          orderId: parseInt(existingOrderId, 10),
          orderNumber: String(order.id),
        }
      }

      // Calculate totals
      const orderTotal = parseFloat(order.total)
      const shippingTotal = order.shipping_lines.reduce(
        (sum, line) => sum + parseFloat(line.total),
        0
      )

      // Build ShipStation order payload
      const shipstationOrder: ShipStationOrder = {
        orderNumber: String(order.id),
        orderDate: new Date().toISOString(),
        paymentDate: new Date().toISOString(),
        orderStatus: "awaiting_shipment",
        customerUsername: order.billing.email || order.billing_email || "",
        customerEmail: order.billing.email || order.billing_email || "",
        billTo: this.mapAddress(order.billing),
        shipTo: this.mapAddress(order.shipping),
        items: this.mapLineItems(order),
        amountPaid: orderTotal,
        shippingAmount: shippingTotal,
        taxAmount: 0, // WooCommerce doesn't expose tax in current schema
        customerNotes: order.customer_note || undefined,
        paymentMethod: "Credit Card (Stripe)",
      }

      logger.info("shipstation", "Creating order in ShipStation", {
        wooOrderId: order.id,
        orderNumber: shipstationOrder.orderNumber,
        itemCount: shipstationOrder.items.length,
        total: orderTotal,
      })

      // Make API request
      const result = await this.request<ShipStationOrderResponse>("/orders/createorder", {
        method: "POST",
        body: JSON.stringify(shipstationOrder),
      })

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

      logger.info("shipstation", "Successfully created order in ShipStation", {
        wooOrderId: order.id,
        shipstationOrderId: result.data.orderId,
        shipstationOrderNumber: result.data.orderNumber,
      })

      return {
        success: true,
        orderId: result.data.orderId,
        orderNumber: result.data.orderNumber,
      }
    } catch (error) {
      logger.error("shipstation", "Unexpected error creating ShipStation order", {
        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,
      }
    }
  }

  /**
   * Void/cancel an order in ShipStation
   * Used when orders are cancelled after being sent to ShipStation
   */
  static async voidOrder(shipstationOrderId: string): Promise<ShipStationOrderResult> {
    try {
      logger.info("shipstation", "Voiding order in ShipStation", {
        shipstationOrderId,
      })

      const result = await this.request(`/orders/${shipstationOrderId}`, {
        method: "DELETE",
      })

      if (!result.success) {
        logger.error("shipstation", "Failed to void order in ShipStation", {
          shipstationOrderId,
          error: result.error,
          errorDetails: result.errorDetails,
        })
        return {
          success: false,
          error: result.error || "Failed to void order",
          errorDetails: result.errorDetails,
        }
      }

      logger.info("shipstation", "Successfully voided order in ShipStation", {
        shipstationOrderId,
      })

      return {
        success: true,
      }
    } catch (error) {
      logger.error("shipstation", "Unexpected error voiding ShipStation order", {
        shipstationOrderId,
        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 order details from ShipStation
   * Used for debugging and verification
   */
  static async getOrder(shipstationOrderId: string): Promise<{
    success: boolean
    order?: ShipStationOrderResponse
    error?: string
  }> {
    try {
      const result = await this.request<ShipStationOrderResponse>(
        `/orders/${shipstationOrderId}`,
        {
          method: "GET",
        }
      )

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

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




