<?php

namespace App\Tests\Repository;

use App\Entity\Product;
use App\Entity\ProductReserve;
use App\Repository\ProductReserveRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

class ProductReserveRepositoryTest extends KernelTestCase
{
    private ?EntityManagerInterface $entityManager;
    private ?ProductReserveRepository $repository;

    protected function setUp(): void
    {
        $kernel = self::bootKernel();

        $this->entityManager = $kernel->getContainer()
            ->get('doctrine')
            ->getManager();
            
        $this->repository = $this->entityManager->getRepository(ProductReserve::class);
        
        // Optional: Purge database or ensure clean state
        // For now, we assume a test DB or we just append data.
        // Ideally, we should use a separate test DB.
    }

    protected function tearDown(): void
    {
        parent::tearDown();
        $this->entityManager->close();
        $this->entityManager = null;
        $this->repository = null;
    }

    public function testCheckAvailability()
    {
        // 1. Create a Product
        $product = new Product();
        $product->setRef('TEST-REF-' . uniqid());
        $product->setCategory('TEST-CAT');
        $product->setName('Test Product ' . uniqid());
        $product->setPriceDay(10.0);
        $product->setCaution(100.0);
        
        $this->entityManager->persist($product);
        
        // 2. Create an existing reservation
        // From 2026-02-10 to 2026-02-15
        $existing = new ProductReserve();
        $existing->setProduct($product);
        $existing->setStartAt(new \DateTimeImmutable('2026-02-10 10:00:00'));
        $existing->setEndAt(new \DateTimeImmutable('2026-02-15 10:00:00'));
        
        $this->entityManager->persist($existing);
        $this->entityManager->flush();

        // 3. Test Cases

        // Case A: Completely before (Available)
        // 2026-02-01 to 2026-02-05
        $reserveA = new ProductReserve();
        $reserveA->setProduct($product);
        $reserveA->setStartAt(new \DateTimeImmutable('2026-02-01 10:00:00'));
        $reserveA->setEndAt(new \DateTimeImmutable('2026-02-05 10:00:00'));
        
        $this->assertTrue($this->repository->checkAvailability($reserveA), 'Should be available (before)');

        // Case B: Completely after (Available)
        // 2026-02-16 to 2026-02-20
        $reserveB = new ProductReserve();
        $reserveB->setProduct($product);
        $reserveB->setStartAt(new \DateTimeImmutable('2026-02-16 10:00:00'));
        $reserveB->setEndAt(new \DateTimeImmutable('2026-02-20 10:00:00'));

        $this->assertTrue($this->repository->checkAvailability($reserveB), 'Should be available (after)');

        // Case C: Overlapping (exact match) (Not Available)
        // 2026-02-10 to 2026-02-15
        $reserveC = new ProductReserve();
        $reserveC->setProduct($product);
        $reserveC->setStartAt(new \DateTimeImmutable('2026-02-10 10:00:00'));
        $reserveC->setEndAt(new \DateTimeImmutable('2026-02-15 10:00:00'));

        $this->assertFalse($this->repository->checkAvailability($reserveC), 'Should NOT be available (exact match)');

        // Case D: Overlapping (partial start) (Not Available)
        // 2026-02-09 to 2026-02-11
        $reserveD = new ProductReserve();
        $reserveD->setProduct($product);
        $reserveD->setStartAt(new \DateTimeImmutable('2026-02-09 10:00:00'));
        $reserveD->setEndAt(new \DateTimeImmutable('2026-02-11 10:00:00'));

        $this->assertFalse($this->repository->checkAvailability($reserveD), 'Should NOT be available (overlap start)');

        // Case E: Overlapping (partial end) (Not Available)
        // 2026-02-14 to 2026-02-16
        $reserveE = new ProductReserve();
        $reserveE->setProduct($product);
        $reserveE->setStartAt(new \DateTimeImmutable('2026-02-14 10:00:00'));
        $reserveE->setEndAt(new \DateTimeImmutable('2026-02-16 10:00:00'));

        $this->assertFalse($this->repository->checkAvailability($reserveE), 'Should NOT be available (overlap end)');

        // Case F: Inside (Not Available)
        // 2026-02-11 to 2026-02-14
        $reserveF = new ProductReserve();
        $reserveF->setProduct($product);
        $reserveF->setStartAt(new \DateTimeImmutable('2026-02-11 10:00:00'));
        $reserveF->setEndAt(new \DateTimeImmutable('2026-02-14 10:00:00'));

        $this->assertFalse($this->repository->checkAvailability($reserveF), 'Should NOT be available (inside)');

        // Case G: Encompassing (Not Available)
        // 2026-02-09 to 2026-02-16
        $reserveG = new ProductReserve();
        $reserveG->setProduct($product);
        $reserveG->setStartAt(new \DateTimeImmutable('2026-02-09 10:00:00'));
        $reserveG->setEndAt(new \DateTimeImmutable('2026-02-16 10:00:00'));

        $this->assertFalse($this->repository->checkAvailability($reserveG), 'Should NOT be available (encompassing)');
    }
}
