<?php

namespace Modules\Academic\Http\Controllers;

use App\Http\Controllers\Controller;
use Modules\Academic\Models\ExamType;
use Modules\Academic\Models\AcademicYear;
use Modules\Academic\Http\Requests\StoreExamTypeRequest;
use Modules\Academic\Http\Requests\UpdateExamTypeRequest;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;

class ExamTypeController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->authorizeResource(ExamType::class, 'exam_type');
    }

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

        // Apply search filter
        if ($request->search) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // Apply status filter
        if ($request->status !== null) {
            $query->where('is_active', $request->status === 'active');
        }

        $examTypes = $query->withCount('results')
            ->orderBy('name')
            ->paginate(20);

        // Get statistics
        $statistics = [
            'total' => ExamType::count(),
            'active' => ExamType::where('is_active', true)->count(),
            'inactive' => ExamType::where('is_active', false)->count(),
            'with_results' => ExamType::has('results')->count(),
        ];

        return Inertia::render('Academic/ExamTypes/Index', [
            'examTypes' => $examTypes,
            'statistics' => $statistics,
            'filters' => [
                'search' => $request->search,
                'status' => $request->status,
            ],
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): Response
    {
        // Get academic years for the dropdown
        $academicYears = AcademicYear::orderBy('name')->get(['id', 'name']);

        return Inertia::render('Academic/ExamTypes/Create', [
            'academicYears' => $academicYears,
        ]);
    }

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

        try {
            DB::beginTransaction();

            $examType = ExamType::create($validated);

            DB::commit();

            return redirect()
                ->route('exam-types.show', $examType)
                ->with('success', 'Exam type created successfully.');

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

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

    /**
     * Display the specified resource.
     */
    public function show(ExamType $examType): Response
    {
        $examType->load('results.student.user', 'results.subject');

        // Get exam type statistics
        $statistics = [
            'total_results' => $examType->results()->count(),
            'students_count' => $examType->results()->distinct('student_id')->count(),
            'subjects_count' => $examType->results()->distinct('subject_id')->count(),
            'average_marks' => $examType->results()->avg('marks'),
            'highest_marks' => $examType->results()->max('marks'),
            'lowest_marks' => $examType->results()->min('marks'),
            'pass_rate' => $examType->results()->where('marks', '>=', 50)->count() / max($examType->results()->count(), 1) * 100, // Using 50 as default pass mark
        ];

        // Get recent results
        $recentResults = $examType->results()
            ->with(['student.user', 'subject'])
            ->latest('entered_at')
            ->limit(10)
            ->get();

        // Get results by subject
        $resultsBySubject = $examType->results()
            ->select('subject_id')
            ->selectRaw('COUNT(*) as count, AVG(marks) as average_marks')
            ->with('subject:id,name')
            ->groupBy('subject_id')
            ->get();

        return Inertia::render('Academic/ExamTypes/Show', [
            'examType' => $examType,
            'statistics' => $statistics,
            'recentResults' => $recentResults,
            'resultsBySubject' => $resultsBySubject,
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(ExamType $examType): Response
    {
        // Get academic years for the dropdown
        $academicYears = AcademicYear::orderBy('name')->get(['id', 'name']);

        return Inertia::render('Academic/ExamTypes/Edit', [
            'examType' => $examType,
            'academicYears' => $academicYears,
        ]);
    }

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

        try {
            DB::beginTransaction();

            $examType->update($validated);

            DB::commit();

            return redirect()
                ->route('exam-types.show', $examType)
                ->with('success', 'Exam type updated successfully.');

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

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

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

            // Check if exam type has results
            if ($examType->results()->exists()) {
                return back()
                    ->withErrors(['error' => 'Cannot delete exam type with existing results.']);
            }

            $examType->delete();

            DB::commit();

            return redirect()
                ->route('exam-types.index')
                ->with('success', 'Exam type deleted successfully.');

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

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

    /**
     * Toggle exam type status
     */
    public function toggleStatus(ExamType $examType): RedirectResponse
    {
        $this->authorize('update', $examType);

        try {
            DB::beginTransaction();

            $examType->update(['is_active' => !$examType->is_active]);

            $message = $examType->is_active ? 'Exam type activated successfully.' : 'Exam type deactivated successfully.';

            DB::commit();

            return back()->with('success', $message);

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

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

    /**
     * Get active exam types for dropdown
     */
    public function getActiveExamTypes(): \Illuminate\Http\JsonResponse
    {
        $examTypes = ExamType::where('is_active', true)
            ->orderBy('name')
            ->get(['id', 'name', 'max_marks', 'pass_marks']);

        return response()->json($examTypes);
    }

    /**
     * Bulk update exam types
     */
    public function bulkUpdate(Request $request): RedirectResponse
    {
        $this->authorize('update', ExamType::class);

        $validated = $request->validate([
            'exam_type_ids' => 'required|array|min:1',
            'exam_type_ids.*' => 'exists:exam_types,id',
            'action' => 'required|in:activate,deactivate,delete',
        ]);

        try {
            DB::beginTransaction();

            $examTypes = ExamType::whereIn('id', $validated['exam_type_ids']);
            $count = $examTypes->count();

            switch ($validated['action']) {
                case 'activate':
                    $examTypes->update(['is_active' => true]);
                    $message = "{$count} exam types activated successfully.";
                    break;

                case 'deactivate':
                    $examTypes->update(['is_active' => false]);
                    $message = "{$count} exam types deactivated successfully.";
                    break;

                case 'delete':
                    // Check if any exam type has results
                    $hasResults = $examTypes->has('results')->exists();
                    if ($hasResults) {
                        return back()
                            ->withErrors(['error' => 'Cannot delete exam types with existing results.']);
                    }

                    $examTypes->delete();
                    $message = "{$count} exam types deleted successfully.";
                    break;
            }

            DB::commit();

            return back()->with('success', $message);

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

            return back()
                ->withErrors(['error' => 'Bulk operation failed: ' . $e->getMessage()]);
        }
    }

    /**
     * Import exam types from CSV
     */
    public function import(Request $request): RedirectResponse
    {
        $this->authorize('create', ExamType::class);

        $request->validate([
            'csv_file' => 'required|file|mimes:csv,txt|max:2048',
        ]);

        try {
            DB::beginTransaction();

            $file = $request->file('csv_file');
            $csvData = array_map('str_getcsv', file($file->path()));
            $headers = array_shift($csvData);

            $successCount = 0;
            $errors = [];

            foreach ($csvData as $index => $row) {
                try {
                    $data = array_combine($headers, $row);

                    // Validate required fields
                    if (empty($data['name']) || empty($data['max_marks']) || empty($data['pass_marks'])) {
                        $errors[] = "Row " . ($index + 2) . ": Missing required fields.";
                        continue;
                    }

                    // Check if exam type already exists
                    if (ExamType::where('name', $data['name'])->exists()) {
                        $errors[] = "Row " . ($index + 2) . ": Exam type '{$data['name']}' already exists.";
                        continue;
                    }

                    ExamType::create([
                        'name' => $data['name'],
                        'description' => $data['description'] ?? null,
                        'max_marks' => (int)$data['max_marks'],
                        'pass_marks' => (int)$data['pass_marks'],
                        'weightage' => isset($data['weightage']) ? (float)$data['weightage'] : null,
                        'is_active' => isset($data['is_active']) ? filter_var($data['is_active'], FILTER_VALIDATE_BOOLEAN) : true,
                    ]);

                    $successCount++;

                } catch (\Exception $e) {
                    $errors[] = "Row " . ($index + 2) . ": " . $e->getMessage();
                }
            }

            DB::commit();

            $message = "{$successCount} exam types imported successfully.";
            if (!empty($errors)) {
                $message .= " " . count($errors) . " errors occurred.";
            }

            return back()
                ->with('success', $message)
                ->with('import_errors', $errors);

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

            return back()
                ->withErrors(['error' => 'Import failed: ' . $e->getMessage()]);
        }
    }
}
