<?php

declare(strict_types=1);

namespace App\Service;

use App\Entity\DrinkType;
use App\Entity\InventoryRecord;
use App\Repository\DrinkTypeRepository;
use App\Repository\InventoryRecordRepository;
use App\Service\Config\LowStockMultiplier;
use App\ValueObject\DrinkStock;
use DateTimeImmutable;

readonly class InventoryService
{
    public function __construct(
        private InventoryRecordRepository $inventoryRecordRepository,
        private DrinkTypeRepository $drinkTypeRepository,
        private LowStockMultiplier $lowStockMultiplier,
    ) {}

    /**
     * Get all inventory records
     *
     * @return InventoryRecord[]
     */
    public function getAllInventoryRecords(): array
    {
        return $this->inventoryRecordRepository->findAll();
    }

    /**
     * Get inventory records for a specific drink type
     *
     * @param DrinkType $drinkType
     * @return InventoryRecord[]
     */
    public function getInventoryRecordsByDrinkType(DrinkType $drinkType): array
    {
        return $this->inventoryRecordRepository->findByDrinkType($drinkType);
    }

    /**
     * Get the latest inventory record for a specific drink type
     *
     * @param DrinkType $drinkType
     * @return InventoryRecord
     */
    public function getLatestInventoryRecord(DrinkType $drinkType): InventoryRecord
    {
        $record = $this->inventoryRecordRepository->findLatestByDrinkType($drinkType);
        if (!($record instanceof InventoryRecord)) {
            return new InventoryRecord($drinkType, 0);
        }
        return $record;
    }



    /**
     * Get the current stock level for a specific drink type
     *
     * @param DrinkType $drinkType
     * @return int
     */
    public function getCurrentStockLevel(DrinkType $drinkType): int
    {
        $latestRecord = $this->getLatestInventoryRecord($drinkType);
        return ($latestRecord instanceof InventoryRecord) ? $latestRecord->getQuantity() : 0;
    }

    /**
     * Update the stock level for a specific drink type
     *
     * @param DrinkType $drinkType
     * @param int $quantity
     * @param DateTimeImmutable|null $timestamp
     * @return InventoryRecord
     */
    public function updateStockLevel(
        DrinkType $drinkType,
        int $quantity,
        DateTimeImmutable $timestamp = new DateTimeImmutable(),
    ): InventoryRecord {
        $inventoryRecord = new InventoryRecord($drinkType, $quantity, $timestamp);

        $this->inventoryRecordRepository->save($inventoryRecord);

        return $inventoryRecord;
    }

    /**
     * @return InventoryRecord[]
     */
    public function getAllDrinkTypesWithStockLevels(bool $includeZeroDesiredStock = false): array
    {
        if ($includeZeroDesiredStock) {
            $drinkTypes = $this->drinkTypeRepository->findAll();
        } else {
            $drinkTypes = $this->drinkTypeRepository->findDesired();
        }
        $result = [];

        foreach ($drinkTypes as $drinkType) {
            $result[] = $this->getDrinkStock($drinkType);
        }

        return $result;
    }

    public function getDrinkStock(DrinkType $drinkType): DrinkStock
    {
        return DrinkStock::fromInventoryRecord(
            $this->getLatestInventoryRecord($drinkType),
            $this->lowStockMultiplier->getValue(),
        );
    }
}
