<?php

namespace domain\Product\ProductPrice\Service;

use domain\PointSale\PointSale\PointSale;
use domain\Product\ProductPrice\Model\ProductPrice;
use domain\User\User\User;
use domain\User\User\UserSolver;
use domain\User\UserGroup\UserGroupRepository;
use domain\_\AbstractService;
use domain\_\SolverInterface;

class ProductPriceSolver extends AbstractService implements SolverInterface
{
    protected UserSolver $userSolver;

    public function loadDependencies(): void
    {
        $this->userSolver = $this->loadService(UserSolver::class);
    }

    // getSpecificPricesFilterByPriorityMatch
    public function filterByPriorityMatch(
        array $specificPrices,
        User $user = null,
        PointSale $pointSale = null): array
    {
        $priorityMatchSpecificPrice =  $this->getPriorityMatch($specificPrices, $user, $pointSale);
        $specificPricesFilter = [];

        foreach ($specificPrices as $keySpecificPrice => $specificPrice) {
            if (($priorityMatchSpecificPrice && $this->$priorityMatchSpecificPrice($specificPrice, $user, $pointSale))
                || $this->matchFromQuantityOnly($specificPrice)) {

                $specificPricesFilter[] = $specificPrice;
            }
        }

        return $specificPricesFilter;
    }

    // getPriorityMatchOfSpecificPriceArray
    public function getPriorityMatch(
        array $specificPriceArray,
        User $user = null,
        PointSale $pointSale = null): ?string
    {
        $typeMatchArray = [
            'matchUserPointSale',
            'matchUser',
            'matchUserGroupPointSale',
            'matchUserGroup',
            'matchPointSale'
        ];

        foreach($typeMatchArray as $typeMatch) {
            if($this->hasMatchOfType($specificPriceArray, $typeMatch, $user, $pointSale)) {
                return $typeMatch;
            }
        }

        return null;
    }

    public function hasMatchOfType(
        array $specificPriceArray,
        string $typeMatch,
        User $user = null,
        PointSale $pointSale = null): bool
    {
        foreach($specificPriceArray as $specificPrice) {
            if($this->$typeMatch($specificPrice, $user, $pointSale)) {
                return true;
            }
        }

        return false;
    }

    public function matchUser(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
    {
        return $user
            && $productPrice->id_user
            && !$productPrice->id_point_sale
            && !$productPrice->id_user_group
            && $productPrice->id_user == $user->id;
    }

    public function matchUserGroup(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
    {
        // @TODO : trouver une solution pour hydrater autrement cette donnée
        if($productPrice->id_user_group && !$productPrice->userGroup) {
            $userGroup = UserGroupRepository::getInstance()->findOneUserGroupById($productPrice->id_user_group);
            if($userGroup) {
                $productPrice->populateUserGroup($userGroup);
            }
        }

        return $user
            && $productPrice->id_user_group
            && $productPrice->userGroup
            && !$productPrice->id_point_sale
            && !$productPrice->id_user
            && $this->userSolver->isUserBelongsToUserGroup($user, $productPrice->userGroup);
    }

    public function matchPointSale(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
    {
        return $pointSale
            && $productPrice->id_point_sale
            && !$productPrice->id_user
            && !$productPrice->id_user_group
            && $productPrice->id_point_sale == $pointSale->id;
    }

    public function matchUserPointSale(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
    {
        return $pointSale && $user
            && $productPrice->id_point_sale
            && $productPrice->id_user
            && $productPrice->id_point_sale == $pointSale->id
            && $productPrice->id_user == $user->id;
    }

    public function matchUserGroupPointSale(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
    {
        // @TODO : trouver une solution pour hydrater autrement cette donnée
        if($productPrice->id_user_group && !$productPrice->userGroup) {
            $userGroup = UserGroupRepository::getInstance()->findOneUserGroupById($productPrice->id_user_group);
            if($userGroup) {
                $productPrice->populateUserGroup($userGroup);
            }
        }

        return $user
            && $pointSale
            && $productPrice->id_user_group
            && $productPrice->id_point_sale
            && !$productPrice->id_user
            && $this->userSolver->isUserBelongsToUserGroup($user, $productPrice->userGroup)
            && $productPrice->id_point_sale == $pointSale->id;
    }

    public function matchFromQuantityOnly(ProductPrice $productPrice): bool
    {
        return !$productPrice->id_user
            && !$productPrice->id_point_sale
            && !$productPrice->id_user_group
            && $productPrice->from_quantity;
    }

    public function percentValues(): array
    {
        $percentValues = [
            '' => 'Aucun'
        ];

        for ($i = -50; $i < 51; $i = $i + 5) {
            $percentValues[$i] = $i . ' %';
        }

        return $percentValues;
    }
}