<?php

namespace App\Http\Controllers\Dosen;

use App\Http\Controllers\Controller;
use App\Models\Absensi;
use App\Models\AbsensiSession;
use App\Models\JadwalKuliah;
use App\Models\Mahasiswa;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class AbsensiController extends Controller
{
    public function list($jadwal)
    {
        $sessions = AbsensiSession::where('jadwal_kuliah_id', $jadwal)
            ->where('expired_at', '<', now())
            ->where('is_closed', false)
            ->get();

        foreach ($sessions as $s) {
            $this->closeSession($jadwal, $s->pertemuan);
        }

        $jadwalData = JadwalKuliah::with(['mataKuliah', 'tahunAkademik'])->findOrFail($jadwal);

        $rekap = Absensi::selectRaw('
                pertemuan,
                tanggal,
                SUM(CASE WHEN status = "hadir" THEN 1 ELSE 0 END) as hadir,
                SUM(CASE WHEN status = "izin" THEN 1 ELSE 0 END) as izin,
                SUM(CASE WHEN status = "sakit" THEN 1 ELSE 0 END) as sakit,
                SUM(CASE WHEN status = "alpha" THEN 1 ELSE 0 END) as alpha
            ')
            ->where('jadwal_kuliah_id', $jadwal)
            ->groupBy('pertemuan', 'tanggal')
            ->orderBy('pertemuan')
            ->get();

        $lastPertemuan = Absensi::where('jadwal_kuliah_id', $jadwal)->max('pertemuan');
        $nextPertemuan = $lastPertemuan ? $lastPertemuan + 1 : 1;

        return inertia('Dosen/Absensi/List', [
            'jadwal' => $jadwalData,
            'rekap' => $rekap,
            'nextPertemuan' => $nextPertemuan,
        ]);
    }

    public function create($jadwal)
    {
        $jadwalData = JadwalKuliah::with(['mataKuliah', 'tahunAkademik', 'dosen.user'])
            ->findOrFail($jadwal);

        $mahasiswas = Mahasiswa::select('mahasiswas.*')
            ->join('krs', 'krs.mahasiswa_id', '=', 'mahasiswas.id')
            ->join('krs_details', 'krs_details.krs_id', '=', 'krs.id')
            ->where('krs_details.jadwal_kuliah_id', $jadwal)
            ->with('user')
            ->distinct()
            ->get();

        $lastPertemuan = Absensi::where('jadwal_kuliah_id', $jadwal)->max('pertemuan');
        $nextPertemuan = $lastPertemuan ? $lastPertemuan + 1 : 1;

        $session = AbsensiSession::updateOrCreate(
            [
                'jadwal_kuliah_id' => $jadwal,
                'pertemuan' => $nextPertemuan,
            ],
            [
                'token' => Str::random(32),
                'expired_at' => now()->addMinutes(10),
                'is_closed' => false,
            ]
        );

        $qrUrl = url("/mahasiswa/absen?jadwal={$jadwal}&pertemuan={$nextPertemuan}&token={$session->token}");
        $qrSvg = QrCode::format('svg')->size(200)->generate($qrUrl);
        $qrCode = 'data:image/svg+xml;base64,' . base64_encode($qrSvg);

        return inertia('Dosen/Absensi/Form', [
            'jadwal'     => $jadwalData,
            'mahasiswas' => $mahasiswas,
            'pertemuan'  => $nextPertemuan,
            'tanggal'    => now()->toDateString(),
            'token'      => $session->token,
            'qrCode'     => $qrCode,
            'expired_at' => $session->expired_at,
        ]);
    }

    public function store(Request $request, $jadwal)
    {
        $request->validate([
            'pertemuan' => 'required|integer|min:1|max:16',
            'tanggal' => 'required|date',
            'data' => 'required|array',
            'data.*.mahasiswa_id' => 'required|exists:mahasiswas,id',
            'data.*.status' => 'required|in:hadir,izin,sakit,alpha',
            'data.*.keterangan' => 'nullable|string|max:255',
        ]);

        foreach ($request->data as $row) {
            Absensi::updateOrCreate(
                [
                    'jadwal_kuliah_id' => $jadwal,
                    'mahasiswa_id' => $row['mahasiswa_id'],
                    'pertemuan' => $request->pertemuan,
                ],
                [
                    'status' => $row['status'],
                    'keterangan' => $row['keterangan'] ?? null,
                    'tanggal' => $request->tanggal,
                ]
            );
        }

        return redirect()
            ->route('dosen.absensi.list', $jadwal)
            ->with('success', 'Absensi berhasil disimpan.');
    }

    public function edit($jadwal, $pertemuan)
    {
        $jadwalData = JadwalKuliah::with(['mataKuliah', 'tahunAkademik', 'dosen.user'])->findOrFail($jadwal);

        $mahasiswas = Mahasiswa::select('mahasiswas.*')
            ->join('krs', 'krs.mahasiswa_id', '=', 'mahasiswas.id')
            ->join('krs_details', 'krs_details.krs_id', '=', 'krs.id')
            ->where('krs_details.jadwal_kuliah_id', $jadwal)
            ->with(['user', 'absensis' => function ($q) use ($jadwal, $pertemuan) {
                $q->where('jadwal_kuliah_id', $jadwal)
                  ->where('pertemuan', $pertemuan);
            }])
            ->distinct()
            ->get();

        $tanggal = Absensi::where('jadwal_kuliah_id', $jadwal)
            ->where('pertemuan', $pertemuan)
            ->value('tanggal');

        return inertia('Dosen/Absensi/Form', [
            'jadwal' => $jadwalData,
            'mahasiswas' => $mahasiswas,
            'pertemuan' => $pertemuan,
            'tanggal' => $tanggal,
        ]);
    }

    public function update(Request $request, $jadwal, $pertemuan)
    {
        $request->validate([
            'tanggal' => 'required|date',
            'data' => 'required|array',
            'data.*.mahasiswa_id' => 'required|exists:mahasiswas,id',
            'data.*.status' => 'required|in:hadir,izin,sakit,alpha',
            'data.*.keterangan' => 'nullable|string|max:255',
        ]);

        foreach ($request->data as $row) {
            Absensi::updateOrCreate(
                [
                    'jadwal_kuliah_id' => $jadwal,
                    'mahasiswa_id' => $row['mahasiswa_id'],
                    'pertemuan' => $pertemuan,
                ],
                [
                    'status' => $row['status'],
                    'keterangan' => $row['keterangan'] ?? null,
                    'tanggal' => $request->tanggal,
                ]
            );
        }

        return redirect()
            ->route('dosen.absensi.list', $jadwal)
            ->with('success', 'Absensi berhasil diperbarui.');
    }

    private function closeSession($jadwal, $pertemuan)
    {
        $session = AbsensiSession::where('jadwal_kuliah_id', $jadwal)
            ->where('pertemuan', $pertemuan)
            ->first();

        if (!$session || $session->is_closed) {
            return;
        }

        if ($session->expired_at->isFuture()) {
            return;
        }

        $mahasiswas = Mahasiswa::select('mahasiswas.id')
            ->join('krs', 'krs.mahasiswa_id', '=', 'mahasiswas.id')
            ->join('krs_details', 'krs_details.krs_id', '=', 'krs.id')
            ->where('krs_details.jadwal_kuliah_id', $jadwal)
            ->distinct()
            ->pluck('mahasiswas.id');

        $sudahAbsen = Absensi::where('jadwal_kuliah_id', $jadwal)
            ->where('pertemuan', $pertemuan)
            ->pluck('mahasiswa_id');

        $belumAbsen = $mahasiswas->diff($sudahAbsen);

        foreach ($belumAbsen as $mahasiswaId) {
            Absensi::create([
                'jadwal_kuliah_id' => $jadwal,
                'mahasiswa_id' => $mahasiswaId,
                'pertemuan' => $pertemuan,
                'status' => 'alpha',
                'tanggal' => $session->expired_at->toDateString(),
            ]);
        }

        $session->update(['is_closed' => true]);
    }
}
