<?php

namespace App\Services\Grading;

use App\Models\ScoreComment;
use App\Models\SemesterScore;
use App\Models\Student;
use App\Services\Scores\SemesterScoreService;
use RuntimeException;

class GradingRefreshService
{
    public function __construct(private SemesterScoreService $semesterScoreService)
    {
    }

    public function refreshSemesterScores(int $classSectionId, string $semester, string $schoolYear): void
    {
        if ($classSectionId <= 0) {
            throw new RuntimeException('Missing class section.');
        }

        $studentTeacherInfo = Student::getStudentInfoByClassSectionId(
            $classSectionId,
            $semester,
            $schoolYear
        );
        if (empty($studentTeacherInfo)) {
            throw new RuntimeException('No students found for this class/term.');
        }

        $this->semesterScoreService->updateScoresForStudents($studentTeacherInfo, $semester, $schoolYear);
        $this->refreshAttendanceComments($classSectionId, $semester, $schoolYear);
    }

    private function refreshAttendanceComments(int $classSectionId, string $semester, string $schoolYear): void
    {
        if (!function_exists('attendance_comment_from_score')) {
            return;
        }

        $scoreRows = SemesterScore::query()
            ->select(['student_id', 'attendance_score'])
            ->where('class_section_id', $classSectionId)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->get();

        if ($scoreRows->isEmpty()) {
            return;
        }

        $studentIds = $scoreRows->pluck('student_id')->map(fn ($v) => (int) $v)->unique()->values()->all();
        if (empty($studentIds)) {
            return;
        }

        $students = Student::query()
            ->select(['id', 'firstname'])
            ->whereIn('id', $studentIds)
            ->get();
        $nameMap = [];
        foreach ($students as $student) {
            $nameMap[(int) $student->id] = (string) ($student->firstname ?? '');
        }

        $existing = ScoreComment::query()
            ->where('score_type', 'attendance')
            ->where('class_section_id', $classSectionId)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->whereIn('student_id', $studentIds)
            ->get();
        $existingByStudent = [];
        foreach ($existing as $row) {
            $existingByStudent[(int) $row->student_id] = $row;
        }

        foreach ($scoreRows as $row) {
            $studentId = (int) $row->student_id;
            if ($studentId <= 0) {
                continue;
            }
            $score = $row->attendance_score !== null ? (float) $row->attendance_score : null;
            if ($score === null) {
                continue;
            }
            $auto = attendance_comment_from_score($score, $nameMap[$studentId] ?? '');
            if ($auto === null) {
                continue;
            }

            if (isset($existingByStudent[$studentId])) {
                $existingByStudent[$studentId]->update([
                    'comment' => $auto,
                ]);
            } else {
                ScoreComment::query()->create([
                    'student_id' => $studentId,
                    'class_section_id' => $classSectionId,
                    'score_type' => 'attendance',
                    'semester' => $semester,
                    'school_year' => $schoolYear,
                    'comment' => $auto,
                    'commented_by' => null,
                    'created_at' => now(),
                ]);
            }
        }
    }
}
