<?php

namespace Lc\CaracoleBundle\Solver\Price;

use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Product\ProductInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface;
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver;
use Lc\CaracoleBundle\Solver\Product\ProductSolver;

class ProductPriceSolver
{
    use PriceSolverTrait;

    protected ProductSolver $productSolver;
    protected ProductFamilySolver $productFamilySolver;

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

    public function getSolver(ProductPropertyInterface $product)
    {
        if ($product instanceof ProductFamilyInterface) {
            return $this->productFamilySolver;
        }

        if ($product instanceof ProductInterface) {
            return $this->productSolver;
        }
    }

    public function getPrice(ProductPropertyInterface $product)
    {
        $solver = $this->getSolver($product);

        if ($solver->getBehaviorPriceInherited($product) == 'by-piece') {
            return $solver->getPriceInherited($product);
        } elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') {
            if ($solver->getQuantityInherited($product) > 0) {
                return $solver->getPriceByRefUnitInherited($product) * ($solver->getQuantityInherited(
                                        $product
                                ) / $solver->getUnitInherited($product)->getCoefficient());
            } else {
                return 0;
            }
        }
    }

    public function getPriceWithTax(ProductPropertyInterface $product)
    {
        return $this->applyTax(
                $this->getPrice($product),
                $this->productFamilySolver->getTaxRateInherited($product)->getValue()
        );
    }

    public function getPriceByRefUnit(ProductPropertyInterface $product)
    {
        $solver = $this->getSolver($product);

        if ($solver->getBehaviorPriceInherited($product) == 'by-piece') {
            return ($this->getPrice($product) * $solver->getUnitInherited($product)->getCoefficient(
                            )) / $solver->getQuantityInherited($product);
        } elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') {
            return $solver->getPriceByRefUnitInherited($product);
        }
    }

    public function getPriceByRefUnitWithTax(ProductPropertyInterface $product)
    {
        return $this->applyTax(
                $this->getPriceByRefUnit($product),
                $this->productFamilySolver->getTaxRateInherited($product)->getValue()
        );
    }

    public function getPriceWithTaxAndReduction(ProductPropertyInterface $product)
    {
        //TODO voir différence entre prix ici et dans tableau décli
        return $this->applyReductionCatalog(
                $product,
                $this->getPrice($product),
                $this->getPriceWithTax($product)
        );
    }

    //Bridge pour applyReductionCatalog qui ne peut pas être appeler à cause du call
    public function getPriceWithTaxByReduction(
            ProductPropertyInterface $product,
            ReductionCatalogInterface $reductionCatalog
    ) {
        return $this->applyReductionCatalog(
                $product,
                $this->getPrice($product),
                $this->getPriceWithTax($product),
                1,
                $reductionCatalog
        );
    }

    public function getPriceByRefUnitWithTaxAndReduction(ProductPropertyInterface $product)
    {
        $priceWithTax = $this->getPriceWithTax($product);

        if ($priceWithTax) {
            return $this->round(
                    ($this->getPriceByRefUnitWithTax($product) * $this->getPriceWithTaxAndReduction($product))
                        / $priceWithTax
                    );
        }

        return 0;
    }

    public function getBuyingPrice(ProductPropertyInterface $product)
    {
        $solver = $this->getSolver($product);

        if ($solver->getBehaviorPriceInherited($product) == 'by-piece') {
            return $solver->getBuyingPriceInherited($product);
        } elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') {
            if ($solver->getQuantityInherited($product) > 0) {
                return $solver->getBuyingPriceByRefUnitInherited($product) * ($solver->getQuantityInherited(
                                        $product
                                ) / $solver->getUnitInherited($product)->getCoefficient());
            } else {
                return 0;
            }
        }
    }

    public function getBuyingPriceWithTax(ProductPropertyInterface $product)
    {
        return $this->applyTax(
                $this->getBuyingPrice($product),
                $this->productFamilySolver->getTaxRateInherited($product)->getValue()
        );
    }

    public function getBuyingPriceByRefUnit(ProductPropertyInterface $product)
    {
        return $this->getSolver($product)->getBuyingPriceByRefUnitInherited($product);
    }

    public function getBuyingPriceByRefUnitWithTax(ProductPropertyInterface $product)
    {
        return $this->applyTax(
                $this->getBuyingPriceByRefUnit($product),
                $this->productFamilySolver->getTaxRateInherited($product)->getValue()
        );
    }

    public function getMultiplyingFactor(ProductPropertyInterface $product)
    {
        return $this->round($this->getPriceWithTax($product) / $this->getBuyingPrice($product));
    }
}