<?php

namespace Tests\Feature\Api\Administrator;

use App\Models\User;
use App\Services\Administrator\AdministratorEnrollmentQueryService;
use App\Services\Administrator\AdministratorEnrollmentStatusService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use Mockery;
use Tests\TestCase;

class AdministratorEnrollmentControllerTest extends TestCase
{
    use RefreshDatabase;

    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    public function test_guest_cannot_update_enrollment_statuses(): void
    {
        $response = $this->postJson('/api/v1/administrator/enrollment-withdrawal/update-statuses', [
            'enrollment_status' => [
                10 => 'enrolled',
            ],
        ]);

        $response->assertStatus(401);
    }

    public function test_can_fetch_enrollment_withdrawal_data(): void
    {
        $user = User::factory()->create();
        Sanctum::actingAs($user);

        $mock = Mockery::mock(AdministratorEnrollmentQueryService::class);
        $mock->shouldReceive('enrollmentWithdrawalData')
            ->once()
            ->with('2025-2026')
            ->andReturn([
                'students' => [],
                'classes' => [],
                'semester' => 'Fall',
                'school_year' => '2025-2026',
                'schoolYears' => ['2025-2026'],
            ]);

        $this->app->instance(AdministratorEnrollmentQueryService::class, $mock);

        $response = $this->getJson('/api/v1/administrator/enrollment-withdrawal?schoolYear=2025-2026');

        $response->assertOk()
            ->assertJson([
                'semester' => 'Fall',
                'school_year' => '2025-2026',
            ]);
    }

    public function test_can_fetch_new_students(): void
    {
        $user = User::factory()->create();
        Sanctum::actingAs($user);

        $mock = Mockery::mock(AdministratorEnrollmentQueryService::class);
        $mock->shouldReceive('newStudentsData')
            ->once()
            ->andReturn([
                'new_students' => [],
                'total_new' => 0,
            ]);

        $this->app->instance(AdministratorEnrollmentQueryService::class, $mock);

        $response = $this->getJson('/api/v1/administrator/enrollment-withdrawal/new-students');

        $response->assertOk()
            ->assertJson([
                'new_students' => [],
                'total_new' => 0,
            ]);
    }

    public function test_update_statuses_requires_valid_status_values(): void
    {
        $user = User::factory()->create();
        Sanctum::actingAs($user);

        $response = $this->postJson('/api/v1/administrator/enrollment-withdrawal/update-statuses', [
            'enrollment_status' => [
                10 => 'bad-status',
            ],
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['enrollment_status.10']);
    }

    public function test_update_statuses_calls_service(): void
    {
        $user = User::factory()->create();
        Sanctum::actingAs($user);

        $payload = [
            'enrollment_status' => [
                10 => 'enrolled',
                11 => 'payment pending',
            ],
        ];

        $mock = Mockery::mock(AdministratorEnrollmentStatusService::class);
        $mock->shouldReceive('updateStatuses')
            ->once()
            ->with($payload['enrollment_status'], $user->id)
            ->andReturn([
                'message' => 'Enrollment statuses updated and notifications sent.',
                'status' => 200,
            ]);

        $this->app->instance(AdministratorEnrollmentStatusService::class, $mock);

        $response = $this->postJson('/api/v1/administrator/enrollment-withdrawal/update-statuses', $payload);

        $response->assertOk()
            ->assertJson([
                'message' => 'Enrollment statuses updated and notifications sent.',
            ]);
    }
}