<?php

namespace common\logic\Distribution\ProductDistribution\Service;

use common\logic\AbstractBuilder;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\Distribution\Repository\DistributionRepository;
use common\logic\Distribution\Distribution\Service\DistributionSolver;
use common\logic\Distribution\ProductDistribution\Model\ProductDistribution;
use common\logic\Distribution\ProductDistribution\Repository\ProductDistributionRepository;
use common\logic\Product\Product\Model\Product;
use common\logic\Product\Product\Service\ProductSolver;

class ProductDistributionBuilder extends AbstractBuilder
{
    protected ProductDistributionRepository $productDistributionRepository;
    protected DistributionSolver $distributionSolver;
    protected ProductSolver $productSolver;
    protected DistributionRepository $distributionRepository;

    public function loadDependencies(): void
    {
        $this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class);
        $this->distributionSolver = $this->loadService(DistributionSolver::class);
        $this->productSolver = $this->loadService(ProductSolver::class);
        $this->distributionRepository = $this->loadService(DistributionRepository::class);
    }

    public function instanciateProductDistribution(Distribution $distribution, Product $product): ProductDistribution
    {
        $productDistribution = new ProductDistribution();
        $productDistribution->populateFieldObject('id_distribution', 'distribution', $distribution);
        $productDistribution->populateFieldObject('id_product', 'product', $product);

        return $productDistribution;
    }

    public function createProductDistribution(Distribution $distribution, Product $product): ProductDistribution
    {
        $productDistribution = $this->instanciateProductDistribution($distribution, $product);
        $this->initProductDistribution($productDistribution);
        $this->saveCreate($productDistribution);

        return $productDistribution;
    }

    public function createProductDistributionIfNotExist(Distribution $distribution, Product $product): ProductDistribution
    {
        return $this->productDistributionRepository->findOneProductDistribution($distribution, $product)
            ?? $this->createProductDistribution($distribution, $product);
    }

    public function updateProductDistribution(ProductDistribution $productDistribution): ProductDistribution
    {
        $this->initProductDistribution($productDistribution);
        $this->update($productDistribution);

        return $productDistribution;
    }

    public function initProductDistribution(ProductDistribution $productDistribution): ProductDistribution
    {
        $this->initActive($productDistribution);
        $this->initQuantityMax($productDistribution);

        return $productDistribution;
    }

    public function initActive(ProductDistribution $productDistribution): ProductDistribution
    {
        $productDistribution->active = (int) $this->productSolver->isProductActiveByDay(
            $productDistribution->product,
            $this->distributionSolver->getDistributionDayAsString($productDistribution->distribution)
        );

        return $productDistribution;
    }

    public function initQuantityMax(ProductDistribution $productDistribution): ProductDistribution
    {
        $productDistribution->quantity_max = $this->productSolver->getProductQuantityMaxByDay(
            $productDistribution->product,
            $this->distributionSolver->getDistributionDayAsString($productDistribution->distribution)
        );

        return $productDistribution;
    }

    public function updateProductDistributionQuantityMax(ProductDistribution $productDistribution, float $quantityMax)
    {
        $productDistribution->quantity_max = ($quantityMax == -1) ? null : (float) abs($quantityMax);
        $this->update($productDistribution);

        return $productDistribution;
    }

    public function updateProductDistributionActive(ProductDistribution $productDistribution, int $active)
    {
        $productDistribution->active = $active;
        $this->update($productDistribution);
    }

    public function disableProductDistributionsIncomingByProduct(Product $product)
    {
        $distributionsIncomingArray = $this->distributionRepository->findDistributionsIncoming(true);
        foreach($distributionsIncomingArray as $distribution) {
            ProductDistribution::updateAll([
                'active' => false
            ], [
                'id_product' => $product->id,
                'id_distribution' => $distribution->id,
            ]);
        }
    }
}