<?php

namespace domain\PointSale\SharedPointSale;

use common\helpers\GlobalParam;
use domain\_\AbstractResolver;
use domain\Distribution\Distribution\Distribution;
use domain\Distribution\Distribution\DistributionRepository;
use domain\Distribution\PointSaleDistribution\PointSaleDistributionRepository;
use domain\PointSale\PointSale\PointSale;
use domain\PointSale\PointSale\PointSaleRepository;
use yii\helpers\Html;

class SharedPointSaleResolver extends AbstractResolver
{
    protected PointSaleRepository $pointSaleRepository;
    protected SharedPointSaleRepository $sharedPointSaleRepository;
    protected PointSaleDistributionRepository $pointSaleDistributionRepository;
    protected DistributionRepository $distributionRepository;

    public function loadDependencies(): void
    {
        $this->pointSaleRepository = $this->loadService(PointSaleRepository::class);
        $this->sharedPointSaleRepository = $this->loadService(SharedPointSaleRepository::class);
        $this->distributionRepository = $this->loadService(DistributionRepository::class);
        $this->pointSaleDistributionRepository = $this->loadService(PointSaleDistributionRepository::class);
    }

    public function getPointsSaleSharedWithPointSale(PointSale $pointSale, Distribution $distribution = null, array &$pointsSaleSharedWithPointSaleArray = []): array
    {
        $idProducerContext = $this->getProducerContextId();
        $sharedPointsSaleConfirmedArray = $this->sharedPointSaleRepository->findSharedPointsSaleConfirmedByPointSale($pointSale);

        foreach($sharedPointsSaleConfirmedArray as $sharedPointSaleConfirmed) {
            if ($sharedPointSaleConfirmed->getPointSale()->id != $pointSale->id
                && !in_array($sharedPointSaleConfirmed->getPointSale(), $pointsSaleSharedWithPointSaleArray)
                && $sharedPointSaleConfirmed->getPointSale()->getProducer()->id != $idProducerContext) {

                $distributionProducer = null;
                if($distribution) {
                    $distributionProducer = $this->distributionRepository
                        ->setProducerContext($sharedPointSaleConfirmed->getPointSale()->getProducer())
                        ->findOneDistribution($distribution->date, true);
                }

                if(!$distribution || ($distributionProducer && $this->pointSaleDistributionRepository->findOnePointSaleDistribution($distributionProducer, $sharedPointSaleConfirmed->getPointSale(), true))) {
                    $pointsSaleSharedWithPointSaleArray[] = $sharedPointSaleConfirmed->getPointSale();
                    $this->getPointsSaleSharedWithPointSale($sharedPointSaleConfirmed->getPointSale(), $distribution, $pointsSaleSharedWithPointSaleArray);
                }
            }
            if ($sharedPointSaleConfirmed->getPointSaleWithSharing()->id != $pointSale->id
                && !in_array($sharedPointSaleConfirmed->getPointSaleWithSharing(), $pointsSaleSharedWithPointSaleArray)
                && $sharedPointSaleConfirmed->getProducerWithSharing()->id != $idProducerContext) {

                $distributionProducer = null;
                if($distribution) {
                    $distributionProducer = $this->distributionRepository
                        ->setProducerContext($sharedPointSaleConfirmed->getProducerWithSharing())
                        ->findOneDistribution($distribution->date, true);
                }

                if(!$distribution || ($distributionProducer && $this->pointSaleDistributionRepository->findOnePointSaleDistribution($distributionProducer, $sharedPointSaleConfirmed->getPointSaleWithSharing(), true))) {
                    $pointsSaleSharedWithPointSaleArray[] = $sharedPointSaleConfirmed->getPointSaleWithSharing();
                    $this->getPointsSaleSharedWithPointSale($sharedPointSaleConfirmed->getPointSaleWithSharing(), $distribution, $pointsSaleSharedWithPointSaleArray);
                }
            }
        }

        return array_unique($pointsSaleSharedWithPointSaleArray, SORT_REGULAR);
    }

    public function getProducersSharingPointSaleAsString(PointSale $pointSale, Distribution $distribution = null, string $separator = ', ', bool $withLink = false): string
    {
        $pointsSaleSharedWithPointSaleArray = $this->getPointsSaleSharedWithPointSale($pointSale, $distribution);
        return implode($separator, array_map(
            function($pointSale) use ($withLink) {
                $return = '';
                if($withLink) {
                    $return .= '<a href="'.\Yii::$app->urlManagerProducer->createUrl(['site/index', 'slug_producer' => $pointSale->getProducer()->slug]).'">';
                }
                $return .= $pointSale->getProducer()->getName();
                if($withLink) {
                    $return .= '</a>';
                }
                return $return;
            },
            $pointsSaleSharedWithPointSaleArray)
        );
    }

    public function countPointsSaleSharedWithPointSale(PointSale $pointSale): int
    {
        return count($this->getPointsSaleSharedWithPointSale($pointSale));
    }

    public function hasPointSaleSharedWithPointSale(PointSale $pointSale): bool
    {
        return (bool) $this->countPointsSaleSharedWithPointSale($pointSale);
    }

    public function countPointsSaleShared(): int
    {
        $count = 0;
        $pointsSaleArray = $this->pointSaleRepository->findPointSales();

        foreach($pointsSaleArray as $pointSale) {
            if($this->hasPointSaleSharedWithPointSale($pointSale)) {
                $count ++;
            }
        }

        return $count;
    }

    public function countSharedPointsSaleRequestsOthers(): int
    {
        return count($this->sharedPointSaleRepository->findSharedPointsSaleRequestsOthers());
    }
}