<?php

namespace Modules\Guardians\Services;

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

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

        // Create guardian profile
        $guardian = Guardian::create([
            'user_id' => $user->id,
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'phone' => $data['phone'] ?? null,
            'address' => $data['address'] ?? null,
            'occupation' => $data['occupation'] ?? null,
            'is_active' => true,
        ]);

        // Assign students if provided
        if (isset($data['students']) && is_array($data['students'])) {
            foreach ($data['students'] as $studentData) {
                $guardian->students()->attach($studentData['student_id'], [
                    'relationship' => $studentData['relationship'],
                ]);
            }
        }

        return $guardian->load(['user', 'students']);
    }

    /**
     * Update guardian information
     */
    public function updateGuardian(Guardian $guardian, array $data): Guardian
    {
        // 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']);
        }

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

        // Update guardian profile
        $guardianUpdateData = [
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'phone' => $data['phone'] ?? null,
            'address' => $data['address'] ?? null,
            'occupation' => $data['occupation'] ?? null,
        ];

        $guardian->update($guardianUpdateData);

        // Update students if provided
        if (isset($data['students']) && is_array($data['students'])) {
            // Detach existing students
            $guardian->students()->detach();
            
            // Attach new students
            foreach ($data['students'] as $studentData) {
                $guardian->students()->attach($studentData['student_id'], [
                    'relationship' => $studentData['relationship'],
                ]);
            }
        }

        return $guardian->load(['user', 'students']);
    }

    /**
     * Get performance summary for a student (guardian view)
     */
    public function getStudentPerformanceSummary(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' => round($results->avg('marks'), 2),
                    'highest_marks' => $results->max('marks'),
                    'lowest_marks' => $results->min('marks'),
                ];
            });

        // Calculate overall statistics
        $allResults = Result::where('student_id', $studentId)
            ->where('academic_year_id', $academicYearId)
            ->get();

        $overallStats = [
            'total_subjects' => $subjectPerformance->count(),
            'total_exams' => $allResults->count(),
            'average_marks' => round($allResults->avg('marks'), 2),
            'highest_marks' => $allResults->max('marks'),
            'lowest_marks' => $allResults->min('marks'),
            'subjects_above_50' => $subjectPerformance->filter(function ($perf) {
                return $perf['average_marks'] >= 50;
            })->count(),
        ];

        return [
            'summary' => $resultSummary,
            'subject_performance' => $subjectPerformance->values(),
            'overall_stats' => $overallStats,
        ];
    }

    /**
     * Get students with their results for a guardian
     */
    public function getStudentsResults(int $guardianId, ?int $academicYearId = null, ?int $examTypeId = null, ?int $studentId = null): array
    {
        $guardian = Guardian::findOrFail($guardianId);

        $studentsQuery = $guardian->students()->with(['user']);

        if ($studentId) {
            $studentsQuery->where('students.id', $studentId);
        }

        $students = $studentsQuery->get();

        $studentsWithResults = [];

        foreach ($students as $student) {
            $resultsQuery = $student->results()->with(['subject', 'examType', 'classroom']);

            if ($academicYearId) {
                $resultsQuery->where('academic_year_id', $academicYearId);
            }

            if ($examTypeId) {
                $resultsQuery->where('exam_type_id', $examTypeId);
            }

            $results = $resultsQuery->orderBy('entered_at', 'desc')->get();

            $studentsWithResults[] = [
                'student' => $student,
                'results' => $results,
                'statistics' => [
                    'total_results' => $results->count(),
                    'average_marks' => round($results->avg('marks'), 2),
                    'highest_marks' => $results->max('marks'),
                    'lowest_marks' => $results->min('marks'),
                    'pass_count' => $results->where('marks', '>=', 40)->count(),
                ],
            ];
        }

        return $studentsWithResults;
    }

    /**
     * Get recent activities for a guardian
     */
    public function getRecentActivities(int $guardianId, int $limit = 10): array
    {
        $guardian = Guardian::findOrFail($guardianId);

        $activities = [];

        // Get recent results for guardian's students
        $recentResults = Result::whereIn('student_id', $guardian->students->pluck('id'))
            ->with(['student', 'subject', 'examType', 'classroom'])
            ->orderBy('entered_at', 'desc')
            ->limit($limit)
            ->get();

        foreach ($recentResults as $result) {
            $activities[] = [
                'type' => 'result_entered',
                'description' => "New {$result->examType->name} result for {$result->student->full_name} in {$result->subject->name}",
                'data' => [
                    'student' => $result->student->full_name,
                    'subject' => $result->subject->name,
                    'exam_type' => $result->examType->name,
                    'marks' => $result->marks,
                    'grade' => $result->grade,
                    'classroom' => $result->classroom->name,
                ],
                'timestamp' => $result->entered_at,
            ];
        }

        // Sort by timestamp
        usort($activities, function ($a, $b) {
            return $b['timestamp'] <=> $a['timestamp'];
        });

        return array_slice($activities, 0, $limit);
    }

    /**
     * Get dashboard statistics for a guardian
     */
    public function getDashboardStatistics(int $guardianId, ?int $academicYearId = null): array
    {
        $guardian = Guardian::findOrFail($guardianId);

        $studentsCount = $guardian->students()->count();

        if ($studentsCount === 0) {
            return [
                'students_count' => 0,
                'total_results' => 0,
                'average_performance' => 0,
                'subjects_count' => 0,
                'performance_trend' => 'no_data',
            ];
        }

        $studentIds = $guardian->students->pluck('id');

        // Get results statistics
        $resultsQuery = Result::whereIn('student_id', $studentIds);

        if ($academicYearId) {
            $resultsQuery->where('academic_year_id', $academicYearId);
        }

        $results = $resultsQuery->get();
        $totalResults = $results->count();
        $averageMarks = round($results->avg('marks'), 2);

        // Get subjects count
        $subjectsCount = $results->pluck('subject_id')->unique()->count();

        // Calculate performance trend
        $performanceTrend = $this->calculatePerformanceTrend($studentIds, $academicYearId);

        // Get grade distribution
        $gradeDistribution = $results->groupBy('grade')->map(function ($gradeResults) {
            return $gradeResults->count();
        });

        return [
            'students_count' => $studentsCount,
            'total_results' => $totalResults,
            'average_performance' => $averageMarks,
            'subjects_count' => $subjectsCount,
            'performance_trend' => $performanceTrend,
            'grade_distribution' => $gradeDistribution,
            'pass_rate' => $totalResults > 0 ? round(($results->where('marks', '>=', 40)->count() / $totalResults) * 100, 2) : 0,
        ];
    }

    /**
     * Calculate performance trend for guardian's students
     */
    private function calculatePerformanceTrend(array $studentIds, ?int $academicYearId = null): string
    {
        $resultsQuery = Result::whereIn('student_id', $studentIds)
            ->orderBy('entered_at');

        if ($academicYearId) {
            $resultsQuery->where('academic_year_id', $academicYearId);
        }

        $results = $resultsQuery->get();

        if ($results->count() < 10) {
            return 'insufficient_data';
        }

        // Compare first half with second half
        $midPoint = intval($results->count() / 2);
        $firstHalf = $results->take($midPoint);
        $secondHalf = $results->skip($midPoint);

        $firstHalfAverage = $firstHalf->avg('marks');
        $secondHalfAverage = $secondHalf->avg('marks');

        $difference = $secondHalfAverage - $firstHalfAverage;

        if ($difference > 2) {
            return 'improving';
        } elseif ($difference < -2) {
            return 'declining';
        } else {
            return 'stable';
        }
    }

    /**
     * Get comprehensive student report for guardian
     */
    public function getStudentReport(int $guardianId, int $studentId, int $academicYearId): array
    {
        $guardian = Guardian::findOrFail($guardianId);
        
        // Verify student belongs to guardian
        if (!$guardian->students()->where('students.id', $studentId)->exists()) {
            throw new \Exception('Student does not belong to this guardian.');
        }

        $student = Student::findOrFail($studentId);

        // Get performance summary
        $performanceSummary = $this->getStudentPerformanceSummary($studentId, $academicYearId);

        // Get attendance data (if implemented)
        $attendanceData = [];

        // Get behavioral notes (if implemented)
        $behavioralNotes = [];

        return [
            'student' => $student,
            'performance' => $performanceSummary,
            'attendance' => $attendanceData,
            'behavioral_notes' => $behavioralNotes,
        ];
    }
}
