<?php

namespace Modules\Teachers\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Illuminate\Http\RedirectResponse;
use Modules\Teachers\Models\Teacher;
use Modules\Teachers\Http\Requests\StoreTeacherRequest;
use Modules\Teachers\Http\Requests\UpdateTeacherRequest;
use Modules\Teachers\Services\TeacherService;
use Modules\Academic\Models\AcademicYear;
use Modules\Academic\Models\Subject;
use Modules\Academic\Models\Classroom;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class TeachersController extends Controller
{
    private TeacherService $teacherService;

    public function __construct(TeacherService $teacherService)
    {
        $this->teacherService = $teacherService;
        $this->authorizeResource(Teacher::class, 'teacher');
    }

    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): Response
    {
        $user = $request->user();

        // Build query based on user role
        $query = Teacher::with(['user', 'subjects']);

        switch ($user->role) {
            case 'admin':
                // Admin can see all teachers
                break;

            case 'teacher':
                // Teachers can see themselves and colleagues in same subjects
                $query->where(function ($q) use ($user) {
                    $q->where('user_id', $user->id)
                      ->orWhereHas('subjects', function ($subjectQuery) use ($user) {
                          $subjectQuery->whereIn('id', function ($subQuery) use ($user) {
                              $subQuery->select('subject_id')
                                       ->from('teacher_subjects')
                                       ->where('teacher_id', $user->id);
                          });
                      });
                });
                break;

            default:
                // Students and guardians cannot access teacher list
                abort(403);
        }

        // Apply filters
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('first_name', 'like', "%{$search}%")
                  ->orWhere('last_name', 'like', "%{$search}%")
                  ->orWhere('teacher_id', 'like', "%{$search}%")
                  ->orWhereHas('user', function ($userQuery) use ($search) {
                      $userQuery->where('email', 'like', "%{$search}%");
                  });
            });
        }

        if ($request->filled('subject_id')) {
            $query->whereHas('subjects', function ($q) use ($request) {
                $q->where('subject_id', $request->subject_id);
            });
        }

        if ($request->filled('status')) {
            $query->where('is_active', $request->status === 'active');
        }

        $teachers = $query->latest()->paginate(20);

        // Get filter options
        $subjects = Subject::where('is_active', true)->get();

        return Inertia::render('Teachers/Index', [
            'teachers' => $teachers,
            'filters' => [
                'search' => $request->search,
                'subject_id' => $request->subject_id,
                'status' => $request->status,
            ],
            'subjects' => $subjects,
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): Response
    {
        $subjects = Subject::where('is_active', true)->get();

        return Inertia::render('Teachers/Create', [
            'subjects' => $subjects,
        ]);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(StoreTeacherRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        try {
            DB::beginTransaction();

            $teacher = $this->teacherService->createTeacher($validated);

            DB::commit();

            return redirect()
                ->route('teachers.show', $teacher)
                ->with('success', 'Teacher created successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to create teacher: ' . $e->getMessage()]);
        }
    }

    /**
     * Show the specified resource.
     */
    public function show(Teacher $teacher): Response
    {
        $teacher->load([
            'user',
            'subjects',
        ]);

        $currentAcademicYear = AcademicYear::where('is_active', true)->first();

        // Get teacher's classrooms for current academic year
        $classrooms = collect();
        if ($currentAcademicYear) {
            $classrooms = $teacher->getClassroomsForAcademicYear($currentAcademicYear->id);
            $classrooms->load(['subjects', 'enrollments']);
        }

        // Get teaching statistics
        $statistics = $this->teacherService->getTeachingStatistics($teacher->id, $currentAcademicYear?->id);

        // Get recent activities
        $recentActivities = $this->teacherService->getRecentActivities($teacher->id);

        return Inertia::render('Teachers/Show', [
            'teacher' => $teacher,
            'classrooms' => $classrooms,
            'statistics' => $statistics,
            'recentActivities' => $recentActivities,
            'currentAcademicYear' => $currentAcademicYear,
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Teacher $teacher): Response
    {
        $teacher->load(['user', 'subjects']);
        $subjects = Subject::where('is_active', true)->get();

        return Inertia::render('Teachers/Edit', [
            'teacher' => $teacher,
            'subjects' => $subjects,
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(UpdateTeacherRequest $request, Teacher $teacher): RedirectResponse
    {
        $validated = $request->validated();

        try {
            DB::beginTransaction();

            $this->teacherService->updateTeacher($teacher, $validated);

            DB::commit();

            return redirect()
                ->route('teachers.show', $teacher)
                ->with('success', 'Teacher updated successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to update teacher: ' . $e->getMessage()]);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Teacher $teacher): RedirectResponse
    {
        try {
            DB::beginTransaction();

            // Soft delete by deactivating
            $teacher->update(['is_active' => false]);
            $teacher->user->update(['is_active' => false]);

            // Remove subject assignments
            $teacher->subjects()->detach();

            DB::commit();

            return redirect()
                ->route('teachers.index')
                ->with('success', 'Teacher deactivated successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withErrors(['error' => 'Failed to deactivate teacher: ' . $e->getMessage()]);
        }
    }

    /**
     * Manage teacher subjects
     */
    public function subjects(Teacher $teacher): Response
    {
        $this->authorize('update', $teacher);

        $teacher->load(['subjects']);
        $availableSubjects = Subject::where('is_active', true)
            ->whereNotIn('id', $teacher->subjects->pluck('id'))
            ->get();

        return Inertia::render('Teachers/Subjects', [
            'teacher' => $teacher,
            'availableSubjects' => $availableSubjects,
        ]);
    }

    /**
     * Assign subject to teacher
     */
    public function assignSubject(Teacher $teacher, Request $request): RedirectResponse
    {
        $this->authorize('update', $teacher);

        $request->validate([
            'subject_id' => 'required|exists:subjects,id',
        ]);

        // Check if subject is active
        $subject = Subject::findOrFail($request->subject_id);
        if (!$subject->is_active) {
            return back()->withErrors(['error' => 'Cannot assign inactive subject.']);
        }

        // Check if already assigned
        if ($teacher->subjects()->where('subject_id', $request->subject_id)->exists()) {
            return back()->withErrors(['error' => 'Subject already assigned to this teacher.']);
        }

        $teacher->subjects()->attach($request->subject_id);

        return back()->with('success', 'Subject assigned successfully.');
    }

    /**
     * Remove subject from teacher
     */
    public function removeSubject(Teacher $teacher, Subject $subject): RedirectResponse
    {
        $this->authorize('update', $teacher);

        // Check if teacher has active classroom assignments for this subject
        $hasActiveAssignments = DB::table('classroom_subjects')
            ->where('teacher_id', $teacher->user_id)
            ->where('subject_id', $subject->id)
            ->exists();

        if ($hasActiveAssignments) {
            return back()->withErrors(['error' => 'Cannot remove subject with active classroom assignments.']);
        }

        $teacher->subjects()->detach($subject->id);

        return back()->with('success', 'Subject removed successfully.');
    }

    /**
     * Get teacher's classrooms
     */
    public function classrooms(Teacher $teacher, Request $request): Response
    {
        $this->authorize('view', $teacher);

        $academicYearId = $request->get('academic_year_id');
        $currentAcademicYear = AcademicYear::where('is_active', true)->first();

        if (!$academicYearId && $currentAcademicYear) {
            $academicYearId = $currentAcademicYear->id;
        }

        $classrooms = collect();
        if ($academicYearId) {
            $classrooms = $teacher->getClassroomsForAcademicYear($academicYearId);
            $classrooms->load(['subjects', 'enrollments', 'academicYear']);
        }

        $academicYears = AcademicYear::orderBy('start_date', 'desc')->get();

        return Inertia::render('Teachers/Classrooms', [
            'teacher' => $teacher,
            'classrooms' => $classrooms,
            'academicYears' => $academicYears,
            'currentAcademicYear' => $currentAcademicYear,
            'selectedAcademicYear' => $academicYearId,
        ]);
    }

    /**
     * Get teacher's students
     */
    public function students(Teacher $teacher, Request $request): Response
    {
        $this->authorize('view', $teacher);

        $academicYearId = $request->get('academic_year_id');
        $classroomId = $request->get('classroom_id');

        $currentAcademicYear = AcademicYear::where('is_active', true)->first();

        if (!$academicYearId && $currentAcademicYear) {
            $academicYearId = $currentAcademicYear->id;
        }

        $students = $this->teacherService->getTeacherStudents(
            $teacher->id,
            $academicYearId,
            $classroomId
        );

        $classrooms = collect();
        if ($academicYearId) {
            $classrooms = $teacher->getClassroomsForAcademicYear($academicYearId);
        }

        $academicYears = AcademicYear::orderBy('start_date', 'desc')->get();

        return Inertia::render('Teachers/Students', [
            'teacher' => $teacher,
            'students' => $students,
            'classrooms' => $classrooms,
            'academicYears' => $academicYears,
            'filters' => [
                'academic_year_id' => $academicYearId,
                'classroom_id' => $classroomId,
            ],
        ]);
    }
}
