<?php

namespace domain\Distribution\Distribution\Export;

use domain\Distribution\Distribution\Distribution;
use domain\Feature\Feature\Feature;
use domain\Feature\Feature\FeatureChecker;
use domain\Order\Order\Order;
use domain\Order\Order\OrderBuilder;
use domain\Order\Order\OrderRepository;
use domain\Order\Order\OrderSolver;
use domain\Producer\Producer\ProducerSolver;
use kartik\mpdf\Pdf;
use domain\_\AbstractGenerator;
use yii\base\ErrorException;

class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
    const FORMAT_70_42 = '70x42';

    protected ProducerSolver $producerSolver;
    protected OrderRepository $orderRepository;
    protected OrderSolver $orderSolver;
    protected FeatureChecker $featureChecker;
    protected OrderBuilder $orderBuilder;

    public function loadDependencies(): void
    {
        $this->producerSolver = $this->loadService(ProducerSolver::class);
        $this->orderRepository = $this->loadService(OrderRepository::class);
        $this->orderSolver = $this->loadService(OrderSolver::class);
        $this->featureChecker = $this->loadService(FeatureChecker::class);
        $this->orderBuilder = $this->loadService(OrderBuilder::class);
    }

    public function getSpecificFormatDetailsArray(): array
    {
        return [
            self::FORMAT_70_42 => [70, 42]
        ];
    }

    public function generate(Distribution $distribution, bool $save = false)
    {
        $isSpecificFormat = false;
        $exportShoppingCartLabelsFormat = $this->producerSolver->getConfig('export_shopping_cart_labels_format');
        if($this->featureChecker->isEnabled(Feature::ALIAS_EXPORT_SHOPPING_CART_LABELS_ADVANCED)) {
            if($exportShoppingCartLabelsFormat) {
                $isSpecificFormat = true;
                [$specificFormatWidth, $specificFormatHeight] = $this->getSpecificFormatDetails($exportShoppingCartLabelsFormat);
            }
            else {
                throw new ErrorException("Aucun format d'étiquette n'est défini dans les paramètres.");
            }
        }

        $ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);
        $ordersArray = $this->filterOrdersExcludedUsersAndPointSales($ordersArray);

        foreach($ordersArray as $order) {
            $this->orderBuilder->initOrder($order);
        }

        $content = \Yii::$app->getView()->render('@backend/views/distribution/shopping-cart-labels.php', [
            'distribution' => $distribution,
            'ordersArray' => $ordersArray,
            'isSpecificFormat' => $isSpecificFormat,
            'shoppingCartLabelsPerColumn' => $this->producerSolver->getConfig('export_shopping_cart_labels_number_per_column') ?: 8
        ]);

        if($isSpecificFormat) {
            $pdf = $this->getPdf($distribution, $content, true, $specificFormatWidth, $specificFormatHeight);
        }
        else {
            $pdf = $this->getPdf($distribution, $content, false);
            $pdf->getApi()->SetColumns(4);
            $pdf->getApi()->keepColumns = true;
        }

        return $pdf->render();
    }

    public function getPdf(Distribution $distribution, string $content, bool $isSpecificFormat, float $specificFormatWidth = 0, float $specificFormatHeight = 0)
    {
        return new Pdf([
            'mode' => Pdf::MODE_UTF8,
            'format' => Pdf::FORMAT_A4,
            'orientation' => Pdf::ORIENT_PORTRAIT,
            'destination' => Pdf::DEST_BROWSER,
            'filename' => \Yii::getAlias(
                '@app/web/pdf/Etiquettes-' . $distribution->date . '-' . $this->getProducerContextId() . '.pdf'
            ),
            'content' => $content,
            'cssInline' => $this->getCss($isSpecificFormat, $specificFormatWidth, $specificFormatHeight),
        ]);
    }

    public function filterOrdersExcludedUsersAndPointSales(array $ordersArray)
    {
        $ordersArrayFilter = [];

        foreach($ordersArray as $order) {
            if(!$this->isOrderUserExcludeExport($order)
                && !$this->isOrderPointSaleExcludeExport($order)) {
                $ordersArrayFilter[] = $order;
            }
        }

        return $ordersArrayFilter;
    }

    public function isOrderUserExcludeExport(Order $order): bool
    {
        return $order->user && $order->user->exclude_export_shopping_cart_labels;
    }

    public function isOrderPointSaleExcludeExport(Order $order): bool
    {
        return $order->pointSale && $order->pointSale->exclude_export_shopping_cart_labels;
    }

    public function getCss(bool $isSpecificFormat = false, float $specificFormatWidth = 0, float $specificFormatHeight = 0): string
    {
        $css = '
            @page {
              margin: 0px 0px 0px 0px !important;
              padding: 0px 0px 0px 0px !important;
            }
            
            body {
              font-family: Arial, Helvetica, sans-serif;
              font-size: 13px;
            }
            
            .shopping-cart-label .username {
                font-weight: bold;
                font-size: 16px;
            }
            
            .shopping-cart-label .point-sale {
                font-size: 10px;
                line-height: 12px;
                text-transform: uppercase;
                margin-bottom: 3px;
            }
            
            .shopping-cart-label .products {
                 font-size: 10px;
            }';

        if($isSpecificFormat) {
            $paddingWidthShoppingCartLabel = 8;
            $paddingHeightShoppingCartLabel = 5;
            $specificFormatWidth = $specificFormatWidth - 2 * $paddingWidthShoppingCartLabel;
            $specificFormatHeight = $specificFormatHeight - 2 * $paddingHeightShoppingCartLabel + 1;

            $css .= '
            .shopping-cart-label {
                box-sizing: border-box;
                padding-top: '.$paddingHeightShoppingCartLabel.'mm;
                padding-bottom: '.$paddingHeightShoppingCartLabel.'mm;
                padding-left: '.$paddingWidthShoppingCartLabel.'mm;
                padding-right: '.$paddingWidthShoppingCartLabel.'mm;
                width: '.$specificFormatWidth.'mm;
                height: '.$specificFormatHeight.'mm;
                display: block;
                float: left;
            }
            
            .shopping-cart-label .amount-and-payment {
                margin-top: 8px;
                font-size: 10px;
                /*border-top: dotted 1px gray;*/
            }
            
            .shopping-cart-label .amount-and-payment .amount {
                display: inline-block; 
                background-color: #e0e0e0;
                color: #333;
                font-weight: bold;
                padding: 3px 8px;
                border-radius: 8px;
            }';
        }
        else {
            $css .= '
            .shopping-cart-label {
                -webkit-column-break-inside:avoid;
                column-break-inside: avoid;
                -webkit-page-break-inside:avoid;
                page-break-inside: avoid;
            }
            
            .shopping-cart-label .inner {
                   padding: 8px;
            }
            ';
        }

        return $css;
    }

    public function getShoppingCartLabelAsHtml(Order $order, int $index, bool $isSpecificFormat): string
    {
        $amountAndPayment = '';
        if($isSpecificFormat) {
            $amountAndPayment = '<div class="amount-and-payment">';
            $amountAndPayment .= '<span class="amount">'.$this->orderSolver->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL, true).'</span>';

            $paymentLabelPaid = $this->orderRepository->getPaymentLabelPaid($order);
            if($paymentLabelPaid && strlen($paymentLabelPaid)) {
                $amountAndPayment .= ' / '.$paymentLabelPaid;
            }
            $amountAndPayment .= '</div>';
        }

        return '<div class="shopping-cart-label shopping-cart-label-'.$index.'">
            <div class="inner">
                <div class="username">
                    '.$this->orderSolver->getOrderUsername($order).'
                </div>
                <div class="point-sale">
                    '.date('d/m', strtotime($order->distribution->date)).' &bull;
                    '.$order->pointSale->name.'
                </div>
                <div class="products">
                    '.$this->orderRepository->getCartSummary($order).'
                </div>
                '.$amountAndPayment.'
            </div>
        </div>';
    }

    public function getSpecificFormatDetails(string $name): array
    {
        $specificFormatDetailsArray = $this->getSpecificFormatDetailsArray();
        if(!isset($specificFormatDetailsArray[$name])) {
            throw new ErrorException("Format d'étiquette inconnu");
        }
        return $specificFormatDetailsArray[$name];
    }

    public function populateDropdownSpecificFormats(): array
    {
        $specificFormatsArray = [null => '--'];
        foreach($this->getSpecificFormatDetailsArray() as $key => $specificFormat) {
            $specificFormatsArray[$key] = $specificFormat[0].'x'.$specificFormat[1].' mm';
        }
        return $specificFormatsArray;
    }
}