<?php

namespace App\Services;

use App\Models\Result;
use App\Models\ResultApproval;
use App\Models\User;
use App\Models\SchoolClass;
use App\Models\Subject;
use App\Models\SchoolSession;
use Illuminate\Support\Facades\DB;

class ResultService
{
    public function createOrUpdateResult($data)
    {
        // Check if student has result approval for this session
        $approval = \App\Models\ResultApproval::where('student_id', $data['student_id'])
            ->where('session_id', $data['session_id'])
            ->first();
        
        $resultData = [
            'ca_score' => $data['ca_score'],
            'exam_score' => $data['exam_score'],
            'ca_absent' => $data['ca_absent'] ?? false,
            'exam_absent' => $data['exam_absent'] ?? false,
        ];
        
        // If approval exists, set approval fields
        if ($approval) {
            $resultData['approved'] = true;
            $resultData['approved_at'] = $approval->created_at;
            $resultData['approved_by'] = $approval->approved_by;
        }
        
        return Result::updateOrCreate(
            [
                'student_id' => $data['student_id'],
                'session_id' => $data['session_id'],
                'subject_id' => $data['subject_id'],
            ],
            $resultData
        );
    }

    public function getStudentsByClass($classId)
    {
        return User::whereHas('batch', function ($query) use ($classId) {
            $query->where('school_class_id', $classId);
        })->where('active', true)->orderBy('firstname')->get();
    }
    
    public function getStudentsByBatch($batchId)
    {
        return User::where('batch_id', $batchId)
            ->where('active', true)
            ->orderBy('firstname')
            ->get();
    }

    public function getSubjectsByClass($classId)
    {
        $class = SchoolClass::with('subjects')->find($classId);
        return $class ? $class->subjects : collect();
    }

    public function getStudentResults($studentId, $sessionId)
    {
        return Result::with(['subject', 'session'])
            ->where('student_id', $studentId)
            ->where('session_id', $sessionId)
            ->get();
    }

    public function approveResults($studentIds, $sessionId, $approvalData, $approvedBy)
    {
        DB::transaction(function () use ($studentIds, $sessionId, $approvalData, $approvedBy) {
            // Get current session and class info for snapshot
            $session = SchoolSession::find($sessionId);
            $approverUser = User::find($approvedBy);
            
            foreach ($studentIds as $studentId) {
                $student = User::find($studentId);
                if (!$student || !$student->batch) continue;
                
                // Get class subjects with aliases for snapshot
                $class = $student->batch->schoolClass;
                $subjectsSnapshot = $this->createSubjectsSnapshot($class->id);
                $classSnapshot = $this->createClassSnapshot($class->id);
                
                // Update ALL results for this student and session as approved
                Result::where('student_id', $studentId)
                    ->where('session_id', $sessionId)
                    ->update([
                        'approved' => true,
                        'approved_at' => now(),
                        'approved_by' => $approvedBy,
                    ]);
                
                // Check for existing approval
                $existingApproval = ResultApproval::withTrashed()
                    ->where('student_id', $studentId)
                    ->where('session_id', $sessionId)
                    ->first();
                
                $approvalRecord = null;
                
                if ($existingApproval && $existingApproval->trashed()) {
                    // Restore and update the soft-deleted approval
                    $existingApproval->restore();
                    $existingApproval->update(array_merge($approvalData, [
                        'approved_by' => $approvedBy,
                        'subjects_snapshot' => $subjectsSnapshot,
                        'class_snapshot' => $classSnapshot,
                        'annual_pass_percentage' => $session->annual_pass_percentage ?? settings('annual_pass_percentage', 50),
                    ]));
                    $approvalRecord = $existingApproval;
                } else {
                    // Create new or update existing approval
                    $approvalRecord = ResultApproval::updateOrCreate(
                        [
                            'student_id' => $studentId,
                            'session_id' => $sessionId,
                        ],
                        array_merge($approvalData, [
                            'approved_by' => $approvedBy,
                            'subjects_snapshot' => $subjectsSnapshot,
                            'class_snapshot' => $classSnapshot,
                            'annual_pass_percentage' => $session->annual_pass_percentage ?? settings('annual_pass_percentage', 50),
                        ])
                    );
                }
                
                // Log the approval action
                if ($approvalRecord) {
                    $approvalRecord->logApprovalAction('approved', $approvedBy, $approverUser->name);
                }
            }
        });
    }
    
    public function disapproveResults($studentIds, $sessionId, $disapprovedBy)
    {
        DB::transaction(function () use ($studentIds, $sessionId, $disapprovedBy) {
            $disapproverUser = User::find($disapprovedBy);
            
            foreach ($studentIds as $studentId) {
                // Update results as not approved
                Result::where('student_id', $studentId)
                    ->where('session_id', $sessionId)
                    ->update([
                        'approved' => false,
                        'approved_at' => null,
                        'approved_by' => null,
                    ]);
                
                // Find and log disapproval, then soft delete
                $approval = ResultApproval::where('student_id', $studentId)
                    ->where('session_id', $sessionId)
                    ->first();
                
                if ($approval) {
                    $approval->logApprovalAction('disapproved', $disapprovedBy, $disapproverUser->name);
                    $approval->delete(); // Soft delete
                }
            }
        });
    }
    
    private function createSubjectsSnapshot($classId)
    {
        $class = SchoolClass::with(['subjects', 'subjectAliases'])->find($classId);
        if (!$class) return [];
        
        $snapshot = [];
        foreach ($class->subjects as $subject) {
            $alias = $class->subjectAliases->where('subject_id', $subject->id)->first();
            $snapshot[] = [
                'id' => $subject->id,
                'name' => $subject->name,
                'alias' => $alias ? $alias->alias : null,
                'display_name' => $alias && $alias->alias ? $alias->alias : $subject->name,
            ];
        }
        
        return $snapshot;
    }
    
    private function createClassSnapshot($classId)
    {
        $class = SchoolClass::find($classId);
        if (!$class) return null;
        
        return [
            'id' => $class->id,
            'name' => $class->name,
            'alias' => $class->alias,
            'display_name' => $class->alias ?: $class->name,
        ];
    }

    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 getAccessibleStudentsForUser($user)
    {
        $userClasses = $this->getClassesForUser($user);
        $allStudents = collect();
        
        foreach ($userClasses as $class) {
            $batches = \App\Models\Batch::where('school_class_id', $class->id)
                ->where('is_active', true)
                ->get();
            foreach ($batches as $batch) {
                $batchStudents = $this->getStudentsByBatch($batch->id);
                $allStudents = $allStudents->merge($batchStudents);
            }
        }
        
        return $allStudents;
    }
}