<?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\ViisonShippingCommon\Controllers\Backend;

use Shopware\CustomModels\ViisonShippingCommon\Product\DispatchMapping;
use Shopware\Plugins\ViisonCommon\Controllers\ViisonCommonBaseController;
use Shopware\Plugins\ViisonShippingCommon\Classes\PluginInfo;

/**
 * This controller adds some actions called in the shipping backend controller.
 * These actions are responsible for creating, updating and deleting associations
 * between dispatch methods and available dispatch service provider products.
 */
class ViisonShippingCommonShipping extends ViisonCommonBaseController
{
    protected $pluginInfo;

    public function __construct(\Enlight_Controller_Request_Request $request = null, \Enlight_Controller_Response_Response $response = null, PluginInfo $pluginInfo = null)
    {
        parent::__construct($request, $response);
        $this->pluginInfo = $pluginInfo;
    }

    /* Actions */

    /**
     * Gathers all dispatch service provider products and returns them in a list.
     */
    public function getProductsAction()
    {
        // Get all dispatch service provider products
        $productTable = new \Zend_Db_Table($this->pluginInfo->getProductTableName());
        $products = $productTable->fetchAll(
            $productTable->select()
                ->order($this->getProductColumnOrder())
        )->toArray();

        // Cast all values to string which is default before PHP 8.1 and would otherwise be native types in PHP 8.1
        foreach ($products as &$product) {
            $product = array_map(function ($value) {
                return (string) $value;
            }, $product);
        }
        unset($product);

        // Return result
        $this->View()->assign(array(
            'success' => true,
            'data' => $products
        ));
    }

    /**
     * Returns the product mapping of a given dispatch method if it exists.
     */
    public function getDispatchProductMappingAction()
    {
        $dispatchId = $this->Request()->getParam('dispatchId', null);
        if (empty($dispatchId)) {
            $this->View()->assign(array(
                'success' => false,
                'message' => 'No valid dispatch id passed.',
                'params' => $this->Request()->getParams()
            ));

            return;
        }

        $modelName = $this->pluginInfo->getProductDispatchMappingModelName();
        if (!$modelName) {
            /**
             * @deprecated block
             */
            // Try to find product mapping
            $productMappingTable = new \Zend_Db_Table($this->pluginInfo->getProductMappingTableName());
            $mapping = $productMappingTable->fetchAll(
                $productMappingTable->select()
                    ->where('dispatchId = ?', $dispatchId)
            )->toArray();
        } else {
            // Try to find product mapping
            $builder = $this->get('models')->createQueryBuilder();
            $builder
                ->select('mapping')
                ->from($modelName, 'mapping')
                ->where('mapping.dispatchId = :dispatchId')
                ->setParameter('dispatchId', $dispatchId);
            $mapping = $builder->getQuery()->getArrayResult();
        }

        // Return result
        $this->View()->assign(array(
            'success' => true,
            'data' => $mapping
        ));
    }

    /**
     * Creates a new mapping from a given dispatch method to a dispatch service provider product.
     */
    public function createDispatchMappingAction()
    {
        // Get dispatch and product id
        $dispatchId = $this->Request()->getParam('dispatchId');
        $productId = $this->Request()->getParam('productId');
        $exportDocumentRequired = $this->Request()->getParam('exportDocumentRequired');
        if (empty($dispatchId) || $productId === null || $exportDocumentRequired === null) {
            $this->View()->assign(array(
                'success' => false,
                'message' => 'Missing dispatchId and/or export document flag for new mapping.',
                'params' => $this->Request()->getParams()
            ));

            return;
        }

        $customMappingAttributes = $this->getCustomMappingAttributes();
        $customMappingAttributeParams = array();
        foreach ($customMappingAttributes as $attribute) {
            $customMappingAttributeParams[$attribute] = $this->Request()->getParam($attribute);
        }

        $modelName = $this->pluginInfo->getProductDispatchMappingModelName();
        if (!$modelName) {
            /**
             * @deprecated block
             */
            // Create new mapping
            $productMappingTable = new \Zend_Db_Table($this->pluginInfo->getProductMappingTableName());
            $id = $productMappingTable->insert(array_merge(array(
                'productId' => $productId,
                'dispatchId' => $dispatchId,
                'exportDocumentRequired' => $exportDocumentRequired
            ), $customMappingAttributeParams));
        } else {
            // Create new mapping
            $entityManager = $this->get('models');
            $dispatchMapping = new $modelName();
            $dispatchMapping->setDispatch(
                $entityManager->find('Shopware\Models\Dispatch\Dispatch', $dispatchId)
            );
            $dispatchMapping->setProduct(
                $entityManager->find($this->pluginInfo->getProductModelName(), $productId)
            );

            // Set other config values
            $dispatchMapping->setExportDocumentRequired($exportDocumentRequired);
            $dispatchMapping->fromArray($customMappingAttributeParams);

            // Save new mapping
            $entityManager->persist($dispatchMapping);
            $entityManager->flush($dispatchMapping);

            $id = $dispatchMapping->getId();
        }

        // Return result
        $this->View()->assign(array(
            'success' => true,
            'data' => array(
                'id' => $id,
                'productId' => $productId,
                'dispatchId' => $dispatchId,
                'exportDocumentRequired' => $exportDocumentRequired
            )
        ));
    }

    /**
     * Updates the mapping from a given dispatch method to a dispatch service provider product.
     */
    public function updateDispatchMappingAction()
    {
        // Get dispatch and product id
        $dispatchId = $this->Request()->getParam('dispatchId');
        $productId = $this->Request()->getParam('productId');
        $exportDocumentRequired = $this->Request()->getParam('exportDocumentRequired');
        if (empty($dispatchId) || $productId === null || $exportDocumentRequired === null) {
            $this->View()->assign(array(
                'success' => false,
                'message' => 'Missing dispatchId, productId and/or export document flag for the mapping.',
                'params' => $this->Request()->getParams()
            ));

            return;
        }

        $customMappingAttributes = $this->getCustomMappingAttributes();
        $customMappingAttributeParams = array();
        foreach ($customMappingAttributes as $attribute) {
            $customMappingAttributeParams[$attribute] = $this->Request()->getParam($attribute);
        }

        $modelName = $this->pluginInfo->getProductDispatchMappingModelName();
        if (!$modelName) {
            /**
             * @deprecated block
             */
            $productMappingTable = new \Zend_Db_Table($this->pluginInfo->getProductMappingTableName());

            // Update mapping
            $productMappingTable->update(
                array_merge(array(
                    'productId' => $productId,
                    'exportDocumentRequired' => $exportDocumentRequired,
                    'dispatchId' => $dispatchId
                ), $customMappingAttributeParams),
                $productMappingTable->getAdapter()->quoteInto('dispatchId = ?', $dispatchId)
            );

            // Get id
            $id = $productMappingTable->fetchRow(
                $productMappingTable->select()
                    ->from($productMappingTable, 'id')
                    ->where('dispatchId = ?', $dispatchId)
            )->id;
        } else {
            $entityManager = $this->get('models');

            /** @var DispatchMapping $dispatchMapping */
            $dispatchMapping = $entityManager->getRepository($modelName)->findOneBy(array(
                'dispatchId' => $dispatchId
            ));
            $product = $entityManager->find(
                $this->pluginInfo->getProductModelName(),
                $productId
            );

            // Update mapping
            $dispatchMapping->setProduct($product);
            $dispatchMapping->setExportDocumentRequired($exportDocumentRequired);
            $dispatchMapping->fromArray($customMappingAttributeParams);

            // Save changes
            $entityManager->flush($dispatchMapping);

            $id = $dispatchMapping->getId();
        }

        // Return result
        $this->View()->assign(array(
            'success' => true,
            'data' => array(
                'id' => $id,
                'productId' => $productId,
                'dispatchId' => $dispatchId,
                'exportDocumentRequired' => $exportDocumentRequired
            )
        ));
    }

    /**
     * Deletes a mapping from a given dispatch method to a dispatch service provider product.
     */
    public function destroyDispatchMappingAction()
    {
        // Get dispatch and product id
        $dispatchId = $this->Request()->getParam('dispatchId');
        if (!isset($dispatchId)) {
            $this->View()->assign(array(
                'success' => false,
                'message' => 'Missing dispatchId.',
                'params' => $this->Request()->getParams()
            ));

            return;
        }

        $modelName = $this->pluginInfo->getProductDispatchMappingModelName();
        if (!$modelName) {
            // Remove any mappings
            $productMappingTable = new \Zend_Db_Table($this->pluginInfo->getProductMappingTableName());
            $productMappingTable->delete($productMappingTable->getAdapter()->quoteInto('dispatchId = ?', $dispatchId));
        } else {
            $entityManager = $this->get('models');
            $dispatchMapping = $entityManager->getRepository($modelName)->findOneBy(array(
                'dispatchId' => $dispatchId
            ));
            if ($dispatchMapping) {
                $entityManager->remove($dispatchMapping);
                $entityManager->flush($dispatchMapping);
            }
        }

        // Return result
        $this->View()->assign(array(
            'success' => true,
            'data' => array()
        ));
    }

    /**
     * @return array The columns of the product table that should be used for the ordering of the products (e.g. in comboboxes where a product can be chosen).
     */
    protected function getProductColumnOrder()
    {
        return array();
    }

    /**
     * @return array
     */
    protected function getCustomMappingAttributes()
    {
        return array();
    }
}
