<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonPickwareMobile\Classes\ShippingProvider;

use Doctrine\DBAL\Connection as DBALConnection;
use \ViisonPickwareMobile_Interfaces_ShippingProvider_ShippingProvider as ShippingProviderInterface;

class ShippingProvider implements ShippingProviderInterface
{
    /**
     * @var \Doctrine\DBAL\Connection $dbalConnection
     */
    private $dbalConnection;

    /**
     * @var \Enlight_Config $pluginConfig
     */
    private $pluginConfig;

    /**
     * @param \Doctrine\DBAL\Connection $dbalConnection
     * @param \Enlight_Config $pluginConfig
     */
    public function __construct(DBALConnection $dbalConnection, \Enlight_Config $pluginConfig)
    {
        $this->dbalConnection = $dbalConnection;
        $this->pluginConfig = $pluginConfig;
    }

    public function getName()
    {
        return 'Fremde Versandarten';
    }

    public function getIdentifier()
    {
        return 'ViisonPickwareMobile_PseudoShippingProvider';
    }

    public function addLabelToOrder($orderId, $shippingProductIdentifier = null, $weight = null, $dimensions = null, $options = [], $exportDocumentItems = null, $address = null)
    {
        // Do nothing here and just return a result without any documents
        return new ShippingLabelCreationResult();
    }

    public function getDocument($orderId, $identifier)
    {
        // Do nothing here and just throw an exception, because third party
        // shipping providers don't have any documents yet.
        throw new \Exception('Unsupported method.');
    }

    public function getAllDocumentDescriptions($orderId, $undispatchedOnly = false)
    {
        // Do nothing here and just return no documents
        return [];
    }

    public function hasCreatedDocumentWithIdentifier($identifier)
    {
        // Documents are not yet supported
        return false;
    }

    public function hasCreatedTrackingCode($trackingCode)
    {
        // This shipping provider doesn't create any tracking codes
        return false;
    }

    public function getOrderIdForTrackingCode($trackingCode)
    {
        return null;
    }

    public function getOrdersIdsForTrackingCodeFragment($trackingCodeFragment)
    {
        return [];
    }

    public function isShippingSupported($orderId)
    {
        // Get the IDs of associated dispatch methods
        $dispatchMethodIds = $this->pluginConfig->toArray()['pickingAppThirdPartyDispatchMethodIds'];
        if (count($dispatchMethodIds) === 0) {
            return false;
        }

        // Get the dispatch method of the order
        $orderDispatchId = $this->dbalConnection->fetchColumn(
            'SELECT dispatchID
            FROM s_order
            WHERE id = ?',
            [
                $orderId
            ]
        );

        // Compare the IDs
        return in_array($orderDispatchId, $dispatchMethodIds);
    }

    public function determineShipmentWeight($orderId, $orderDetails = null)
    {
        // Get the weight and quantity of all articles of this order. An item's weight is always at least 0.1kg:
        // * If it's not defined (0.0 as it's a DECIMAL column or NULL)
        // * The actual article was deleted (all details are gone, therefore NULL)
        // * The weight is below 0.1kg (since that's the minimum when submitting an export document)
        $result = $this->dbalConnection->fetchAll(
            'SELECT o.id AS detailId, o.quantity AS quantity, GREATEST(IFNULL(a.weight, 0), 0.1) as weight
            FROM s_order_details o
            LEFT JOIN s_articles_details a
            ON o.articleID = a.articleID
            AND o.articleordernumber = a.ordernumber
            WHERE o.orderID = ?
            AND o.esdarticle = 0',
            [
                $orderId
            ]
        );

        // Calculate the total weight
        $weight = 0.0;
        foreach ($result as $row) {
            $detailId = $row['detailId'];
            if ($orderDetails !== null && $orderDetails[$detailId] === null) {
                // Current item shall not be contained in the result
                continue;
            }

            // Add the weight of the current item
            $quantity = ($orderDetails !== null) ? $orderDetails[$detailId] : $row['quantity'];
            $weight += floatval($quantity) * floatval($row['weight']);
        }

        return round($weight, 3);
    }

    public function packageDimensionsRequired($orderId)
    {
        return false;
    }

    public function validDispatchIds()
    {
        // Get the dispatch IDs associated with this plugin
        return $this->pluginConfig->toArray()['pickingAppThirdPartyDispatchMethodIds'];
    }

    public function shippingProducts()
    {
        // Third party dispatch methods don't support specific products yet
        return [];
    }

    public function shippingProductIdentifierForOrder($orderId)
    {
        // Third party dispatch methods don't support specific products yet
        return null;
    }

    public function shippingProductOptionsForOrder($orderId)
    {
        // Since there are no products, there are also no options
        return [];
    }

    /**
     * @inheritdoc
     */
    public function statusUrlsForTrackingCodes($trackingCodes)
    {
        // This provider doesn't provide any status URLs
        return [];
    }

    /**
     * @inheritdoc
     */
    public function getAvailableShippingDocumentTypes()
    {
        return [];
    }
}
