<?php

namespace Tests\Feature\Api;

use App\Models\User;
use App\Models\Student;
use App\Models\StudentClass;
use App\Models\TeacherClass;
use App\Models\ClassSection;
use App\Models\Configuration;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

class AssignmentApiTest extends TestCase
{
    use RefreshDatabase;

    protected User $user;

    protected function setUp(): void
    {
        parent::setUp();

        $this->user = User::factory()->create();

        // Seed config values used by AssignmentService
        Configuration::query()->updateOrCreate(
            ['config_key' => 'semester'],
            ['config_value' => 'Fall']
        );

        Configuration::query()->updateOrCreate(
            ['config_key' => 'school_year'],
            ['config_value' => '2025-2026']
        );
    }

    #[Test]
    public function it_returns_assignment_sections_json(): void
    {
        Sanctum::actingAs($this->user);

        $section = ClassSection::factory()->create([
            'class_section_name' => 'Grade 5 - A',
        ]);

        $teacher = User::factory()->create([
            'firstname' => 'Ahmad',
            'lastname'  => 'Ali',
        ]);

        TeacherClass::query()->create([
            'teacher_id'        => $teacher->id,
            'class_section_id'  => $section->class_section_id,
            'position'          => 'main',
            'semester'          => 'Fall',
            'school_year'       => '2025-2026',
            'description'       => 'Main teacher assignment',
        ]);

        $student = Student::factory()->create([
            'firstname'          => 'Sara',
            'lastname'           => 'Yousef',
            'is_active'          => 1,
            'gender'             => 'F',
            'registration_grade' => '5',
            'photo_consent'      => 1,
            'tuition_paid'       => 1,
            'school_id'          => 'SCH-1001',
        ]);

        StudentClass::query()->create([
            'student_id'        => $student->id,
            'class_section_id'  => $section->class_section_id,
            'semester'          => 'Fall',
            'school_year'       => '2025-2026',
            'description'       => 'Student assigned',
            'is_active'         => 1, // remove if your table doesn’t have this column
        ]);

        $response = $this->getJson('/api/assignments');

        $response->assertOk()
            ->assertJsonStructure([
                'message',
                'data' => [
                    'classSections' => [
                        '*' => [
                            'class_section_id',
                            'class_section_name',
                            'main_teachers',
                            'teacher_assistants',
                            'students',
                            'semester',
                            'school_year',
                            'description',
                        ]
                    ],
                    'schoolYears',
                    'selectedYear',
                    'selectedSemester',
                    'semester',
                    'current_school_year',
                ],
            ]);

        $response->assertJsonPath('data.classSections.0.class_section_id', $section->class_section_id);
        $response->assertJsonPath('data.classSections.0.main_teachers.0', 'Ahmad Ali');
        $response->assertJsonPath('data.classSections.0.students.0.id', $student->id);
    }

    #[Test]
    public function it_filters_assignments_by_school_year(): void
    {
        Sanctum::actingAs($this->user);

        $section1 = ClassSection::factory()->create(['class_section_name' => 'Grade 4']);
        $section2 = ClassSection::factory()->create(['class_section_name' => 'Grade 6']);

        $teacher = User::factory()->create(['firstname' => 'Test', 'lastname' => 'Teacher']);

        TeacherClass::query()->create([
            'teacher_id'       => $teacher->id,
            'class_section_id' => $section1->class_section_id,
            'position'         => 'main',
            'semester'         => 'Fall',
            'school_year'      => '2024-2025',
        ]);

        TeacherClass::query()->create([
            'teacher_id'       => $teacher->id,
            'class_section_id' => $section2->class_section_id,
            'position'         => 'main',
            'semester'         => 'Fall',
            'school_year'      => '2025-2026',
        ]);

        $response = $this->getJson('/api/assignments?school_year=2025-2026');

        $response->assertOk();

        $sections = $response->json('data.classSections');
        $ids = collect($sections)->pluck('class_section_id')->all();

        $this->assertContains($section2->class_section_id, $ids);
        $this->assertNotContains($section1->class_section_id, $ids);
        $response->assertJsonPath('data.selectedYear', '2025-2026');
    }

    #[Test]
    public function it_creates_or_updates_student_assignment(): void
    {
        Sanctum::actingAs($this->user);

        $student = Student::factory()->create(['is_active' => 1]);
        $section = ClassSection::factory()->create();

        $payload = [
            'student_id'       => $student->id,
            'class_section_id' => $section->class_section_id,
            'semester'         => 'Spring',
            'school_year'      => '2025-2026',
            'description'      => 'Moved after placement review',
        ];

        $response = $this->postJson('/api/assignments', $payload);

        $response->assertCreated()
            ->assertJsonPath('message', 'Assignment saved successfully.');

        $this->assertDatabaseHas('student_class', [
            'student_id'       => $student->id,
            'class_section_id' => $section->class_section_id,
            'semester'         => 'Spring',
            'school_year'      => '2025-2026',
        ]);
    }

    #[Test]
    public function it_validates_required_fields_when_storing_assignment(): void
    {
        Sanctum::actingAs($this->user);

        $response = $this->postJson('/api/assignments', []);

        $response->assertStatus(422)
            ->assertJsonValidationErrors([
                'student_id',
                'class_section_id',
            ]);
    }

    #[Test]
    public function store_is_idempotent_for_same_student_semester_and_year(): void
    {
        Sanctum::actingAs($this->user);

        $student = Student::factory()->create(['is_active' => 1]);
        $sectionA = ClassSection::factory()->create();
        $sectionB = ClassSection::factory()->create();

        // First create
        $this->postJson('/api/assignments', [
            'student_id'       => $student->id,
            'class_section_id' => $sectionA->class_section_id,
            'semester'         => 'Fall',
            'school_year'      => '2025-2026',
        ])->assertCreated();

        // Second call same unique key should update (per service updateOrCreate)
        $this->postJson('/api/assignments', [
            'student_id'       => $student->id,
            'class_section_id' => $sectionA->class_section_id,
            'semester'         => 'Fall',
            'school_year'      => '2025-2026',
            'description'      => 'Reassigned',
        ])->assertCreated();

        $this->assertEquals(
            1,
            StudentClass::query()
                ->where('student_id', $student->id)
                ->where('semester', 'Fall')
                ->where('school_year', '2025-2026')
                ->count()
        );

        $this->assertDatabaseHas('student_class', [
            'student_id'       => $student->id,
            'class_section_id' => $sectionA->class_section_id,
            'semester'         => 'Fall',
            'school_year'      => '2025-2026',
        ]);
    }

    #[Test]
    public function guest_cannot_access_assignment_api_when_auth_is_required(): void
    {
        $response = $this->getJson('/api/assignments');

        $response->assertStatus(401);
    }
}
