<?php

namespace App\Tests\Event\Signature;

use App\Entity\Contrats;
use App\Entity\Customer;
use App\Event\Signature\ContratEvent;
use App\Event\Signature\ContratSubscriber;
use App\Service\Mailer\Mailer;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Vich\UploaderBundle\Storage\StorageInterface;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

#[AllowMockObjectsWithoutExpectations]
class ContratSubscriberTest extends TestCase
{
    private $mailer;
    private $urlGenerator;
    private $kernel;
    private $uploaderHelper;
    private $storage;
    private $subscriber;
    private $tempDir;

    protected function setUp(): void
    {
        $this->mailer = $this->createMock(Mailer::class);
        $this->urlGenerator = $this->createMock(UrlGeneratorInterface::class);
        $this->kernel = $this->createMock(KernelInterface::class);
        $this->storage = $this->createMock(StorageInterface::class);
        $this->uploaderHelper = new UploaderHelper($this->storage); // Real class as it's final
        
        $this->tempDir = sys_get_temp_dir() . '/contrat_test_' . uniqid();
        mkdir($this->tempDir . '/public', 0777, true);
        
        $this->subscriber = new ContratSubscriber(
            $this->mailer,
            $this->urlGenerator,
            $this->kernel,
            $this->uploaderHelper
        );
        
        $_ENV['CONTRAT_BASEURL'] = 'https://baseurl.com';
    }
    
    protected function tearDown(): void
    {
        $this->removeDirectory($this->tempDir);
    }

    public function testOnContratSendWithAttachment()
    {
        // 1. Setup File
        $relativePath = '/uploads/contrats/c1.pdf';
        mkdir(dirname($this->tempDir . '/public' . $relativePath), 0777, true);
        file_put_contents($this->tempDir . '/public' . $relativePath, 'PDF Content');
        
        $this->kernel->method('getProjectDir')->willReturn($this->tempDir);

        // 2. Setup Entities
        $customer = $this->createMock(Customer::class);
        $customer->method('getEmail')->willReturn('cust@test.com');
        $customer->method('getSurname')->willReturn('John');
        $customer->method('getName')->willReturn('Doe');

        $contrat = $this->createMock(Contrats::class);
        $contrat->method('getCustomer')->willReturn($customer);
        $contrat->method('getNumReservation')->willReturn('RES-123');
        
        $this->storage->method('resolveUri')->willReturn($relativePath);

        $event = new ContratEvent($contrat);

        // 3. Expectations
        $this->urlGenerator->expects($this->once())
            ->method('generate')
            ->with('gestion_contrat_view', ['num' => 'RES-123']);

        $this->mailer->expects($this->once())
            ->method('send')
            ->with(
                'cust@test.com',
                'John Doe',
                '[Ludikevent] - Contrat de location N°RES-123',
                'mails/sign/contrat.twig',
                $this->anything(),
                $this->callback(function($attachments) {
                    return count($attachments) === 1;
                })
            );

        $this->subscriber->onContratSend($event);
    }
    
    public function testOnContratSendWithoutAttachment()
    {
        // No file created
        $this->kernel->method('getProjectDir')->willReturn($this->tempDir);
        
        $customer = $this->createMock(Customer::class);
        $customer->method('getEmail')->willReturn('cust@test.com'); // Mock email
        $contrat = $this->createMock(Contrats::class);
        $contrat->method('getCustomer')->willReturn($customer);
        $contrat->method('getNumReservation')->willReturn('RES-123');

        $this->storage->method('resolveUri')->willReturn(null);

        $event = new ContratEvent($contrat);

        $this->mailer->expects($this->once())
            ->method('send')
            ->with(
                $this->anything(),
                $this->anything(),
                $this->anything(),
                $this->anything(),
                $this->anything(),
                [] // Empty attachments
            );

        $this->subscriber->onContratSend($event);
    }

    private function removeDirectory($dir) {
        if (!is_dir($dir)) return;
        $files = array_diff(scandir($dir), array('.','..'));
        foreach ($files as $file) {
            (is_dir("$dir/$file")) ? $this->removeDirectory("$dir/$file") : unlink("$dir/$file");
        }
        rmdir($dir);
    }
}
