<?php
// app/Http/Controllers/Teacher/GradeEntryController.php

namespace App\Http\Controllers\Teacher;

use App\Http\Controllers\Controller;
use App\Models\SchoolClass;
use App\Models\Subject;
use App\Models\Student;
use App\Models\Grade;
use App\Models\AuditLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class GradeEntryController extends Controller
{
    public function create(SchoolClass $class, Subject $subject)
    {
        $teacher = auth()->user();

        $students = $class->students()->orderBy('admission_number')->get();

        $existingGrades = Grade::where('school_class_id', $class->id)
            ->where('subject_id', $subject->id)
            ->where('teacher_id', $teacher->id)
            ->pluck('score', 'student_id');

        $existingRemarks = Grade::where('school_class_id', $class->id)
            ->where('subject_id', $subject->id)
            ->where('teacher_id', $teacher->id)
            ->pluck('remarks', 'student_id');

        return view('teacher.grades.create', compact('class', 'subject', 'students', 'existingGrades', 'existingRemarks'));
    }

    public function store(Request $request, SchoolClass $class, Subject $subject)
    {
        $teacher = auth()->user();
        
        $request->validate([
            'scores' => 'required|array',
            'scores.*' => 'nullable|integer|min:0|max:100',
            'exam_type' => 'required|string|max:100',
            'remarks' => 'nullable|array',
        ]);

        $changes = [];
        
        foreach ($request->scores as $studentId => $score) {
            if ($score !== null) {
                $oldGrade = Grade::where('student_id', $studentId)
                    ->where('school_class_id', $class->id)
                    ->where('subject_id', $subject->id)
                    ->where('exam_type', $request->exam_type)
                    ->first();
                
                $oldScore = $oldGrade ? $oldGrade->score : null;
                
                $grade = Grade::updateOrCreate(
                    [
                        'student_id' => $studentId,
                        'school_class_id' => $class->id,
                        'subject_id' => $subject->id,
                        'exam_type' => $request->exam_type,
                    ],
                    [
                        'teacher_id' => $teacher->id,
                        'score' => $score,
                        'status' => 'submitted',
                        'remarks' => $request->remarks[$studentId] ?? null,
                        'graded_by' => $teacher->id,
                        'graded_at' => now(),
                    ]
                );
                
                // Log audit
                if ($oldScore !== null && $oldScore != $score) {
                    $changes[] = [
                        'student_id' => $studentId,
                        'old_score' => $oldScore,
                        'new_score' => $score,
                    ];
                }
                
                AuditLog::log(
                    $grade,
                    $oldGrade ? 'updated' : 'created',
                    $oldGrade ? ['score' => $oldScore] : null,
                    ['score' => $score],
                    "Grade " . ($oldGrade ? 'updated' : 'created') . " for student ID: {$studentId} in {$subject->name}"
                );
            }
        }
        
        return redirect()->route('teacher.grades.index')
            ->with('success', "Marks saved successfully for {$subject->name}. " . 
                (count($changes) ? count($changes) . " grades were updated." : ""));
    }

    public function showBulkUploadForm(SchoolClass $class, Subject $subject)
    {
        return view('teacher.grades.bulk-upload', compact('class', 'subject'));
    }

    public function processBulkUpload(Request $request, SchoolClass $class, Subject $subject)
    {
        $request->validate([
            'exam_type' => 'required|string|max:100',
            'grades_file' => 'required|file|mimes:csv,xlsx,xls|max:2048',
        ]);

        $teacher = auth()->user();
        
        try {
            DB::beginTransaction();
            
            $students = $class->students()->get()->keyBy('admission_number');
            $gradesData = $this->parseGradesFile($request->file('grades_file'), $students);
            
            $successCount = 0;
            $errorRows = [];
            
            foreach ($gradesData as $index => $gradeData) {
                $student = $students->get($gradeData['admission_number']);
                
                if (!$student) {
                    $errorRows[] = "Row " . ($index + 2) . ": Student admission number '{$gradeData['admission_number']}' not found in this class";
                    continue;
                }
                
                $oldGrade = Grade::where('student_id', $student->id)
                    ->where('school_class_id', $class->id)
                    ->where('subject_id', $subject->id)
                    ->where('exam_type', $request->exam_type)
                    ->first();
                
                $grade = Grade::updateOrCreate(
                    [
                        'student_id' => $student->id,
                        'school_class_id' => $class->id,
                        'subject_id' => $subject->id,
                        'exam_type' => $request->exam_type,
                    ],
                    [
                        'teacher_id' => $teacher->id,
                        'score' => $gradeData['score'],
                        'status' => 'submitted',
                        'remarks' => $gradeData['remarks'] ?? null,
                        'graded_by' => $teacher->id,
                        'graded_at' => now(),
                    ]
                );
                
                AuditLog::log(
                    $grade,
                    $oldGrade ? 'bulk_updated' : 'bulk_created',
                    $oldGrade ? ['score' => $oldGrade->score] : null,
                    ['score' => $gradeData['score']],
                    "Bulk upload: Grade " . ($oldGrade ? 'updated' : 'created') . " for {$student->fullName()} in {$subject->name}"
                );
                
                $successCount++;
            }
            
            if (count($errorRows) > 0) {
                DB::commit();
                return redirect()->route('teacher.grades.create', [$class, $subject])
                    ->with('warning', "Bulk upload completed with errors. Success: {$successCount}, Failed: " . count($errorRows))
                    ->with('errors', $errorRows);
            }
            
            DB::commit();
            
            return redirect()->route('teacher.grades.create', [$class, $subject])
                ->with('success', "Successfully uploaded {$successCount} grades for {$subject->name}");
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Error processing file: ' . $e->getMessage());
        }
    }

    public function downloadTemplate(SchoolClass $class, Subject $subject)
    {
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="grade_template.csv"',
        ];
        
        $callback = function() use ($class, $subject) {
            $file = fopen('php://output', 'w');
            
            // Add headers
            fputcsv($file, ['Admission Number', 'Student Name', 'Score (0-100)', 'Remarks (Optional)']);
            
            // Add sample data
            $students = $class->students()->take(3)->get();
            foreach ($students as $student) {
                fputcsv($file, [
                    $student->admission_number,
                    $student->fullName(),
                    '',
                    ''
                ]);
            }
            
            fclose($file);
        };
        
        return response()->stream($callback, 200, $headers);
    }

    protected function parseGradesFile($file, $students)
    {
        $extension = $file->getClientOriginalExtension();
        $grades = [];
        
        if ($extension === 'csv') {
            $handle = fopen($file->getPathname(), 'r');
            $header = fgetcsv($handle);
            
            while (($row = fgetcsv($handle)) !== false) {
                $grades[] = [
                    'admission_number' => trim($row[0]),
                    'score' => (int) trim($row[2]),
                    'remarks' => trim($row[3] ?? ''),
                ];
            }
            fclose($handle);
        } elseif (in_array($extension, ['xlsx', 'xls'])) {
            // You'll need to install: composer require phpoffice/phpspreadsheet
            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file->getPathname());
            $worksheet = $spreadsheet->getActiveSheet();
            $rows = $worksheet->toArray();
            
            // Remove header row
            array_shift($rows);
            
            foreach ($rows as $row) {
                if (!empty($row[0])) {
                    $grades[] = [
                        'admission_number' => trim($row[0]),
                        'score' => (int) trim($row[2]),
                        'remarks' => trim($row[3] ?? ''),
                    ];
                }
            }
        }
        
        return $grades;
    }

    public function auditLog(SchoolClass $class, Subject $subject)
    {
        $teacher = auth()->user();
        
        $auditLogs = AuditLog::where('auditable_type', Grade::class)
            ->whereHasMorph('auditable', [Grade::class], function ($query) use ($class, $subject, $teacher) {
                $query->where('school_class_id', $class->id)
                    ->where('subject_id', $subject->id)
                    ->where('teacher_id', $teacher->id);
            })
            ->with('user')
            ->orderBy('created_at', 'desc')
            ->paginate(20);
        
        return view('teacher.grades.audit-log', compact('class', 'subject', 'auditLogs'));
    }
}