<?php

namespace App\Http\Controllers\Siswa;

use App\Http\Controllers\Controller;
use App\Models\Ujian;
use App\Models\SoalUjian;
use App\Models\HasilUjian;
use App\Models\Kelas;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;

class UjianController extends Controller
{
    /**
     * List all exams matching the student's class.
     */
    public function index(): View
    {
        $siswa = auth()->user();
        $siswaProfile = $siswa->siswaProfile;
        $kelas = $siswaProfile ? $siswaProfile->kelas : null;

        $ujianList = collect();
        $submissions = collect();

        if ($kelas) {
            $kelasModel = Kelas::where('nama_kelas', $kelas)->first();
            if ($kelasModel) {
                // Fetch exams for student class
                $ujianList = Ujian::where('kelas_id', $kelasModel->id)
                    ->where('status', 'Aktif')
                    ->with(['mataPelajaran', 'guru'])
                    ->latest()
                    ->get();

                // Fetch student submissions/grades
                $submissions = HasilUjian::where('siswa_id', $siswa->id)
                    ->get()
                    ->keyBy('ujian_id');
            }
        }

        return view('siswa.ujian.index', [
            'ujianList' => $ujianList,
            'submissions' => $submissions,
            'kelas' => $kelas,
        ]);
    }

    /**
     * Show instructions for taking a specific exam.
     */
    public function show(Ujian $ujian): View
    {
        $siswa = auth()->user();
        $siswaProfile = $siswa->siswaProfile;
        $kelas = $siswaProfile ? $siswaProfile->kelas : null;

        $this->ensureStudentCanAccessUjian($ujian, $kelas);

        $ujian->load(['mataPelajaran', 'guru', 'soalUjian']);

        $submission = HasilUjian::where('ujian_id', $ujian->id)
            ->where('siswa_id', $siswa->id)
            ->first();

        $availability = $this->examAvailability($ujian, $submission !== null);

        return view('siswa.ujian.show', [
            'ujian' => $ujian,
            'submission' => $submission,
            'kelas' => $kelas,
            'availability' => $availability,
            'waktuSelesai' => $this->endsAt($ujian),
        ]);
    }

    /**
     * Display the exam taking page.
     */
    public function kerjakan(Ujian $ujian): View|RedirectResponse
    {
        $siswa = auth()->user();
        $siswaProfile = $siswa->siswaProfile;
        $kelas = $siswaProfile ? $siswaProfile->kelas : null;

        $this->ensureStudentCanAccessUjian($ujian, $kelas);

        // Check if student has already taken the exam
        $submission = HasilUjian::where('ujian_id', $ujian->id)
            ->where('siswa_id', $siswa->id)
            ->first();

        $availability = $this->examAvailability($ujian, $submission !== null);
        if (! $availability['can_start']) {
            return redirect()
                ->route('siswa.ujian.show', $ujian)
                ->with('error', $availability['message']);
        }

        $ujian->load(['mataPelajaran', 'guru']);
        $soals = SoalUjian::where('ujian_id', $ujian->id)->get();

        if ($soals->isEmpty()) {
            return redirect()
                ->route('siswa.ujian.show', $ujian)
                ->with('error', 'Bank soal untuk ujian ini masih kosong. Silakan hubungi guru Anda.');
        }

        return view('siswa.ujian.kerjakan', [
            'ujian' => $ujian,
            'soals' => $soals,
            'kelas' => $kelas,
            'remainingSeconds' => (int) max(now('Asia/Jakarta')->diffInSeconds($this->endsAt($ujian), false), 1),
        ]);
    }

    /**
     * Submit and grade the exam.
     */
    public function submit(Request $request, Ujian $ujian): RedirectResponse
    {
        $siswa = auth()->user();
        $siswaProfile = $siswa->siswaProfile;
        $kelas = $siswaProfile ? $siswaProfile->kelas : null;

        $this->ensureStudentCanAccessUjian($ujian, $kelas);

        // Double check submission
        $existing = HasilUjian::where('ujian_id', $ujian->id)
            ->where('siswa_id', $siswa->id)
            ->first();

        if ($existing) {
            return redirect()
                ->route('siswa.ujian.show', $ujian)
                ->with('error', 'Anda sudah mengumpulkan ujian ini.');
        }

        $availability = $this->examAvailability($ujian, false);
        if (! $availability['can_start']) {
            return redirect()
                ->route('siswa.ujian.show', $ujian)
                ->with('error', $availability['message']);
        }

        $soals = SoalUjian::where('ujian_id', $ujian->id)->get();
        $totalSoal = $soals->count();
        $benar = 0;
        $salah = 0;

        $userAnswers = $request->input('answers', []); // array of soal_id => selected_option

        foreach ($soals as $soal) {
            $selected = $userAnswers[$soal->id] ?? null;
            if ($selected === $soal->jawaban_benar) {
                $benar++;
            } else {
                $salah++;
            }
        }

        // Calculate score out of 100
        $nilai = $totalSoal > 0 ? round(($benar / $totalSoal) * 100, 2) : 0;

        $hasil = HasilUjian::create([
            'ujian_id' => $ujian->id,
            'siswa_id' => $siswa->id,
            'benar' => $benar,
            'salah' => $salah,
            'nilai' => $nilai,
        ]);

        return redirect()
            ->route('siswa.ujian.show', $ujian)
            ->with('success', 'Ujian berhasil diselesaikan dan dikumpulkan.');
    }

    private function ensureStudentCanAccessUjian(Ujian $ujian, ?string $kelas): void
    {
        if (
            ! $kelas
            || ! $ujian->kelas
            || $ujian->kelas->nama_kelas !== $kelas
            || $ujian->status !== 'Aktif'
        ) {
            abort(403, 'Anda tidak memiliki akses ke ujian ini.');
        }
    }

    private function endsAt(Ujian $ujian)
    {
        return $ujian->waktu_selesai_otomatis;
    }

    private function examAvailability(Ujian $ujian, bool $alreadySubmitted): array
    {
        if ($alreadySubmitted) {
            return [
                'status' => 'Sudah Dikerjakan',
                'can_start' => false,
                'message' => 'Anda sudah mengerjakan ujian ini.',
                'badge' => 'badge-aktif',
            ];
        }

        $now = now('Asia/Jakarta');
        $startsAt = $ujian->waktu_mulai_ujian;
        $endsAt = $this->endsAt($ujian);

        if ($now->isBefore($startsAt)) {
            return [
                'status' => 'Ujian Belum Dimulai',
                'can_start' => false,
                'message' => 'Ujian belum dimulai. Ujian dapat dikerjakan mulai ' . $startsAt->translatedFormat('d M Y, H:i') . ' WIB.',
                'badge' => 'badge-draft',
            ];
        }

        if ($now->greaterThanOrEqualTo($endsAt)) {
            return [
                'status' => 'Ujian Ditutup',
                'can_start' => false,
                'message' => 'Ujian sudah ditutup.',
                'badge' => 'badge-libur',
            ];
        }

        return [
            'status' => 'Siap Dikerjakan',
            'can_start' => true,
            'message' => 'Ujian sedang berlangsung.',
            'badge' => 'badge-selesai',
        ];
    }
}
