<?php

namespace Tests\Unit\Services\Badges;

use App\Services\Badges\BadgePdfService;
use App\Services\Badges\BadgePrintLogService;
use App\Services\Badges\BadgeTextFormatter;
use App\Services\Badges\BadgeUserLookupService;
use Mockery;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Tests\TestCase;

class BadgePdfServiceTest extends TestCase
{
    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    public function test_generate_returns_pdf_response_and_logs_prints(): void
    {
        $lookup = Mockery::mock(BadgeUserLookupService::class);
        $printLog = Mockery::mock(BadgePrintLogService::class);
        $formatter = new BadgeTextFormatter();

        $lookup->shouldReceive('getUserInfoById')
            ->once()
            ->with(10, '2025-2026')
            ->andReturn([
                'user_id' => 10,
                'name' => 'John Doe',
                'role' => 'Teacher',
                'roles' => 'Teacher',
                'role_name_raw' => 'teacher',
                'roles_raw' => 'teacher',
                'class_section_name' => '3-A',
                'school_name' => 'Al Rahma Sunday School',
                'school_logo' => null,
                'isgl_logo' => null,
                'school_year' => '2025-2026',
            ]);

        $printLog->shouldReceive('logSafely')
            ->once()
            ->with([10], 1, '2025-2026', [], [], 1);

        $service = new BadgePdfService($lookup, $printLog, $formatter);

        $response = $service->generate(
            userIds: [10],
            schoolYear: '2025-2026',
            rolesMap: [],
            classesMap: [],
            actorId: 1
        );

        $this->assertInstanceOf(SymfonyResponse::class, $response);
        $this->assertSame('application/pdf', $response->headers->get('Content-Type'));
        $this->assertStringContainsString('inline; filename="Staff_Badges.pdf"', $response->headers->get('Content-Disposition'));
        $this->assertNotEmpty($response->getContent());
    }

    public function test_generate_returns_empty_state_pdf_when_no_valid_users_found(): void
    {
        $lookup = Mockery::mock(BadgeUserLookupService::class);
        $printLog = Mockery::mock(BadgePrintLogService::class);
        $formatter = new BadgeTextFormatter();

        $lookup->shouldReceive('getUserInfoById')
            ->once()
            ->with(99, null)
            ->andReturn(null);

        $printLog->shouldReceive('logSafely')
            ->once()
            ->with([99], null, null, [], [], 1);

        $service = new BadgePdfService($lookup, $printLog, $formatter);

        $response = $service->generate(
            userIds: [99],
            schoolYear: null,
            rolesMap: [],
            classesMap: [],
            actorId: null
        );

        $this->assertSame('application/pdf', $response->headers->get('Content-Type'));
        $this->assertNotEmpty($response->getContent());
    }

    public function test_generate_deduplicates_same_badge_content(): void
    {
        $lookup = Mockery::mock(BadgeUserLookupService::class);
        $printLog = Mockery::mock(BadgePrintLogService::class);
        $formatter = new BadgeTextFormatter();

        $userInfo = [
            'user_id' => 10,
            'name' => 'John Doe',
            'role' => 'Teacher',
            'roles' => 'Teacher',
            'role_name_raw' => 'teacher',
            'roles_raw' => 'teacher',
            'class_section_name' => '3-A',
            'school_name' => 'Al Rahma Sunday School',
            'school_logo' => null,
            'isgl_logo' => null,
            'school_year' => '2025-2026',
        ];

        $lookup->shouldReceive('getUserInfoById')->once()->andReturn($userInfo);

        $printLog->shouldReceive('logSafely')
            ->once()
            ->with([10], 7, '2025-2026', [], [], 1);

        $service = new BadgePdfService($lookup, $printLog, $formatter);

        $response = $service->generate(
            userIds: [10, 10],
            schoolYear: '2025-2026',
            rolesMap: [],
            classesMap: [],
            actorId: 7
        );

        $this->assertSame(200, $response->getStatusCode());
        $this->assertSame('application/pdf', $response->headers->get('Content-Type'));
    }
}
