<?php

namespace App\Services;

use App\Models\User;
use App\Models\SchoolClass;
use App\Models\Batch;
use App\Models\SchoolSession;
use App\Models\Result;
use App\Models\ResultApproval;

class ViewResultsService
{
    public function getClassesForUser($user)
    {
        if ($user->isAdmin() || $user->isHeadTeacher()) {
            return SchoolClass::where('is_active', true)->orderBy('order')->get();
        }

        if ($user->isTeacher()) {
            return $user->classes()->where('is_active', true)->orderBy('order')->get();
        }

        return collect();
    }

    public function getBatchesByClass($classId)
    {
        return Batch::where('school_class_id', $classId)
            ->where('is_active', true)
            ->orderBy('name')
            ->get();
    }

    public function getActiveSessions()
    {
        return SchoolSession::orderBy('start_year', 'desc')->get();
    }

    public function getStudentsWithResultStatus($batchId, $sessionId)
    {
        // Only get students who have approved results
        $approvedStudentIds = ResultApproval::where('session_id', $sessionId)
            ->pluck('student_id');

        $students = User::where('batch_id', $batchId)
            ->where('active', true)
            ->whereIn('id', $approvedStudentIds)
            ->orderBy('firstname')
            ->get();

        return $students->map(function ($student) use ($sessionId) {
            $approval = ResultApproval::with('approvedBy')
                ->where('student_id', $student->id)
                ->where('session_id', $sessionId)
                ->first();

            return [
                'student' => $student,
                'has_results' => true,
                'is_approved' => true,
                'approved_by' => $approval ? $approval->approvedBy->name : null,
                'approved_at' => $approval ? $approval->created_at : null,
                'status' => 'Approved'
            ];
        });
    }

    public function getStudentCompleteResult($studentId, $sessionId)
    {
        $student = User::with(['batch.schoolClass'])->find($studentId);
        $session = SchoolSession::find($sessionId);
        
        if (!$student || !$session) {
            return null;
        }

        $approval = ResultApproval::where('student_id', $studentId)
            ->where('session_id', $sessionId)
            ->first();

        // Use snapshot data if approval exists, otherwise use current class subjects
        if ($approval && $approval->subjects_snapshot) {
            $subjects = collect($approval->subjects_snapshot)->map(function ($subjectData) {
                return (object) [
                    'id' => $subjectData['id'],
                    'name' => $subjectData['name'],
                    'display_name' => $subjectData['display_name'],
                ];
            });
            $passPercentage = $approval->annual_pass_percentage;
            
            // Use class snapshot if available
            if ($approval->class_snapshot) {
                $class = (object) $approval->class_snapshot;
            } else {
                $class = $student->batch->schoolClass;
            }
        } else {
            $class = $student->batch->schoolClass;
            $subjects = $this->getSubjectsByClass($class->id);
            $passPercentage = $session->overall_pass_percentage;
        }
        
        $results = Result::with(['subject'])
            ->where('student_id', $studentId)
            ->where('session_id', $sessionId)
            ->get()
            ->keyBy('subject_id');

        // Calculate master list data for single student
        $studentData = [
            'student' => $student,
            'subjects' => [],
            'grand_total' => 0,
            'average' => 0,
            'grades' => ['A' => 0, 'B' => 0, 'C' => 0, 'D' => 0, 'E' => 0, 'F' => 0],
            'position' => 1,
            'position_suffix' => '1st',
            'remark' => 'Pass'
        ];

        foreach ($subjects as $subject) {
            $result = $results->get($subject->id);
            
            if ($result) {
                $total = $result->total_score;
                $grade = $this->calculateGrade($total, $session);
                
                $studentData['subjects'][$subject->id] = [
                    'ca_score' => $result->ca_score,
                    'exam_score' => $result->exam_score,
                    'ca_absent' => $result->ca_absent,
                    'exam_absent' => $result->exam_absent,
                    'total' => $total,
                    'grade' => $grade
                ];
                
                $studentData['grand_total'] += $total;
                $studentData['grades'][$grade]++;
            } else {
                $studentData['subjects'][$subject->id] = [
                    'ca_score' => 0,
                    'exam_score' => 0,
                    'ca_absent' => false,
                    'exam_absent' => false,
                    'total' => 0,
                    'grade' => 'F'
                ];
                $studentData['grades']['F']++;
            }
        }

        $studentData['average'] = $subjects->count() > 0 ? 
            round($studentData['grand_total'] / $subjects->count(), 2) : 0;

        // Calculate pass/fail using snapshot data if available
        $maxPossibleTotal = $subjects->count() * 100;
        $passThreshold = ($maxPossibleTotal * $passPercentage) / 100;
        $studentData['remark'] = $studentData['grand_total'] >= $passThreshold ? 'Pass' : 'Fail';

        return [
            'student' => $student,
            'session' => $session,
            'class' => $class,
            'subjects' => $subjects,
            'studentData' => $studentData,
            'approval' => $approval,
            'pass_percentage' => $passPercentage
        ];
    }

    private function getSubjectsByClass($classId)
    {
        $class = SchoolClass::with(['subjects', 'subjectAliases'])->find($classId);
        
        return $class->subjects->map(function ($subject) use ($class) {
            $alias = $class->subjectAliases->where('subject_id', $subject->id)->first();
            $subject->display_name = $alias ? $alias->alias : $subject->name;
            return $subject;
        });
    }

    public function getStudentResult($studentId, $sessionId)
    {
        return $this->getStudentCompleteResult($studentId, $sessionId);
    }

    private function calculateGrade($score, $session)
    {
        if ($score >= $session->grade_a_min) return 'A';
        if ($score >= $session->grade_b_min) return 'B';
        if ($score >= $session->grade_c_min) return 'C';
        if ($score >= $session->grade_d_min) return 'D';
        if ($score >= $session->grade_e_min) return 'E';
        return 'F';
    }
}