<?php

namespace Modules\Teachers\Services;

use Modules\Teachers\Models\Teacher;
use Modules\Students\Models\Student;
use Modules\Academic\Models\Classroom;
use Modules\Results\Models\Result;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;

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

        // Generate unique teacher ID if not provided
        if (!isset($data['teacher_id'])) {
            $data['teacher_id'] = $this->generateTeacherId();
        }

        // Create teacher profile
        $teacher = Teacher::create([
            'user_id' => $user->id,
            'teacher_id' => $data['teacher_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,
            'qualification' => $data['qualification'] ?? null,
            'hire_date' => $data['hire_date'],
            'is_active' => true,
        ]);

        // Assign subjects if provided
        if (isset($data['subjects']) && is_array($data['subjects'])) {
            $teacher->subjects()->attach($data['subjects']);
        }

        return $teacher->load(['user', 'subjects']);
    }

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

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

        // Update teacher profile
        $teacherUpdateData = [
            '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,
            'qualification' => $data['qualification'] ?? null,
            'hire_date' => $data['hire_date'],
        ];

        if (isset($data['teacher_id'])) {
            $teacherUpdateData['teacher_id'] = $data['teacher_id'];
        }

        $teacher->update($teacherUpdateData);

        // Update subjects if provided
        if (isset($data['subjects']) && is_array($data['subjects'])) {
            $teacher->subjects()->sync($data['subjects']);
        }

        return $teacher->load(['user', 'subjects']);
    }

    /**
     * Get teaching statistics for a teacher
     */
    public function getTeachingStatistics(int $teacherId, ?int $academicYearId = null): array
    {
        $teacher = Teacher::findOrFail($teacherId);

        // Get classrooms count
        $classroomsQuery = Classroom::whereHas('subjects', function ($query) use ($teacher) {
            $query->where('teacher_id', $teacher->user_id);
        });

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

        $classroomsCount = $classroomsQuery->count();

        // Get students count
        $studentsQuery = Student::whereHas('enrollments', function ($enrollmentQuery) use ($teacher, $academicYearId) {
            $enrollmentQuery->whereHas('classroom.subjects', function ($subjectQuery) use ($teacher) {
                $subjectQuery->where('teacher_id', $teacher->user_id);
            });

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

            $enrollmentQuery->where('is_active', true);
        });

        $studentsCount = $studentsQuery->count();

        // Get subjects count
        $subjectsCount = $teacher->subjects()->count();

        // Get results statistics
        $resultsQuery = Result::whereHas('classroom.subjects', function ($query) use ($teacher) {
            $query->where('teacher_id', $teacher->user_id);
        });

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

        $totalResults = $resultsQuery->count();
        $averageMarks = $resultsQuery->avg('marks');
        $passRate = $resultsQuery->where('marks', '>=', 40)->count();
        $passPercentage = $totalResults > 0 ? round(($passRate / $totalResults) * 100, 2) : 0;

        // Get grade distribution
        $gradeDistribution = $resultsQuery
            ->select('grade', DB::raw('count(*) as count'))
            ->groupBy('grade')
            ->pluck('count', 'grade')
            ->toArray();

        return [
            'classrooms_count' => $classroomsCount,
            'students_count' => $studentsCount,
            'subjects_count' => $subjectsCount,
            'total_results' => $totalResults,
            'average_marks' => round($averageMarks ?? 0, 2),
            'pass_percentage' => $passPercentage,
            'grade_distribution' => $gradeDistribution,
        ];
    }

    /**
     * Get recent activities for a teacher
     */
    public function getRecentActivities(int $teacherId, int $limit = 10): array
    {
        $teacher = Teacher::findOrFail($teacherId);

        // Get recent results entered
        $recentResults = Result::whereHas('classroom.subjects', function ($query) use ($teacher) {
            $query->where('teacher_id', $teacher->user_id);
        })
        ->with(['student', 'subject', 'examType', 'classroom'])
        ->orderBy('entered_at', 'desc')
        ->limit($limit)
        ->get();

        return $recentResults->map(function ($result) {
            return [
                'type' => 'result_entered',
                'description' => "Entered {$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,
            ];
        })->toArray();
    }

    /**
     * Get students taught by a teacher
     */
    public function getTeacherStudents(int $teacherId, ?int $academicYearId = null, ?int $classroomId = null): \Illuminate\Pagination\LengthAwarePaginator
    {
        $teacher = Teacher::findOrFail($teacherId);

        $query = Student::whereHas('enrollments', function ($enrollmentQuery) use ($teacher, $academicYearId, $classroomId) {
            $enrollmentQuery->whereHas('classroom.subjects', function ($subjectQuery) use ($teacher) {
                $subjectQuery->where('teacher_id', $teacher->user_id);
            });

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

            if ($classroomId) {
                $enrollmentQuery->where('classroom_id', $classroomId);
            }

            $enrollmentQuery->where('is_active', true);
        })->with(['user', 'enrollments.classroom', 'enrollments.academicYear']);

        return $query->paginate(20);
    }

    /**
     * Generate unique teacher ID
     */
    private function generateTeacherId(): string
    {
        $year = date('Y');
        $prefix = 'TCH' . $year;
        
        // Get the last teacher ID for this year
        $lastTeacher = Teacher::where('teacher_id', 'like', $prefix . '%')
            ->orderBy('teacher_id', 'desc')
            ->first();

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

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

    /**
     * Get teacher workload summary
     */
    public function getWorkloadSummary(int $teacherId, int $academicYearId): array
    {
        $teacher = Teacher::findOrFail($teacherId);

        // Get classroom-subject assignments
        $assignments = DB::table('classroom_subjects')
            ->join('classrooms', 'classroom_subjects.classroom_id', '=', 'classrooms.id')
            ->join('subjects', 'classroom_subjects.subject_id', '=', 'subjects.id')
            ->where('classroom_subjects.teacher_id', $teacher->user_id)
            ->where('classrooms.academic_year_id', $academicYearId)
            ->select([
                'classrooms.name as classroom_name',
                'subjects.name as subject_name',
                'classrooms.capacity',
                DB::raw('(SELECT COUNT(*) FROM enrollments WHERE classroom_id = classrooms.id AND is_active = true) as enrolled_students')
            ])
            ->get();

        $totalClassrooms = $assignments->groupBy('classroom_name')->count();
        $totalSubjects = $assignments->groupBy('subject_name')->count();
        $totalStudents = $assignments->sum('enrolled_students');

        return [
            'assignments' => $assignments,
            'summary' => [
                'total_classrooms' => $totalClassrooms,
                'total_subjects' => $totalSubjects,
                'total_students' => $totalStudents,
                'average_class_size' => $totalClassrooms > 0 ? round($totalStudents / $totalClassrooms, 1) : 0,
            ],
        ];
    }

    /**
     * Check if teacher can be deleted
     */
    public function canDelete(Teacher $teacher): array
    {
        $issues = [];

        // Check for active classroom assignments
        $activeAssignments = DB::table('classroom_subjects')
            ->join('classrooms', 'classroom_subjects.classroom_id', '=', 'classrooms.id')
            ->join('academic_years', 'classrooms.academic_year_id', '=', 'academic_years.id')
            ->where('classroom_subjects.teacher_id', $teacher->user_id)
            ->where('academic_years.is_active', true)
            ->count();

        if ($activeAssignments > 0) {
            $issues[] = "Teacher has {$activeAssignments} active classroom assignments";
        }

        // Check for recent results
        $recentResults = Result::whereHas('classroom.subjects', function ($query) use ($teacher) {
            $query->where('teacher_id', $teacher->user_id);
        })->where('entered_at', '>=', now()->subDays(30))->count();

        if ($recentResults > 0) {
            $issues[] = "Teacher has entered {$recentResults} results in the last 30 days";
        }

        return [
            'can_delete' => empty($issues),
            'issues' => $issues,
        ];
    }
}
