<?php

namespace Modules\Students\Services;

use Modules\Students\Models\Student;
use Modules\Results\Models\StudentResultSummary;
use Modules\Results\Models\Result;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class StudentService
{
    /**
     * Create a new student with user account
     */
    public function createStudent(array $data): Student
    {
        // Create user account
        $user = User::create([
            'name' => $data['first_name'] . ' ' . $data['last_name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password'] ?? 'password123'),
            'role' => 'student',
            'is_active' => true,
        ]);

        // Generate unique student ID if not provided
        if (!isset($data['student_id'])) {
            $data['student_id'] = $this->generateStudentId();
        }

        // Create student profile
        $student = Student::create([
            'user_id' => $user->id,
            'student_id' => $data['student_id'],
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'date_of_birth' => $data['date_of_birth'],
            'gender' => $data['gender'],
            'address' => $data['address'] ?? null,
            'phone' => $data['phone'] ?? null,
            'emergency_contact' => $data['emergency_contact'] ?? null,
            'admission_date' => $data['admission_date'],
            'is_active' => true,
        ]);

        // Assign guardians if provided
        if (isset($data['guardians']) && is_array($data['guardians'])) {
            foreach ($data['guardians'] as $guardianData) {
                $student->guardians()->attach($guardianData['guardian_id'], [
                    'relationship' => $guardianData['relationship'],
                ]);
            }
        }

        return $student->load(['user', 'guardians']);
    }

    /**
     * Update student information
     */
    public function updateStudent(Student $student, array $data): Student
    {
        // Update user account
        $userUpdateData = [
            'name' => $data['first_name'] . ' ' . $data['last_name'],
        ];

        if (isset($data['email'])) {
            $userUpdateData['email'] = $data['email'];
        }

        if (isset($data['password']) && !empty($data['password'])) {
            $userUpdateData['password'] = Hash::make($data['password']);
        }

        $student->user->update($userUpdateData);

        // Update student profile
        $studentUpdateData = [
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'date_of_birth' => $data['date_of_birth'],
            'gender' => $data['gender'],
            'address' => $data['address'] ?? null,
            'phone' => $data['phone'] ?? null,
            'emergency_contact' => $data['emergency_contact'] ?? null,
            'admission_date' => $data['admission_date'],
        ];

        if (isset($data['student_id'])) {
            $studentUpdateData['student_id'] = $data['student_id'];
        }

        $student->update($studentUpdateData);

        // Update guardians if provided
        if (isset($data['guardians']) && is_array($data['guardians'])) {
            // Detach existing guardians
            $student->guardians()->detach();
            
            // Attach new guardians
            foreach ($data['guardians'] as $guardianData) {
                $student->guardians()->attach($guardianData['guardian_id'], [
                    'relationship' => $guardianData['relationship'],
                ]);
            }
        }

        return $student->load(['user', 'guardians']);
    }

    /**
     * Get performance summary for a student
     */
    public function getPerformanceSummary(int $studentId, int $academicYearId): array
    {
        // Get latest result summary
        $resultSummary = StudentResultSummary::where('student_id', $studentId)
            ->where('academic_year_id', $academicYearId)
            ->latest('computed_at')
            ->first();

        // Get subject-wise performance
        $subjectPerformance = Result::where('student_id', $studentId)
            ->where('academic_year_id', $academicYearId)
            ->with(['subject', 'examType'])
            ->get()
            ->groupBy('subject_id')
            ->map(function ($results) {
                $subject = $results->first()->subject;
                $latestResult = $results->sortByDesc('entered_at')->first();
                
                return [
                    'subject' => $subject,
                    'latest_marks' => $latestResult->marks,
                    'latest_grade' => $latestResult->grade,
                    'latest_points' => $latestResult->points,
                    'exam_type' => $latestResult->examType,
                    'total_exams' => $results->count(),
                    'average_marks' => $results->avg('marks'),
                ];
            });

        // Get exam type performance
        $examTypePerformance = Result::where('student_id', $studentId)
            ->where('academic_year_id', $academicYearId)
            ->with(['examType'])
            ->get()
            ->groupBy('exam_type_id')
            ->map(function ($results) {
                $examType = $results->first()->examType;
                
                return [
                    'exam_type' => $examType,
                    'total_subjects' => $results->count(),
                    'average_marks' => $results->avg('marks'),
                    'total_points' => $results->sum('points'),
                    'highest_marks' => $results->max('marks'),
                    'lowest_marks' => $results->min('marks'),
                ];
            });

        // Calculate trends (improvement/decline)
        $trends = $this->calculatePerformanceTrends($studentId, $academicYearId);

        return [
            'summary' => $resultSummary,
            'subject_performance' => $subjectPerformance->values(),
            'exam_type_performance' => $examTypePerformance->values(),
            'trends' => $trends,
            'statistics' => [
                'total_subjects' => $subjectPerformance->count(),
                'total_exams_taken' => Result::where('student_id', $studentId)
                    ->where('academic_year_id', $academicYearId)
                    ->count(),
                'subjects_above_average' => $subjectPerformance->filter(function ($perf) {
                    return $perf['average_marks'] >= 50; // Assuming 50 is average
                })->count(),
            ],
        ];
    }

    /**
     * Calculate performance trends
     */
    private function calculatePerformanceTrends(int $studentId, int $academicYearId): array
    {
        $results = Result::where('student_id', $studentId)
            ->where('academic_year_id', $academicYearId)
            ->with(['examType'])
            ->orderBy('entered_at')
            ->get();

        if ($results->count() < 2) {
            return ['trend' => 'insufficient_data'];
        }

        // Group by exam type and calculate trends
        $examTypeTrends = $results->groupBy('exam_type_id')->map(function ($examResults) {
            if ($examResults->count() < 2) {
                return ['trend' => 'insufficient_data'];
            }

            $first = $examResults->first();
            $last = $examResults->last();
            
            $averageFirst = $examResults->take(ceil($examResults->count() / 2))->avg('marks');
            $averageLast = $examResults->skip(floor($examResults->count() / 2))->avg('marks');
            
            $trend = $averageLast > $averageFirst ? 'improving' : 
                    ($averageLast < $averageFirst ? 'declining' : 'stable');
            
            return [
                'exam_type' => $first->examType->name,
                'trend' => $trend,
                'change' => round($averageLast - $averageFirst, 2),
                'change_percentage' => $averageFirst > 0 ? round((($averageLast - $averageFirst) / $averageFirst) * 100, 2) : 0,
            ];
        });

        // Overall trend
        $overallAverage = $results->avg('marks');
        $recentAverage = $results->sortByDesc('entered_at')->take(5)->avg('marks');
        $earlierAverage = $results->sortBy('entered_at')->take(5)->avg('marks');
        
        $overallTrend = $recentAverage > $earlierAverage ? 'improving' : 
                       ($recentAverage < $earlierAverage ? 'declining' : 'stable');

        return [
            'overall' => [
                'trend' => $overallTrend,
                'current_average' => round($overallAverage, 2),
                'recent_average' => round($recentAverage, 2),
                'earlier_average' => round($earlierAverage, 2),
                'change' => round($recentAverage - $earlierAverage, 2),
            ],
            'by_exam_type' => $examTypeTrends->values(),
        ];
    }

    /**
     * Generate unique student ID
     */
    private function generateStudentId(): string
    {
        $year = date('Y');
        $prefix = 'STU' . $year;
        
        // Get the last student ID for this year
        $lastStudent = Student::where('student_id', 'like', $prefix . '%')
            ->orderBy('student_id', 'desc')
            ->first();

        if ($lastStudent) {
            $lastNumber = (int) substr($lastStudent->student_id, -4);
            $newNumber = $lastNumber + 1;
        } else {
            $newNumber = 1;
        }

        return $prefix . str_pad($newNumber, 4, '0', STR_PAD_LEFT);
    }

    /**
     * Get student enrollment history
     */
    public function getEnrollmentHistory(int $studentId): array
    {
        $student = Student::findOrFail($studentId);
        
        $enrollments = $student->enrollments()
            ->with(['classroom', 'academicYear'])
            ->orderBy('enrolled_at', 'desc')
            ->get();

        return $enrollments->map(function ($enrollment) {
            return [
                'id' => $enrollment->id,
                'classroom' => $enrollment->classroom,
                'academic_year' => $enrollment->academicYear,
                'enrolled_at' => $enrollment->enrolled_at,
                'is_active' => $enrollment->is_active,
                'status' => $enrollment->is_active ? 'Active' : 'Inactive',
            ];
        })->toArray();
    }

    /**
     * Transfer student to different classroom
     */
    public function transferStudent(int $studentId, int $newClassroomId, string $reason = null): bool
    {
        $student = Student::findOrFail($studentId);
        
        // Deactivate current enrollment
        $currentEnrollment = $student->enrollments()
            ->where('is_active', true)
            ->first();

        if ($currentEnrollment) {
            $currentEnrollment->update([
                'is_active' => false,
                'transfer_reason' => $reason,
            ]);
        }

        // Create new enrollment
        $student->enrollments()->create([
            'classroom_id' => $newClassroomId,
            'academic_year_id' => $currentEnrollment->academic_year_id,
            'enrolled_at' => now(),
            'is_active' => true,
        ]);

        return true;
    }
}
