<?php

namespace App\Console\Commands;

use App\Models\ResultMark;
use App\Models\Exam;
use App\Models\Student;
use App\Models\FinalResult;
use App\Models\ExamSubjectRule;
use Illuminate\Console\Command;

class FixResultTotals extends Command
{
    protected $signature = 'fix:result-totals {exam_name?}';
    protected $description = 'Recalculate total_marks from component marks';

    public function handle()
    {
        $examName = $this->argument('exam_name') ?? 'test exam 2025';
        
        $exam = Exam::where('name', $examName)->first();
        
        if (!$exam) {
            $this->error("Exam '{$examName}' not found!");
            $this->info("Available exams:");
            Exam::all()->each(fn($e) => $this->line("  - {$e->name} (ID: {$e->id})"));
            return 1;
        }
        
        $this->info("Processing Exam: {$exam->name} (ID: {$exam->id})");
        $this->info("Session: {$exam->session}, Class: {$exam->class}");
        $this->newLine();
        
        $resultMarks = ResultMark::with('subject', 'student')
            ->where('exam_id', $exam->id)
            ->get();
        
        $this->info("Found {$resultMarks->count()} result records");
        $this->newLine();
        
        $fixed = 0;
        $unchanged = 0;
        
        foreach ($resultMarks as $mark) {
            $oldTotal = $mark->total_marks;
            
            $newTotal = ($mark->first_paper_mcq ?? 0) +
                        ($mark->first_paper_cq ?? 0) +
                        ($mark->first_paper_practical ?? 0) +
                        ($mark->second_paper_mcq ?? 0) +
                        ($mark->second_paper_cq ?? 0) +
                        ($mark->second_paper_practical ?? 0);
            
            $studentName = $mark->student->name ?? 'Unknown';
            $subjectName = $mark->subject->name ?? 'Unknown';

            // Get Rule
            $rule = ExamSubjectRule::where('exam_id', $exam->id)
                ->where('subject_id', $mark->subject_id)
                ->first();
            
            // Calculate GPA/Grade based on Percentage
            $ruleTotal = ($rule && $rule->total_marks > 0) ? $rule->total_marks : 100;
            $percentage = ($newTotal / $ruleTotal) * 100;
            
            $newGpa = ResultMark::calculateGPAFromPercentage($percentage);
            $newGrade = ResultMark::getGradeFromPercentage($percentage);
             
            $passMarks = $rule->pass_marks ?? 33;
            $isFailed = $newTotal < $passMarks;
            
            // Check if ANY value (Total, GPA, Grade) needs update
            if (abs($oldTotal - $newTotal) > 0.01 || 
                abs($mark->subject_gpa - $newGpa) > 0.01 || 
                $mark->subject_grade !== $newGrade ||
                $mark->is_failed !== $isFailed
            ) {
                $this->warn("FIXING: {$studentName} - {$subjectName}");
                $this->line("  Marks: {$oldTotal} -> {$newTotal}");
                $this->line("  Grade: {$mark->subject_grade} -> {$newGrade}");
                
                $mark->update([
                    'total_marks' => $newTotal,
                    'subject_gpa' => $newGpa,
                    'subject_grade' => $newGrade,
                    'is_failed' => $isFailed,
                ]);
                
                $this->info("  ✓ Updated!");
                $this->newLine();
                $fixed++;
            } else {
                $unchanged++;
            }
        }
        
        $this->newLine();
        $this->info("=== Summary ===");
        $this->info("Fixed: {$fixed} records");
        $this->info("Unchanged: {$unchanged} records");
        $this->newLine();
        
        if ($fixed > 0) {
            $this->info("Recalculating final results...");
            
            $students = ResultMark::where('exam_id', $exam->id)
                ->distinct('student_id')
                ->pluck('student_id');
            
            foreach ($students as $studentId) {
                $student = Student::find($studentId);
                if ($student) {
                    $this->line("  Recalculating for: {$student->name}");
                    
                    $resultMarks = ResultMark::where('exam_id', $exam->id)
                        ->where('student_id', $student->id)
                        ->get();
                    
                    $hasFailure = $resultMarks->contains(fn($m) => $m->is_failed === true);
                    $totalMarks = $resultMarks->sum('total_marks');
                    
                    if ($hasFailure) {
                        $gpa = 0.00;
                        $grade = 'F';
                    } else {
                        $gpa = round($resultMarks->avg('subject_gpa'), 2);
                        $grade = $this->getFinalGrade($gpa);
                    }
                    
                    FinalResult::updateOrCreate(
                        ['exam_id' => $exam->id, 'student_id' => $student->id],
                        ['total_marks' => $totalMarks, 'gpa' => $gpa, 'grade' => $grade]
                    );
                }
            }
            
            $this->newLine();
            $this->info("✓ All done! Please check the results on the frontend.");
        } else {
            $this->info("No issues found. All totals are correct!");
        }
        
        return 0;
    }
    
    private function getFinalGrade($gpa)
    {
        if ($gpa >= 5.00) return 'A+';
        if ($gpa >= 4.00) return 'A';
        if ($gpa >= 3.50) return 'A-';
        if ($gpa >= 3.00) return 'B';
        if ($gpa >= 2.00) return 'C';
        if ($gpa >= 1.00) return 'D';
        return 'F';
    }
}
