<?php
declare(strict_types=1);

namespace Leadlion\SalesOrder\Controller\Adminhtml\Order;

use Eadesigndev\Awb\Model\Sources\CarrierType;
use Magento\Framework\Controller\ResultFactory;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Backend\App\Action;
use Magento\Framework\Exception\LocalizedException;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory as SalesCollectionFactory;
use Leadlion\SalesOrder\Model\Config;
use Magento\Framework\App\Area;
use Magento\Sales\Model\Order;
use Magento\Backend\Model\View\Result\Redirect;
use Magento\Framework\App\Response\Http\FileFactory;
use SmartBill\Integration\Model\ResourceModel\Invoice\CollectionFactory as InvoiceCollectionFactory;
use Eadesigndev\Awb\Model\ResourceModel\Collection\CollectionFactory as AwbCollectionFactory;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\Filesystem;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\App\RequestInterface;
use Eadesigndev\Urgent\Model\Carrier\Carrier as ConnectUrgent;
use Eadesigndev\FanCourier\Helper\Data as ConnectFanCourier;
use Eadesigndev\GLS\Helper\Data as ConnectGLS;
use Eadesigndev\DPD\Helper\Data as ConnectDPD;
use Eadesigndev\DragonStar\Helper\Api as ConnectDragonStar;
use Eadesigndev\NemoExpress\Helper\Data as ConnectNemoExpress;
use Eadesigndev\Sameday\Helper\Data as ConnectSameday;
use Eadesigndev\Awb\Model\AwbRepository;

class MassDownload extends Action
{

    const ARCHIVE_FILENAME = 'Facturi.zip';

    /**
     * @var Filter
     */
    protected $filter;

    /**
     * @var salesCollectionFactory
     */
    protected $salesCollectionFactory;

    /**
     * @var Config
     */
    protected $config;

    /**
     * @var FileFactory
     */
    protected $fileFactory;

    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var InvoiceCollectionFactory
     */
    private $invoiceCollectionFactory;

    /**
     * @var Filesystem
     */
    protected $filesystem;

    /**
     * @var OrderRepositoryInterface
     */
    protected $orderRespository;
    private  $carrierType;
    private  $connectUrgent;
    private  $connectFanCourier;
    private  $connectGLS;
    private  $connectDPD;
    private  $connectDragonStar;
    private  $connectNemoExpress;
    private  $request;
    private  $awbRepository;
    private  $awbCollectionFactory;
    private $awbFilesPathArray = [];
    /**
     * @var \Magento\Framework\App\Filesystem\DirectoryList
     */
    private $directory;
    /**
     * @var ConnectSameday
     */
    private $connectSameday;

    /**
     * @param Context $context
     * @param Filter $filter
     * @param Config $config
     * @param SalesCollectionFactory $salesCollectionFactory
     * @param FileFactory $fileFactory
     * @param StoreManagerInterface $storeManager
     * @param InvoiceCollectionFactory $invoiceCollectionFactory
     * @param Filesystem $filesystem
     * @param \Magento\Framework\App\Filesystem\DirectoryList $directory
     * @param OrderRepositoryInterface $orderRespository
     * @param CarrierType $carrierType
     * @param ConnectUrgent $connectUrgent
     * @param ConnectFanCourier $connectFanCourier
     * @param ConnectGLS $connectGLS
     * @param ConnectDPD $connectDPD
     * @param ConnectDragonStar $connectDragonStar
     * @param ConnectNemoExpress $connectNemoExpress
     * @param ConnectSameday $connectSameday
     * @param RequestInterface $request
     * @param AwbRepository $awbRepository
     * @param AwbCollectionFactory $awbCollectionFactory
     */
    public function __construct(
        Context $context,
        Filter $filter,
        Config $config,
        SalesCollectionFactory $salesCollectionFactory,
        FileFactory $fileFactory,
        StoreManagerInterface $storeManager,
        InvoiceCollectionFactory $invoiceCollectionFactory,
        Filesystem $filesystem,
        \Magento\Framework\App\Filesystem\DirectoryList $directory,
        OrderRepositoryInterface $orderRespository,
        CarrierType $carrierType,
        ConnectUrgent $connectUrgent,
        ConnectFanCourier $connectFanCourier,
        ConnectGLS $connectGLS,
        ConnectDPD $connectDPD,
        ConnectDragonStar $connectDragonStar,
        ConnectNemoExpress $connectNemoExpress,
        ConnectSameday $connectSameday,
        RequestInterface $request,
        AwbRepository $awbRepository,
        AwbCollectionFactory $awbCollectionFactory
    ) {
        $this->filter = $filter;
        $this->config = $config;
        $this->salesCollectionFactory = $salesCollectionFactory;
        $this->fileFactory = $fileFactory;
        $this->storeManager = $storeManager;
        $this->invoiceCollectionFactory = $invoiceCollectionFactory;
        $this->filesystem = $filesystem;
        $this->directory = $directory;
        $this->orderRespository = $orderRespository;
        $this->carrierType = $carrierType;
        $this->connectUrgent = $connectUrgent;
        $this->connectFanCourier = $connectFanCourier;
        $this->connectGLS = $connectGLS;
        $this->connectDPD = $connectDPD;
        $this->connectDragonStar = $connectDragonStar;
        $this->connectNemoExpress = $connectNemoExpress;
        $this->connectSameday = $connectSameday;
        $this->request = $request;
        $this->awbRepository = $awbRepository;
        $this->awbCollectionFactory = $awbCollectionFactory;
        parent::__construct($context);
    }

    /**
     * Execute action
     *
     * @return Redirect
     * @throws LocalizedException
     */
    public function execute()
    {
        $countDownloads = $filePath = $documentUrl = $fileName = $orderObj = 0;
        $collection = $this->filter->getCollection($this->salesCollectionFactory->create());

        $varPath = $this->filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR)->getAbsolutePath();
        $zipArchive = new \ZipArchive();
        $zipArchive->open($varPath . self::ARCHIVE_FILENAME, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

        /** @var Order $order */
        foreach ($collection->getItems() as $order) {
            $orderId = $order->getEntityId();
            $orderIncrementId = $order->getIncrementId();
            $smartbillObj = $this->invoiceCollectionFactory->create()->getItemByColumnValue('order_id', $orderId);
            /** @var \Magento\Sales\Model\ResourceModel\Order\Shipment\Collection $shipmentCollection */
            $shipmentCollection = $order->getShipmentsCollection();
            /** @var \Magento\Sales\Model\Order\Shipment $shipment */
            $shipment = $order->getShipmentsCollection()->getFirstItem();
            if (isset($smartbillObj)) {
                $documentUrl = $smartbillObj->getData('smartbill_document_url');
                $docRelPath = ltrim($documentUrl, '/');
                $filePath = $this->directory->getPath("var") . '/' . dirname($docRelPath);
                $fileName = basename($documentUrl);
            }


            if(isset($shipment)) {
                $awbObject = $this->awbCollectionFactory->create()->getItemByColumnValue('awb_number', $order->getData('awb_number'));
                if($awbObject) {
                    $awbId = $awbObject->getData('entity_id');
                    $awbNumber = $awbObject->getData('awb_number');
                    $pickupId = null;
                    $carrierId = $awbObject->getData('carrier_id');
                    $awbModel = $this->awbRepository->getById($awbId);
                    if (!empty($awbModel->getData('awb_pickup_id'))) {
                        $pickupId = $awbModel->getData('awb_pickup_id');
                    }

                    $this->addAwbToArchive(
                        ['media_path' => $varPath, 'dirname' => $orderIncrementId, 'tmp_filename' => 'AWB_' . $order->getId() . ".pdf"],
                        $zipArchive,
                        $carrierId,
                        $awbNumber,
                        $pickupId
                    );
                }
            }

            $zipArchive->addEmptyDir($orderIncrementId);

            if (!empty($fileName)) {
                $currentFile = $filePath . "/" . $fileName;
                $zipPath =$orderIncrementId . "/" . $fileName;
                if(is_file($currentFile) && file_exists($currentFile)) {
                    $zipArchive->addFile($currentFile, $zipPath);
                }
                $orderObj = $this->orderRespository->get($orderId);
                $orderObj->setStatus(Order::STATE_COMPLETE);
                $orderObj->setState(Order::STATE_COMPLETE);
                $orderObj->save();
                $countDownloads++;
            }
        }
        $zipArchive->close();
        $this->removeTempFiles();

        $countNonDownloads = $collection->count() - $countDownloads;

        if ($countNonDownloads && $countDownloads) {
            $this->messageManager->addErrorMessage(__('%1 order(s) were not downloaded.', $countNonDownloads));
        } elseif ($countNonDownloads) {
            $this->messageManager->addErrorMessage(__('No order(s) were downloaded'));
        }

        if ($countDownloads) {
            $this->messageManager->addSuccessMessage(__('A total of %1 order(s) downloaded successfully.', $countDownloads));
        }

        $this->fileFactory->create(
            self::ARCHIVE_FILENAME,
            [
                'type' => 'filename',
                'value' => self::ARCHIVE_FILENAME,
                'rm' => true
            ],
            \Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR,
            'application/zip'
        );

        $resultRaw = $this->resultRawFactory->create();
        $resultRaw->setContents($fileName);
        return $resultRaw;
    }

    protected function addAwbToArchive($fileData, &$zipArchive, $carrierId, $identifier, $pickupId) {
        $carrierConnector = null;
        if ($carrierId >= 0) {
            switch ($carrierId)
            {
                case CarrierType::URGENT_CURRIER:
                    $carrierConnector = $this->connectUrgent;
                    break;
                case CarrierType::FAN_CURRIER:
                    $carrierConnector = $this->connectFanCourier;
                    break;
                case CarrierType::DPD:
                    $carrierConnector = $this->connectDPD;
                    break;
                case CarrierType::GLS:
                    $carrierConnector = $this->connectGLS;
                    break;
                case CarrierType::DRAGON_STAR:
                    $carrierConnector = $this->connectDragonStar;
                    break;
                case CarrierType::NEMO_EXPRESS:
                    $carrierConnector = $this->connectNemoExpress;
                    break;
                case CarrierType::SAMEDAY:
                    $carrierConnector =  $this->connectSameday;
                    break;
            }
        }
        if (method_exists($carrierConnector, 'getAwbDocument')) {
            $response = $carrierConnector->getAwbDocument($identifier, $pickupId);
            $fileAbsPath = $fileData['media_path'] . "/" . $fileData['tmp_filename'];
            $zipPath = $fileData['dirname']."/".$fileData['tmp_filename'];
            file_put_contents($fileAbsPath, $response);
            if(is_file($fileAbsPath) && file_exists($fileAbsPath)) {
                $this->addFileToArchive(
                    $zipArchive,
                    $fileAbsPath,
                    $zipPath
                );
            }
            $this->awbFilesPathArray[] = $fileAbsPath;
        }
    }

    protected function addFileToArchive(&$archive, $filePath, $entryName) {
        $archive->addFile($filePath, $entryName);
    }

    protected function removeTempFiles() {
        foreach($this->awbFilesPathArray as $filePath) {
            if(is_file($filePath) && file_exists($filePath)) {
                unlink($filePath);
            }
        }
        $this->awbFilesPathArray = [];
    }
}

