<?php

namespace Lc\CaracoleBundle\Resolver;

use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
use Lc\CaracoleBundle\Solver\Price\PriceSolver;
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver;

class ProductFamilyResolver
{
    protected PriceSolver $priceSolver;
    protected ProductFamilySolver $productFamilySolver;

    public function __construct(PriceSolver $priceSolver, ProductFamilySolver $productFamilySolver)
    {
        $this->priceSolver = $priceSolver;
        $this->productFamilySolver = $productFamilySolver;
    }

    public function getMultiplyingFactor(ProductFamilyInterface $productFamily)
    {
        if ($productFamily->getBehaviorPrice() == ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) {
            if ($productFamily->getBuyingPrice() > 0) {
                return number_format(
                        $this->priceSolver->getPriceWithTax($productFamily) / $productFamily->getBuyingPrice(),
                        3
                );
            }
        } elseif ($productFamily->getBehaviorPrice() == ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) {
            if ($productFamily->getBuyingPriceByRefUnit() > 0) {
                return number_format(
                        $this->priceSolver->getPriceByRefUnitWithTax(
                                $productFamily
                        ) / $productFamily->getBuyingPriceByRefUnit(),
                        3
                );
            }
        }
    }

    public function getCheapestProduct(ProductFamilyInterface $productFamily)
    {
        $priceSolver = $this->priceSolver;

        return $this->getCheapestOrMostExpensiveProduct(
                $productFamily,
                function ($a, $b) use ($priceSolver) {
                    return $priceSolver->getPriceWithTaxAndReduction(
                                    $a
                            ) > $priceSolver->getPriceWithTaxAndReduction($b);
                },
                true
        );
    }

    public function getCheapestProductByRefUnit(ProductFamilyInterface $productFamily)
    {
        $priceSolver = $this->priceSolver;

        return $this->getCheapestOrMostExpensiveProduct(
                $productFamily,
                function ($a, $b) use ($priceSolver) {
                    return $priceSolver->getPriceByRefUnitWithTaxAndReduction(
                                    $a
                            ) > $priceSolver->getPriceByRefUnitWithTaxAndReduction($b);
                },
                false
        );
    }

    public function getMostExpensiveProductByRefUnit(ProductFamilyInterface $productFamily)
    {
        $priceSolver = $this->priceSolver;

        return $this->getCheapestOrMostExpensiveProduct(
                $productFamily,
                function ($a, $b) use ($priceSolver) {
                    return $priceSolver->getPriceByRefUnitWithTaxAndReduction(
                                    $a
                            ) < $priceSolver->getPriceByRefUnitWithTaxAndReduction($b);
                },
                false
        );
    }

    private function getCheapestOrMostExpensiveProduct(
            ProductFamilyInterface $productFamily,
            $comparisonFunction,
            $returnSelfIfNotActiveProducts
    ) {
        if ($productFamily->getActiveProducts()) {
            $products = $this->productFamilySolver->getProductsOnline($productFamily)->getValues();
            if (count($products) > 0) {
                usort($products, $comparisonFunction);
                return $products[0];
            }
        } else {
            return $this->productFamilySolver->getOriginProduct($productFamily);
        }
        if ($returnSelfIfNotActiveProducts) {
            return $productFamily;
        } else {
            return false;
        }
    }
}