<?php

namespace App\Http\Controllers\School;

use App\Http\Controllers\Controller;
use App\Http\Requests\School\StoreStudentRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class StudentController extends Controller
{
    public function index(Request $request): Response
    {
        $schoolId = $this->currentSchoolId($request);

        $base = DB::table('students')->where('school_id', $schoolId);
        $total = $schoolId ? (clone $base)->count() : 0;
        $incomplete = $schoolId
            ? (clone $base)
                ->where(function ($query): void {
                    $query->whereNull('father_mobile')
                        ->orWhereNull('mother_mobile')
                        ->orWhereNull('home_phone')
                        ->orWhereNull('address');
                })
                ->count()
            : 0;

        $onlineToday = $schoolId
            ? DB::table('users')
                ->where('school_id', $schoolId)
                ->where('role_key', 'student')
                ->whereDate('last_seen_at', today())
                ->count()
            : 0;

        $students = $schoolId
            ? DB::table('students')
                ->leftJoin('grade_levels', 'grade_levels.id', '=', 'students.grade_level_id')
                ->leftJoin('users', 'users.id', '=', 'students.user_id')
                ->leftJoin('class_students', function ($join): void {
                    $join->on('class_students.student_id', '=', 'students.id')
                        ->where('class_students.status', '=', 'active');
                })
                ->where('students.school_id', $schoolId)
                ->select([
                    'students.id',
                    'students.first_name',
                    'students.last_name',
                    'students.student_code',
                    'students.mobile',
                    'students.father_mobile',
                    'students.mother_mobile',
                    'students.home_phone',
                    'students.address',
                    'students.status',
                    'students.grade_level_id',
                    'class_students.classroom_id',
                    'grade_levels.name_fa as grade_name',
                    'users.last_seen_at',
                ])
                ->latest('students.created_at')
                ->limit(50)
                ->get()
            : collect();

        return Inertia::render('School/Students', [
            'metrics' => [
                'total' => (int) $total,
                'incomplete' => (int) $incomplete,
                'onlineToday' => (int) $onlineToday,
            ],
            'gradeOptions' => $this->gradeOptions((int) ($schoolId ?? 0)),
            'classroomOptions' => $this->classroomOptions((int) ($schoolId ?? 0)),
            'students' => $students->map(fn ($student): array => [
                'id' => $student->id,
                'fullName' => trim($student->first_name.' '.$student->last_name),
                'firstName' => $student->first_name,
                'lastName' => $student->last_name,
                'studentCode' => $student->student_code,
                'mobile' => $student->mobile ?? '',
                'fatherMobile' => $student->father_mobile ?? '',
                'motherMobile' => $student->mother_mobile ?? '',
                'homePhone' => $student->home_phone ?? '',
                'address' => $student->address ?? '',
                'gradeLevelId' => $student->grade_level_id,
                'classroomId' => $student->classroom_id,
                'grade' => $student->grade_name ?: '—',
                'profileStatus' => $this->profileStatus($student),
                'lastSeen' => $student->last_seen_at ? $this->jalaliDate($student->last_seen_at, true) : '—',
            ])->values(),
        ]);
    }

    public function store(StoreStudentRequest $request): RedirectResponse
    {
        $schoolId = $this->currentSchoolId($request);

        abort_unless($schoolId, 422, 'مدرسه مشخص نیست.');

        $data = $request->validated();

        $exists = DB::table('students')
            ->where('school_id', $schoolId)
            ->where('student_code', $data['student_code'])
            ->exists();

        if ($exists) {
            return back()->withErrors(['student_code' => 'این کد دانش‌آموزی قبلا در مدرسه ثبت شده است.'])->withInput();
        }

        DB::transaction(function () use ($schoolId, $data): void {
            $studentId = DB::table('students')->insertGetId([
                'school_id' => $schoolId,
                'student_code' => $data['student_code'],
                'first_name' => $data['first_name'],
                'last_name' => $data['last_name'],
                'mobile' => $data['mobile'] ?? null,
                'father_mobile' => $data['father_mobile'] ?? null,
                'mother_mobile' => $data['mother_mobile'] ?? null,
                'home_phone' => $data['home_phone'] ?? null,
                'address' => $data['address'] ?? null,
                'grade_level_id' => $data['grade_level_id'],
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            if (! empty($data['classroom_id'])) {
                DB::table('class_students')->insert([
                    'school_id' => $schoolId,
                    'classroom_id' => $data['classroom_id'],
                    'student_id' => $studentId,
                    'status' => 'active',
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }
        });

        return redirect()->route('school.students')->with('success', 'دانش‌آموز ثبت شد.');
    }

    public function update(Request $request, int $id): RedirectResponse
    {
        $schoolId = $this->currentSchoolId($request);

        abort_unless($schoolId, 422, 'مدرسه مشخص نیست.');

        $exists = DB::table('students')->where('id', $id)->where('school_id', $schoolId)->exists();
        abort_unless($exists, 404, 'دانش‌آموز یافت نشد.');

        $data = $request->validate([
            'student_code' => ['required', 'string', 'max:80'],
            'first_name' => ['required', 'string', 'max:120'],
            'last_name' => ['required', 'string', 'max:120'],
            'mobile' => ['nullable', 'regex:/^09\d{9}$/'],
            'father_mobile' => ['nullable', 'regex:/^09\d{9}$/'],
            'mother_mobile' => ['nullable', 'regex:/^09\d{9}$/'],
            'home_phone' => ['nullable', 'string', 'max:30'],
            'address' => ['nullable', 'string', 'max:400'],
            'grade_level_id' => ['required', 'integer'],
            'classroom_id' => ['nullable', 'integer'],
        ]);

        $codeConflict = DB::table('students')
            ->where('school_id', $schoolId)
            ->where('student_code', $data['student_code'])
            ->where('id', '!=', $id)
            ->exists();

        if ($codeConflict) {
            return back()->withErrors(['student_code' => 'این کد دانش‌آموزی برای دانش‌آموز دیگری ثبت شده است.'])->withInput();
        }

        DB::transaction(function () use ($schoolId, $id, $data): void {
            DB::table('students')->where('id', $id)->update([
                'student_code' => $data['student_code'],
                'first_name' => $data['first_name'],
                'last_name' => $data['last_name'],
                'mobile' => $data['mobile'] ?? null,
                'father_mobile' => $data['father_mobile'] ?? null,
                'mother_mobile' => $data['mother_mobile'] ?? null,
                'home_phone' => $data['home_phone'] ?? null,
                'address' => $data['address'] ?? null,
                'grade_level_id' => $data['grade_level_id'],
                'updated_at' => now(),
            ]);

            DB::table('class_students')->where('student_id', $id)->where('school_id', $schoolId)->delete();

            if (! empty($data['classroom_id'])) {
                DB::table('class_students')->insert([
                    'school_id' => $schoolId,
                    'classroom_id' => $data['classroom_id'],
                    'student_id' => $id,
                    'status' => 'active',
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }
        });

        return redirect()->route('school.students')->with('success', 'اطلاعات دانش‌آموز بروز شد.');
    }

    public function destroy(Request $request, int $id): RedirectResponse
    {
        $schoolId = $this->currentSchoolId($request);

        abort_unless($schoolId, 422, 'مدرسه مشخص نیست.');

        $student = DB::table('students')->where('id', $id)->where('school_id', $schoolId)->first();
        abort_unless($student, 404, 'دانش‌آموز یافت نشد.');

        DB::transaction(function () use ($schoolId, $id): void {
            DB::table('class_students')->where('student_id', $id)->where('school_id', $schoolId)->delete();
            DB::table('students')->where('id', $id)->delete();
        });

        return redirect()->route('school.students')->with('success', 'دانش‌آموز حذف شد.');
    }

    private function profileStatus(object $student): string
    {
        return $student->father_mobile && $student->mother_mobile && $student->home_phone && $student->address
            ? 'تکمیل شده'
            : 'نیازمند تکمیل';
    }

    private function gradeOptions(int $schoolId): array
    {
        if (! $schoolId) {
            return [];
        }

        return DB::table('school_grade_levels')
            ->join('grade_levels', 'grade_levels.id', '=', 'school_grade_levels.grade_level_id')
            ->where('school_grade_levels.school_id', $schoolId)
            ->where('school_grade_levels.enabled', true)
            ->orderBy('grade_levels.number')
            ->get(['grade_levels.id', 'grade_levels.name_fa'])
            ->map(fn ($grade): array => ['value' => $grade->id, 'label' => $grade->name_fa])
            ->values()
            ->all();
    }

    private function classroomOptions(int $schoolId): array
    {
        if (! $schoolId) {
            return [];
        }

        return DB::table('classrooms')
            ->where('school_id', $schoolId)
            ->where('status', 'active')
            ->orderBy('name')
            ->get(['id', 'name'])
            ->map(fn ($classroom): array => ['value' => $classroom->id, 'label' => $classroom->name])
            ->values()
            ->all();
    }
}
