<?php
/**
 * BookiFlex Cart Extension
 *
 * @package    BookiFlex
 * @subpackage Cart
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */


declare(strict_types=1);
namespace BookiFlex\Extensions\Cart;

use BookiFlex\Core\Contract\AvailabilityChecker\QuotaAvailabilityInterface;
use BookiFlex\Core\Contract\Fee\FeeCalculatorInterface;
use BookiFlex\Core\Contract\Payment\PaymentFactoryInterface;
use BookiFlex\Core\Contract\Taxation\TaxCalculatorInterface;
use BookiFlex\Core\Contract\Taxation\TaxRuleProviderInterface;
use BookiFlex\Extensions\Cart\Contract\CartExtraProviderInterface;
use BookiFlex\Core\Repository\AccommodationTypeRepository;
use BookiFlex\Core\Repository\CustomerRepository;
use BookiFlex\Core\Repository\RatePlanRepository;
use BookiFlex\Core\Service\AvailabilityChecker\AvailabilityChecker;
use BookiFlex\Core\Service\NumberGenerator\NumberGenerator;
use BookiFlex\Core\Service\SessionService;
use BookiFlex\Core\Service\StayCostCalculator\StayCostCalculator;
use BookiFlex\Extensions\Cart\Api\Controller\CartController;
use BookiFlex\Extensions\Cart\Api\Transformer\CartTransformer;
use BookiFlex\Extensions\Cart\Api\Transformer\CartTotalsTransformer;
use BookiFlex\Extensions\Cart\Model\Cart as CartModel;
use BookiFlex\Extensions\Cart\Model\CartItem;
use BookiFlex\Extensions\Cart\Repository\CartItemRepository;
use BookiFlex\Extensions\Cart\Repository\CartRepository;
use BookiFlex\Extensions\Cart\Service\CartCheckoutService;
use BookiFlex\Extensions\Cart\Service\CartInitService;
use BookiFlex\Extensions\Cart\Service\CartService;
use BookiFlex\Extensions\Cart\Service\Jobs\CleanupExpiredCartsJob;
use BookiFlex\Extensions\Cart\Service\PaymentTypeService;
use Cycle\ORM\EntityManagerInterface;
use Cycle\ORM\ORM;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Psr\Log\LoggerInterface;

defined( 'ABSPATH' ) || exit;

class ServiceProvider implements ServiceProviderInterface
{
    public function register(Container $pimple): void
    {
        $pimple[CartInitService::class] = function ($c) {
            return new CartInitService(
                $c['config'],
                $c->get(TaxRuleProviderInterface::class),
            );
        };

        // Default null binding — overridden by Extras extension when active.
        $pimple[CartExtraProviderInterface::class] = function () {
            return null;
        };

        $pimple[CartService::class] = function ($c) {
            return new CartService(
                $c->get(CartRepository::class),
                $c->get(RatePlanRepository::class),
                $c->get(AccommodationTypeRepository::class),
                $c->get(CustomerRepository::class),
                $c->get(AvailabilityChecker::class),
                $c->get(StayCostCalculator::class),
                $c->get('config'),
                $c->get(EntityManagerInterface::class),
                $c->get(TaxCalculatorInterface::class),
                $c->get(FeeCalculatorInterface::class),
                $c->get(CartExtraProviderInterface::class),
            );
        };

        $pimple[CartCheckoutService::class] = function ($c) {
            return new CartCheckoutService(
                $c->get(RatePlanRepository::class),
                $c->get(AccommodationTypeRepository::class),
                $c->get(NumberGenerator::class),
                $c->get('config'),
                $c->get(StayCostCalculator::class),
                $c->get(EntityManagerInterface::class),
                $c->get(QuotaAvailabilityInterface::class),
                $c->get(PaymentFactoryInterface::class),
                $c->get(TaxCalculatorInterface::class),
                $c->get(FeeCalculatorInterface::class),
	            $c->get(LoggerInterface::class),
                $c->get(CartExtraProviderInterface::class),
            );
        };

        // Repositories
        $pimple[CartRepository::class] = function ($c) {
            return $c->get(ORM::class)->getRepository(CartModel::class);
        };
        $pimple[CartItemRepository::class] = function ($c) {
            return $c->get(ORM::class)->getRepository(CartItem::class);
        };

        // Controllers
        $pimple[CartController::class] = function ($c) {
            return new CartController(
                $c->get(CartInitService::class),
                $c->get(CartService::class),
                $c->get(CartCheckoutService::class),
                $c->get(SessionService::class),
                $c->get(CartTransformer::class),
                $c->get(CartTotalsTransformer::class)
            );
        };

        $pimple[CartTransformer::class] = function ($c) {
            return new CartTransformer(
                $c->get(PaymentTypeService::class),
            );
        };

        $pimple[CartTotalsTransformer::class] = function () {
            return new CartTotalsTransformer();
        };

        $pimple[PaymentTypeService::class] = function ($c) {
            return new PaymentTypeService(
                $c->get(RatePlanRepository::class),
            );
        };

        $pimple[CleanupExpiredCartsJob::class] = function ($c) {
            return new CleanupExpiredCartsJob(
                $c->get(CartService::class)
            );
        };
    }
}
