<?php

namespace Tests\Feature\Api\V1\Parents;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;

class ParentAttendanceReportControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_form_returns_students_and_sundays(): void
    {
        $this->seedConfig();
        $parent = $this->seedParent();
        $this->seedStudent($parent->id);

        Sanctum::actingAs($parent);
        $response = $this->getJson('/api/v1/parents/attendance-reports/form');

        $response->assertOk();
        $response->assertJson(['ok' => true]);
        $this->assertNotEmpty($response->json('students'));
        $this->assertNotEmpty($response->json('sundays'));
    }

    public function test_submit_creates_report_and_attendance(): void
    {
        $this->seedConfig();
        $parent = $this->seedParent();
        $studentId = $this->seedStudent($parent->id);
        $this->seedClassSection($studentId);

        $date = $this->nextSunday();
        Sanctum::actingAs($parent);

        $response = $this->postJson('/api/v1/parents/attendance-reports', [
            'student_ids' => [$studentId],
            'date' => $date,
            'type' => 'absent',
            'reason' => 'Sick',
        ]);

        $response->assertStatus(201);
        $response->assertJson(['ok' => true]);

        $this->assertDatabaseHas('parent_attendance_reports', [
            'student_id' => $studentId,
            'report_date' => $date,
            'type' => 'absent',
        ]);
        $this->assertDatabaseHas('attendance_data', [
            'student_id' => $studentId,
            'date' => $date,
            'status' => 'absent',
        ]);
    }

    public function test_check_existing_returns_rows(): void
    {
        $this->seedConfig();
        $parent = $this->seedParent();
        $studentId = $this->seedStudent($parent->id);
        $date = $this->nextSunday();

        DB::table('parent_attendance_reports')->insert([
            'parent_id' => $parent->id,
            'student_id' => $studentId,
            'report_date' => $date,
            'type' => 'late',
            'semester' => 'Fall',
            'school_year' => '2025-2026',
            'status' => 'new',
        ]);

        Sanctum::actingAs($parent);
        $response = $this->postJson('/api/v1/parents/attendance-reports/check-existing', [
            'student_ids' => [$studentId],
            'date' => $date,
            'type' => 'late',
        ]);

        $response->assertOk();
        $response->assertJson(['ok' => true]);
        $this->assertSame($studentId, $response->json('students.0.student_id'));
    }

    public function test_update_report_updates_reason(): void
    {
        $this->seedConfig();
        $parent = $this->seedParent();
        $studentId = $this->seedStudent($parent->id);
        $date = $this->nextSunday();

        $reportId = DB::table('parent_attendance_reports')->insertGetId([
            'parent_id' => $parent->id,
            'student_id' => $studentId,
            'report_date' => $date,
            'type' => 'absent',
            'semester' => 'Fall',
            'school_year' => '2025-2026',
            'status' => 'new',
        ]);

        Sanctum::actingAs($parent);
        $response = $this->patchJson('/api/v1/parents/attendance-reports/' . $reportId, [
            'reason' => 'Family emergency',
        ]);

        $response->assertOk();
        $this->assertDatabaseHas('parent_attendance_reports', [
            'id' => $reportId,
            'reason' => 'Family emergency',
        ]);
    }

    private function seedParent(): User
    {
        $id = DB::table('users')->insertGetId([
            'firstname' => 'Parent',
            'lastname' => 'User',
            'cellphone' => '1234567890',
            'email' => 'parent.attendance@example.com',
            'address_street' => '123 Street',
            'city' => 'City',
            'state' => 'ST',
            'zip' => '12345',
            'accept_school_policy' => 1,
            'password' => bcrypt('password'),
            'user_type' => 'primary',
            'semester' => 'Fall',
            'school_year' => '2025-2026',
            'status' => 'Active',
        ]);

        return User::query()->findOrFail($id);
    }

    private function seedStudent(int $parentId): int
    {
        return DB::table('students')->insertGetId([
            'school_id' => 'S-300',
            'firstname' => 'Evan',
            'lastname' => 'Parent',
            'dob' => '2014-09-01',
            'age' => 11,
            'gender' => 'Male',
            'photo_consent' => 1,
            'parent_id' => $parentId,
            'year_of_registration' => '2025',
            'school_year' => '2025-2026',
            'semester' => 'Fall',
        ]);
    }

    private function seedClassSection(int $studentId): void
    {
        DB::table('classSection')->insert([
            'class_id' => 1,
            'class_section_id' => 10,
            'class_section_name' => '1A',
            'semester' => 'Fall',
            'school_year' => '2025-2026',
        ]);

        DB::table('student_class')->insert([
            'student_id' => $studentId,
            'class_section_id' => 10,
            'semester' => 'Fall',
            'school_year' => '2025-2026',
        ]);
    }

    private function seedConfig(): void
    {
        DB::table('configuration')->insert([
            ['config_key' => 'school_year', 'config_value' => '2025-2026'],
            ['config_key' => 'semester', 'config_value' => 'Fall'],
            ['config_key' => 'date_age_reference', 'config_value' => '2025-12-31'],
            ['config_key' => 'parent_report_cutoff', 'config_value' => '23:59'],
            ['config_key' => 'fall_semester_start', 'config_value' => '2025-09-01'],
            ['config_key' => 'spring_semester_start', 'config_value' => '2026-01-15'],
            ['config_key' => 'last_school_day', 'config_value' => '2026-06-15'],
        ]);
    }

    private function nextSunday(): string
    {
        $dt = new \DateTime('today');
        if ((int) $dt->format('w') !== 0) {
            $dt->modify('next sunday');
        }
        return $dt->format('Y-m-d');
    }
}
