<?php

namespace Tests\Feature\Api\V1\Admin;

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

class AdministratorAbsenceControllerTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_guest_cannot_access_absence_index(): void
    {
        $response = $this->getJson('/api/v1/administrator/absence');

        $response->assertStatus(401);
    }

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

        Sanctum::actingAs($user);

        $mock = Mockery::mock(AdministratorAbsenceService::class);
        $mock->shouldReceive('getAbsenceFormData')
            ->once()
            ->with($user->id)
            ->andReturn([
                'admin_name' => 'Test Admin',
                'semester' => 'Fall',
                'schoolYear' => '2025-2026',
                'existing' => [],
                'availableDates' => ['2026-03-08'],
            ]);

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

        $response = $this->getJson('/api/v1/administrator/absence');

        $response->assertOk()
            ->assertJson([
                'admin_name' => 'Test Admin',
                'semester' => 'Fall',
                'schoolYear' => '2025-2026',
            ]);
    }

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

        Sanctum::actingAs($user);

        $response = $this->postJson('/api/v1/administrator/absence', [
            'dates' => ['2026-03-08'],
            'reason_type' => 'vacation',
            'reason' => '',
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['reason']);
    }

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

        Sanctum::actingAs($user);

        $response = $this->postJson('/api/v1/administrator/absence', [
            'dates' => ['03/08/2026'],
            'reason_type' => 'vacation',
            'reason' => 'Family trip',
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['dates.0']);
    }

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

        Sanctum::actingAs($user);

        $payload = [
            'dates' => ['2026-03-08'],
            'reason_type' => 'vacation',
            'reason' => 'Family trip',
        ];

        $mock = Mockery::mock(AdministratorAbsenceService::class);
        $mock->shouldReceive('submit')
            ->once()
            ->andReturn([
                'message' => '1 day(s) saved as absent.',
                'saved' => 1,
                'dates' => ['2026-03-08'],
                'status' => 200,
            ]);

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

        $response = $this->postJson('/api/v1/administrator/absence', $payload);

        $response->assertOk()
            ->assertJson([
                'message' => '1 day(s) saved as absent.',
                'saved' => 1,
                'dates' => ['2026-03-08'],
            ]);
    }
}