<?php

namespace common\logic\Subscription\Subscription\Service;

use common\logic\AbstractManager;
use common\logic\Distribution\Distribution\Repository\DistributionRepository;
use common\logic\Distribution\Distribution\Service\DistributionSolver;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\Order\Repository\OrderRepository;
use common\logic\Order\Order\Service\OrderBuilder;
use common\logic\Subscription\Subscription\Model\Subscription;
use common\logic\Subscription\Subscription\Repository\SubscriptionRepository;

class OrderManager extends AbstractManager
{
    protected DistributionSolver $distributionSolver;
    protected DistributionRepository $distributionRepository;
    protected OrderRepository $orderRepository;
    protected OrderBuilder $orderBuilder;
    protected SubscriptionRepository $subscriptionRepository;
    protected SubscriptionSolver $subscriptionSolver;

    public function loadDependencies(): void
    {
        $this->distributionSolver = $this->loadService(DistributionSolver::class);
        $this->distributionRepository = $this->loadService(DistributionRepository::class);
        $this->orderRepository = $this->loadService(OrderRepository::class);
        $this->orderBuilder = $this->loadService(OrderBuilder::class);
        $this->subscriptionRepository = $this->loadService(SubscriptionRepository::class);
        $this->subscriptionSolver = $this->loadService(SubscriptionSolver::class);
    }

    /**
     * Ajoute l'abonnement' pour une date donnée.
     */
    public function createOrderFromSubscription(Subscription $subscription, string $date, bool $force = false): ?Order
    {
        $now = date('Y-m-d');
        $distributionDate = date('Y-m-d', strtotime($date));
        $distribution = $this->distributionRepository->findOneDistribution($distributionDate);

        if ($distribution
            && $distribution->active
            && ($distributionDate > $now || $force)
            && count($subscription->productSubscription)
            && $subscription->pointSale) {

            $order = $this->orderBuilder->createOrder($distribution);
            $this->orderBuilder->updateOrderFromSubscription($order, $subscription);

            return $order;
        }

        return null;
    }

    /**
     * Ajoute les commandes pour une date donnée à partir des abonnements.
     */
    public function createAllOrdersFromSubscriptions(string $date, bool $force = false): array
    {
        $ordersSubscriptionsArray = [];
        $distribution = $this->distributionRepository->findOneDistribution(date('Y-m-d', strtotime($date)));

        if ($distribution) {
            $orderArray = $this->orderRepository->findOrdersByDistribution($distribution);
            $subscriptionArray = $this->subscriptionRepository->findSubscriptionsByDate($date);
            foreach ($subscriptionArray as $subscription) {
                if (!$this->subscriptionSolver->hasOrderAlreadyExist($subscription, $orderArray)) {
                    $order = $this->createOrderFromSubscription($subscription, $date, $force);
                    if ($order) {
                        $ordersSubscriptionsArray[] = $order;
                    }
                }
            }
        }

        return $ordersSubscriptionsArray;
    }

    public function updateOrdersIncomingDistributionsFromSubscription(Subscription $subscription, $update = false): array
    {
        $orderArray = [];
        $matchedDistributionsArray = $this->distributionRepository->findDistributionsIncomingMatchWithSubscrtiption($subscription, true);

        if ($update) {
            $this->deleteOrdersIncomingDistributionsFromSubscription($subscription);
        }

        if (count($matchedDistributionsArray)) {
            foreach ($matchedDistributionsArray as $distribution) {
                $orderArray[] = $this->createOrderFromSubscription($subscription, $distribution->date);
            }
        }

        return $orderArray;
    }

    public function deleteOrdersIncomingDistributionsFromSubscription(Subscription $subscription, bool $deleteAfterDateEnd = false): int
    {
        $ordersArray = $this->orderRepository->findOrdersIncomingBySubscription($subscription, !$deleteAfterDateEnd);
        $countOrdersDeleted = 0;

        if ($ordersArray && count($ordersArray)) {
            foreach ($ordersArray as $order) {
                if ($this->distributionSolver->isDistributionAvailable($order->distribution)) {
                    $theOrder = $this->orderRepository->findOneOrderById($order->id);
                    $this->orderBuilder->initOrder($theOrder);
                    $this->orderBuilder->deleteOrder($order, true);
                    $countOrdersDeleted++;
                }
            }
        }

        return $countOrdersDeleted;
    }
}