<?php

namespace App\Services;

use App\Models\Exam;
use App\Models\Grade;
use App\Models\Answer;
use App\Support\AnswerEvaluator;

class GradingService
{
    /**
     * Calculate grade summary based on answers and exam weights
     */
    public static function calculateGradeSummary(Exam $exam, $answers): array
    {
        $weights = $exam->getWeights();
        $groupedByType = [];

        foreach ($answers as $answer) {
            $type = $answer->question->type ?? 'pg';
            $groupedByType[$type][] = $answer;
        }

        $totalWeightedScore = 0;
        $totalCorrect = 0;

        foreach ($weights as $type => $weight) {
            $weight = floatval($weight);
            if ($weight <= 0 || !isset($groupedByType[$type])) {
                continue;
            }

            $questionsOfType = $groupedByType[$type];
            $countOfType = count($questionsOfType);
            if ($countOfType === 0) {
                continue;
            }

            $sumScore = 0;

            foreach ($questionsOfType as $answer) {
                if (in_array($type, ['isian', 'uraian'])) {
                    // Manual types: use manual_score if graded, otherwise auto-grade for isian
                    if ($answer->is_graded === 'Y' && !is_null($answer->manual_score)) {
                        $sumScore += floatval($answer->manual_score);
                    } elseif ($type === 'isian' && $answer->is_correct === 'Y') {
                        $sumScore += 100;
                    }
                    // Count correct for both isian and uraian
                    if ($answer->is_correct === 'Y') {
                        $totalCorrect++;
                    }
                } else {
                    // Automatic types (pg, pg_kompleks, menjodohkan)
                    if ($answer->is_correct === 'Y') {
                        $sumScore += 100;
                        $totalCorrect++;
                    }
                }
            }

            $avgScore = $sumScore / $countOfType;
            $totalWeightedScore += $avgScore * ($weight / 100);
        }

        return [
            'total_correct' => $totalCorrect,
            'grade' => round($totalWeightedScore, 2),
        ];
    }

    /**
     * Sync automatic answers
     */
    public static function syncAutomaticAnswers(int $examId, int $studentId, ?int $examSessionId = null, bool $ordered = true)
    {
        $query = Answer::with('question')
            ->where('exam_id', $examId)
            ->where('student_id', $studentId);

        if ($examSessionId !== null) {
            $query->where('exam_session_id', $examSessionId);
        }

        if ($ordered) {
            $query->orderBy('question_order', 'ASC');
        }

        $answers = $query->get();

        foreach ($answers as $answer) {
            // Skip manually graded answers — don't overwrite teacher's correction
            if ($answer->is_graded === 'Y') {
                continue;
            }

            if (!AnswerEvaluator::isAutomaticallyGradable($answer->question->type ?? null)) {
                continue;
            }

            $evaluated = AnswerEvaluator::evaluate($answer->question, $answer->answer);

            if ($answer->is_correct !== $evaluated) {
                $answer->is_correct = $evaluated;
                $answer->save();
            }
        }

        return $answers;
    }

    /**
     * Refresh grade summary in database
     */
    public static function refreshGradeSummary(Exam $exam, int $studentId, ?int $examSessionId = null, $answers = null): void
    {
        if ($answers === null) {
            $answers = self::syncAutomaticAnswers($exam->id, $studentId, $examSessionId, false);
        }

        $summary = self::calculateGradeSummary($exam, $answers);

        $query = Grade::where('exam_id', $exam->id)
            ->where('student_id', $studentId);

        if ($examSessionId !== null) {
            $query->where('exam_session_id', $examSessionId);
        }

        $grade = $query->first();

        if ($grade) {
            $grade->total_correct = $summary['total_correct'];
            $grade->grade = $summary['grade'];
            $grade->save();
        }
    }
}
