import {
  ShippingProviderContract,
  ShipmentResult,
  TrackingResult,
  RateResult,
} from './shipping_interface.js'
import Order from '#models/order'
import shippingConfig from '#config/shipping'
import logger from '@adonisjs/core/services/logger'
import {
  getNextBusinessDateBH,
  mapDhlRates,
  normalizeCity,
  resolveBahrainPostalCode,
  // resolveDhlCity,
} from '../../Helper/Helper.js'
import InternationalOrder from '#models/international_order'
import { DateTime } from 'luxon'
import { TimeZone } from '../../../types/enum.js'

export default class DHLService implements ShippingProviderContract {
  private config = shippingConfig.dhl

  private getAuthHeader() {
    const credentials = `${this.config.username}:${this.config.password}`
    return `Basic ${Buffer.from(credentials).toString('base64')}`
  }

  async createShipment(order: Order): Promise<ShipmentResult> {
    try {
      const payload = this.prepareShipmentPayload(order, order?.international_order_details)
      const response = await fetch(`${this.config.baseUrl}/shipments`, {
        method: 'POST',
        headers: {
          'Authorization': this.getAuthHeader(),
          'Content-Type': 'application/json',
          'Message-Reference': `ORDER-${order.id}`,
          'Message-Reference-Date': new Date().toISOString(),
        },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const errorBody = await response.text()
        logger.error({ errorBody }, 'DHL Create Shipment Failed')
        throw new Error(`DHL API Error: ${response.statusText}`)
      }

      const data: any = await response.json()
      // Assuming standard MyDHL API response structure
      // Adjust based on actual response
      const shipmentId = data.shipmentTrackingNumber
      const labelData = data.documents?.[0]?.content // Base64 label
      console.log(data, 'data')
      return {
        trackingNumber: shipmentId,
        labelData: labelData,
        provider: 'DHL',
        cost: data.totalNet?.amount,
        currency: data.totalNet?.currency,
        apiResponse: data,
      }
    } catch (error) {
      logger.error(error, 'DHL Create Shipment Error')
      throw error
    }
  }

  async trackShipment(trackingNumber: string): Promise<TrackingResult> {
    try {
      const response = await fetch(`${this.config.baseUrl}/shipments/${trackingNumber}/tracking`, {
        method: 'GET',
        headers: {
          Authorization: this.getAuthHeader(),
          Accept: 'application/json',
        },
      })

      if (!response.ok) {
        throw new Error(`DHL Tracking Failed: ${response.statusText}`)
      }

      const data: any = await response.json()
      const shipment = data.shipments?.[0]

      return {
        trackingNumber: trackingNumber,
        status: shipment?.status?.statusCode || 'UNKNOWN',
        history:
          shipment?.events?.map((event: any) => ({
            status: event.statusCode,
            location: event.location?.address?.addressLocality,
            timestamp: event.timestamp,
            description: event.description,
          })) || [],
      }
    } catch (error) {
      logger.error(error, 'DHL Track Shipment Error')
      throw error
    }
  }

  async cancelShipment(_trackingNumber: string): Promise<boolean> {
    // DHL API might not support direct cancellation via API for all accounts
    // or it might be a different endpoint.
    // For now, returning false or implementing if endpoint is known.
    // Usually DELETE /shipments/{trackingNumber} if within window
    return false
  }

  async generateLabel(_trackingNumber: string): Promise<string> {
    return ''
  }

  async calculateRate(order: Order): Promise<RateResult> {
    try {
      const payload = this.prepareRatePayload(order)
      const response = await fetch(`${this.config.baseUrl}/rates`, {
        method: 'POST',
        headers: {
          'Authorization': this.getAuthHeader(),
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const errorBody = await response.text()
        logger.error({ errorBody }, 'DHL Calculate Rate Failed')
        throw new Error(`DHL Rate Error: ${response.statusText}`)
      }

      const data: any = await response.json()
      const product = data.products?.[0] // Get the first product or filter by preferred

      if (!product) {
        throw new Error('No rates found')
      }

      return {
        amount: product.totalPrice?.[0]?.price,
        currency: product.totalPrice?.[0]?.currencyType,
        provider: 'DHL',
        serviceName: product.productName,
        estimatedDeliveryDate: product.deliveryCapabilities?.estimatedDeliveryDateAndTime,
      }
    } catch (error) {
      logger.error(error, 'DHL Calculate Rate Error')
      throw error
    }
  }

  private prepareRatePayload(order: Order) {
    return {
      customerDetails: {
        shipperDetails: {
          postalCode: '12345', // Needs to come from order/config
          cityName: 'Manama',
          countryCode: 'BH',
        },
        receiverDetails: {
          postalCode: '54321', // Needs to come from order
          cityName: 'Riyadh', // Needs to come from order
          countryCode: 'SA', // Needs to come from order
        },
      },
      accounts: [
        {
          typeCode: 'shipper',
          number: this.config.accountNumber,
        },
      ],
      productCode: 'P',
      plannedShippingDateAndTime: new Date().toISOString(),
      unitOfMeasurement: 'metric',
      isCustomsDeclarable: true,
      monetaryAmount: [
        {
          typeCode: 'declaredValue',
          value: 10, // Placeholder
          currency: 'USD',
        },
      ],
      packages: order.order_package_list.map((pkg) => ({
        weight: pkg.weight,
        dimensions: {
          length: 10,
          width: 10,
          height: 10,
        },
      })),
    }
  }

  async calculateInternationalRate(details: {
    width: number
    length: number
    originCity: string
    originCountry: string
    originPostalCode?: string
    destinationCity: string
    destinationCountry: string
    destinationPostalCode?: string
    weight: number
    numberOfPieces: number
    productGroup?: string
    productType?: string
  }): Promise<RateResult> {
    try {
      // const payload = {
      //   customerDetails: {
      //     shipperDetails: {
      //       postalCode: '317', // Bahrain test postal
      //       cityName: 'Manama',
      //       countryCode: 'BH',
      //     },
      //     receiverDetails: {
      //       postalCode: '691001', // Thiruvananthapuram PIN
      //       cityName: 'Thiruvananthapuram',
      //       countryCode: 'IN',
      //     },
      //   },

      //   accounts: [
      //     {
      //       typeCode: 'shipper',
      //       number: this.config.accountNumber, // Your DHL account
      //     },
      //   ],

      //   payerCountryCode: 'BH', // REQUIRED

      //   plannedShippingDateAndTime: new Date().toISOString(),

      //   unitOfMeasurement: 'metric',

      //   isCustomsDeclarable: true,

      //   monetaryAmount: [
      //     {
      //       typeCode: 'declaredValue',
      //       value: 100,
      //       currency: 'USD',
      //     },
      //   ],

      //   packages: [
      //     {
      //       typeCode: '3BX', // ✅ Must be 3 chars minimum
      //       weight: 5, // KG
      //       dimensions: {
      //         length: 10,
      //         width: 10,
      //         height: 10,
      //       },
      //     },
      //   ],
      // }
      // const originCityDhl = resolveDhlCity(details.originCity)
      // const originCityDhl = 'AL HIDD'
      // const originPostalCode =
      //   details.originPostalCode ||
      //   (details.originCountry === 'BH' ? resolveBahrainPostalCode(details.originCity) : '') ||
      //   'AL HIDD'
      const originCityDhl = 'AL HIDD'
      const originPostalCode = resolveBahrainPostalCode(originCityDhl)
      console.log({
        shipperDetails: {
          cityName: originCityDhl, // DHL safe
          countryCode: details.originCountry,
          postalCode: originPostalCode, // NEVER empty for BH
        },
        receiverDetails: {
          cityName: normalizeCity(details.destinationCity),
          countryCode: details.destinationCountry,
          postalCode: details.destinationPostalCode || '695001',
        },
      })
      const payload = {
        customerDetails: {
          shipperDetails: {
            cityName: originCityDhl, // DHL safe
            countryCode: details.originCountry,
            postalCode: originPostalCode, // NEVER empty for BH
          },
          receiverDetails: {
            cityName: normalizeCity(details.destinationCity),
            countryCode: details.destinationCountry,
            postalCode: details.destinationPostalCode || '695001',
          },
        },
        // customerDetails: {
        //   shipperDetails: {
        //     cityName: details.originCity,
        //     countryCode: details.originCountry,
        //     postalCode: details.originPostalCode || '',
        //   },
        //   receiverDetails: {
        //     cityName: details.destinationCity,
        //     countryCode: details.destinationCountry,
        //     postalCode: details.destinationPostalCode || '',
        //   },
        // },
        accounts: [
          {
            typeCode: 'shipper',
            number: this.config.accountNumber,
          },
        ],

        payerCountryCode: 'BH', // REQUIRED

        // plannedShippingDateAndTime: new Date().toISOString(),
        plannedShippingDateAndTime: getNextBusinessDateBH(),

        unitOfMeasurement: 'metric',

        isCustomsDeclarable: true,

        monetaryAmount: [
          {
            typeCode: 'declaredValue',
            value: 100,
            currency: 'BHD',
          },
        ],

        packages: [
          {
            typeCode: '3BX', // ✅ Must be 3 chars minimum
            weight: details?.weight ?? 0, // KG
            dimensions: {
              length: details?.length ?? 0,
              width: details?.width ?? 0,
              height: details?.weight ?? 0,
            },
          },
        ],
      }
      const response = await fetch(`${this.config.baseUrl}/rates`, {
        method: 'POST',
        headers: {
          'Authorization': this.getAuthHeader(),
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const errorBody = await response.text()
        logger.error({ errorBody }, 'DHL Calculate International Rate Failed')
        throw new Error(`DHL Rate Error: ${errorBody}`)
      }

      const data: any = await response.json()
      const product = data.products

      if (!product?.length) {
        throw new Error('No rates found from DHL')
      }
      const rates = mapDhlRates(data)
      return rates
    } catch (error) {
      logger.error(error, 'DHL Calculate International Rate Error')
      throw error
    }
  }

  private prepareShipmentPayload(order: Order, internationalOrder: InternationalOrder) {
    return {
      plannedShippingDateAndTime: DateTime.now()
        .setZone(TimeZone)
        .toFormat("yyyy-MM-dd'T'HH:mm:ss 'GMT'ZZ"),

      pickup: {
        isRequested: false,
      },

      productCode: internationalOrder?.product_type || 'D',

      accounts: [
        {
          typeCode: 'shipper',
          number: this.config.accountNumber,
        },
      ],

      customerDetails: {
        shipperDetails: {
          postalAddress: {
            addressLine1: internationalOrder.shipper_address || 'Address',
            cityName: internationalOrder.shipper_city || 'Manama',
            postalCode: internationalOrder.shipper_postal_code || '00000',
            countryCode: internationalOrder.shipper_country_details?.short_code || 'BH',
          },
          contactInformation: {
            fullName:
              internationalOrder.shipper_name ||
              internationalOrder.shipper_company_name ||
              'Shipper',
            companyName:
              internationalOrder.shipper_company_name ||
              internationalOrder.shipper_name ||
              'Shipper',
            phone: internationalOrder.shipper_phone || '+97333333333',
          },
        },

        receiverDetails: {
          postalAddress: {
            addressLine1: internationalOrder.recipient_address || 'Address',
            cityName: internationalOrder.recipient_city || 'City',
            postalCode: internationalOrder.recipient_postal_code || '00000',
            countryCode: internationalOrder.recipient_country_details?.short_code || 'BH',
          },
          contactInformation: {
            fullName: internationalOrder.recipient_name || 'Receiver',
            companyName:
              internationalOrder.recipient_company_name ||
              internationalOrder.recipient_name ||
              'Receiver',
            phone:
              internationalOrder.recipient_phone ||
              internationalOrder.recipient_mobile ||
              '+97333333333',
          },
        },
      },

      content: {
        description: internationalOrder?.description || 'Merchandise',

        isCustomsDeclarable: false,
        incoterm: 'DAP',
        unitOfMeasurement: 'metric',

        declaredValue: Number(internationalOrder.customs_value || 1),

        declaredValueCurrency: internationalOrder.currency || 'BHD',

        packages:
          order.order_package_list?.length > 0
            ? order.order_package_list.map((pkg) => ({
                weight: Number(pkg?.weight) > 0 ? Number(pkg.weight) : 0,

                dimensions: {
                  length: Number(pkg?.length) > 0 ? Number(pkg.length) : 0,
                  width: Number(pkg?.width) > 0 ? Number(pkg.width) : 0,
                  height: Number(pkg?.height) > 0 ? Number(pkg.height) : 0,
                },
              }))
            : [
                {
                  weight: Number(order.total_weight || 0),
                  dimensions: {
                    length: 0,
                    width: 0,
                    height: 0,
                  },
                },
              ],
      },
    }
  }
}
