<?php

namespace App\Services\Integrations\ShipmentTracking;

use App\Models\ApiCredential;
use App\Services\Integrations\ShipmentTracking\FedEx\FedEx;

/** 
 * Service class for tracking the shipment status by using FedEx Api
 */
class FedexTracking extends FedEx implements ShipmentTrackingInterface
{
    private $apiCredential;

    /**
     *  Constructor function for FedexTracking service class. Where setup the SopaClient for calling the api
     */
    public function __construct()
    {
        $this->apiCredential      = ApiCredential::where('slug', 'fedex_tracking')->first();

        parent::__construct('TrackService_v18.wsdl', optional($this->apiCredential)->key, optional($this->apiCredential)->password, optional($this->apiCredential)->account_no, optional($this->apiCredential)->meter_no);

        $this->setEndpoint(optional($this->apiCredential)->url);

        $this->setCustomerTransactionId('Track Request using PHP');

        $this->setVersion('trck', 18, 0, 0);
    }

    /**
     * Get the latest tracking details by tracking number
     *
     * @param $tracking_no   UPS shipment tracking no
     * @return String
     */
    public function getTrackingDetails($trackingNo)
    {
        $shipmentData   = $this->shipmentTrackingDetails($trackingNo);
        $shipmentData   = $this->getPcakageDetails($shipmentData);
        $shipStatus     = $this->shipmentLatestStatus($shipmentData);

        return $shipStatus;
    }

    /**
     *  Gets the tracking detials for the given tracking number and returns the FedEx request as an object.
     *
     *  @param string   // Tracking #
     *  @return SoapClient Object
     */
    public function shipmentTrackingDetails($id)
    {

        $this->request['SelectionDetails'] = array(
            'PackageIdentifier' => array(
                'Type' => 'TRACKING_NUMBER_OR_DOORTAG',
                'Value' => $id
            )
        );

        $this->request = $this->buildRequest($this->request);
        return $this->getSoapClient()->track($this->request);
    }

    /**
     * Some tracking numbers have multiple packages. so we need to check package details to get the shipment status
     *
     * @param array  FedEx tack detail
     * @return SoapClient Object
     */
    public function getPcakageDetails($trackingData)
    {
        $UniqueIdentifier = $this->getTrackingNumberUniqueIdentifier($trackingData);
        if ($UniqueIdentifier) {
            $this->request['SelectionDetails']['TrackingNumberUniqueIdentifier'] = $UniqueIdentifier;

            $this->request = $this->buildRequest($this->request);
            return $this->getSoapClient()->track($this->request);
        }

        return $trackingData;
    }

    /**
     * Taking the latest shipment status from the FedEx api response data
     *
     * @param $trackingData   FedEx API response array
     * @return Array 
     */
    public function shipmentLatestStatus($trackingData)
    {
        if ($trackingData->HighestSeverity == 'SUCCESS') {
            return $trackingData->CompletedTrackDetails ?
                ($trackingData->CompletedTrackDetails->TrackDetails ?
                    (is_array($trackingData->CompletedTrackDetails->TrackDetails) ?
                        null
                        :
                        $this->getStatusDescription($trackingData->CompletedTrackDetails->TrackDetails)
                    )
                    : null)
                : null;
        }
        return null;
    }


    /**
     *  Gets the tracking detials for the given tracking number and returns the FedEx request as an object.
     *
     *  @param string   // Tracking #
     *  @return SoapClient Object
     */
    public function getTrackingDetailsById($id)
    {

        $this->request['SelectionDetails'] = array(
            'PackageIdentifier' => array(
                'Type' => 'TRACKING_NUMBER_OR_DOORTAG',
                'Value' => $id
            )
        );

        $this->request = $this->buildRequest($this->request);
        return $this->getSoapClient()->track($this->request);
    }


    /**
     * Get the latest tracking details by tracking number
     *
     * @param $tracking_no   UPS shipment tracking no
     * @return String
     */
    public function getLatestTrackingDetails($trackingNo)
    {
        $shipmentData   = $this->getTrackingDetailsById($trackingNo);
        $shipmentData   = $this->getPcakageDetails($shipmentData);
        $shipStatus     = $this->getShipmentLatestStatusName($shipmentData);

        return $shipStatus;
    }
}
