<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Application\Service\Import;

use App\Administration\Application\Service\Import\CsvParser;
use App\Administration\Domain\Model\Import\ParentInvitationImportField;

use function mb_strtolower;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

use function str_contains;

/**
 * Test d'intégration de la chaîne d'import invitations parents avec de vrais fichiers CSV.
 *
 * Parse → Mapping suggestion → Validation des champs
 */
final class ParentImportIntegrationTest extends TestCase
{
    #[Test]
    public function parseSimpleParentCsv(): void
    {
        $parser = new CsvParser();
        $parseResult = $parser->parse($this->fixture('parents_simple.csv'));

        self::assertSame(['Nom élève', 'Email parent 1', 'Email parent 2'], $parseResult->columns);
        self::assertSame(3, $parseResult->totalRows());
        self::assertSame('Dupont Alice', $parseResult->rows[0]['Nom élève']);
        self::assertSame('alice.parent1@email.com', $parseResult->rows[0]['Email parent 1']);
        self::assertSame('alice.parent2@email.com', $parseResult->rows[0]['Email parent 2']);
    }

    #[Test]
    public function parseCommaSeparatedParentCsv(): void
    {
        $parser = new CsvParser();
        $parseResult = $parser->parse($this->fixture('parents_comma.csv'));

        self::assertSame(['Nom élève', 'Email parent 1', 'Email parent 2'], $parseResult->columns);
        self::assertSame(2, $parseResult->totalRows());
        self::assertSame('Dupont Alice', $parseResult->rows[0]['Nom élève']);
    }

    #[Test]
    public function suggestMappingForParentColumns(): void
    {
        $parser = new CsvParser();
        $parseResult = $parser->parse($this->fixture('parents_simple.csv'));

        $mapping = $this->suggestMapping($parseResult->columns);

        self::assertSame(ParentInvitationImportField::STUDENT_NAME->value, $mapping['Nom élève']);
        self::assertSame(ParentInvitationImportField::EMAIL_1->value, $mapping['Email parent 1']);
        self::assertSame(ParentInvitationImportField::EMAIL_2->value, $mapping['Email parent 2']);
    }

    #[Test]
    public function completParentCsvHasExpectedStructure(): void
    {
        $parser = new CsvParser();
        $parseResult = $parser->parse($this->fixture('parents_complet.csv'));

        self::assertSame(8, $parseResult->totalRows());

        // Ligne 3 : Bernard Pierre — email1 manquant
        self::assertSame('Bernard Pierre', $parseResult->rows[2]['Nom élève']);
        self::assertSame('', $parseResult->rows[2]['Email parent 1']);

        // Ligne 4 : nom élève manquant
        self::assertSame('', $parseResult->rows[3]['Nom élève']);
        self::assertSame('orphelin@email.com', $parseResult->rows[3]['Email parent 1']);

        // Ligne 5 : email invalide
        self::assertSame('invalide-email', $parseResult->rows[4]['Email parent 1']);
    }

    #[Test]
    public function requiredFieldsAreCorrect(): void
    {
        $required = ParentInvitationImportField::champsObligatoires();

        self::assertCount(2, $required);
        self::assertContains(ParentInvitationImportField::STUDENT_NAME, $required);
        self::assertContains(ParentInvitationImportField::EMAIL_1, $required);
    }

    #[Test]
    public function email2IsOptional(): void
    {
        self::assertFalse(ParentInvitationImportField::EMAIL_2->estObligatoire());
    }

    /**
     * Reproduit la logique de suggestMapping du controller pour pouvoir la tester.
     *
     * @param list<string> $columns
     *
     * @return array<string, string>
     */
    private function suggestMapping(array $columns): array
    {
        $mapping = [];
        $email1Found = false;

        foreach ($columns as $column) {
            $lower = mb_strtolower($column);

            if ($this->isStudentNameColumn($lower) && !isset($mapping[$column])) {
                $mapping[$column] = ParentInvitationImportField::STUDENT_NAME->value;
            } elseif (str_contains($lower, 'email') || str_contains($lower, 'mail') || str_contains($lower, 'courriel')) {
                if (str_contains($lower, '2') || str_contains($lower, 'parent 2')) {
                    $mapping[$column] = ParentInvitationImportField::EMAIL_2->value;
                } elseif (!$email1Found) {
                    $mapping[$column] = ParentInvitationImportField::EMAIL_1->value;
                    $email1Found = true;
                } else {
                    $mapping[$column] = ParentInvitationImportField::EMAIL_2->value;
                }
            }
        }

        return $mapping;
    }

    private function isStudentNameColumn(string $lower): bool
    {
        return str_contains($lower, 'élève')
            || str_contains($lower, 'eleve')
            || str_contains($lower, 'étudiant')
            || str_contains($lower, 'etudiant')
            || str_contains($lower, 'student')
            || $lower === 'nom';
    }

    private function fixture(string $filename): string
    {
        return __DIR__ . '/../../../../../fixtures/import/' . $filename;
    }
}
