<?php

namespace App\Services;

use App\Models\Badge;
use App\Models\SiswaBadge;
use App\Models\PesertaChallenge;
use App\Models\PengumpulanTugas;
use App\Models\Leaderboard;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class BadgeService
{
    /**
     * Syarat (kolom `syarat` di tabel badges) yang dikenali sistem.
     *
     * CHALLENGE
     *   challenge_1   → selesaikan 1 challenge
     *   challenge_3   → selesaikan 3 challenge
     *
     * TUGAS
     *   tugas_1       → kumpulkan 1 tugas tepat waktu (tanggal_submit ≤ deadline)
     *   tugas_3       → kumpulkan 3 tugas tepat waktu (tanggal_submit ≤ deadline)
     *
     * LEADERBOARD  (dicek & dicabut secara real-time)
     *   leaderboard_top5  → masuk top 5 leaderboard kelas aktif
     *   leaderboard_top1  → raih peringkat 1 leaderboard kelas aktif
     */

    // -------------------------------------------------------------------------
    // ENTRY POINTS
    // -------------------------------------------------------------------------

    /**
     * Dipanggil setelah siswa submit challenge.
     */
    public function checkChallengeBadges(int $idSiswa): void
    {
        $jumlahSelesai = PesertaChallenge::where('id_siswa', $idSiswa)
            ->where('status', 'selesai')
            ->count();

        $this->grantIfEligible($idSiswa, 'challenge_1', $jumlahSelesai >= 1);
        $this->grantIfEligible($idSiswa, 'challenge_3', $jumlahSelesai >= 3);
    }

    /**
     * Dipanggil setelah siswa submit tugas.
     * Badge hanya diberikan jika tugas dikumpulkan TEPAT WAKTU
     * (tanggal_submit ≤ deadline tugas).
     */
    public function checkTugasBadges(int $idSiswa): void
    {
        // Join pengumpulan_tugas dengan tugas untuk membandingkan
        // tanggal_submit dengan deadline secara langsung di DB.
        $jumlahTepatWaktu = DB::table('pengumpulan_tugas')
            ->join('tugas', 'pengumpulan_tugas.id_tugas', '=', 'tugas.id_tugas')
            ->where('pengumpulan_tugas.id_siswa', $idSiswa)
            ->whereNotNull('pengumpulan_tugas.lampiran_tugas')
            ->whereColumn('pengumpulan_tugas.tanggal_submit', '<=', 'tugas.deadline')
            ->count();

        $this->grantIfEligible($idSiswa, 'tugas_1', $jumlahTepatWaktu >= 1);
        $this->grantIfEligible($idSiswa, 'tugas_3', $jumlahTepatWaktu >= 3);
    }

    /**
     * Dipanggil dari endpoint JSON leaderboard (polling real-time).
     * Badge leaderboard DICABUT jika siswa tidak lagi memenuhi syarat,
     * dan DIBERIKAN KEMBALI jika kembali memenuhi syarat.
     */
    public function checkLeaderboardBadges(int $idSiswa, int $idKelas): void
    {
        [$semester, $tahunAjaran] = $this->semesterAktif();

        $lb = Leaderboard::where('id_siswa', $idSiswa)
            ->where('id_kelas', $idKelas)
            ->where('semester', $semester)
            ->where('tahun_ajaran', $tahunAjaran)
            ->first();

        $ranking = $lb?->ranking ?? 0;

        $isTop5 = $ranking >= 1 && $ranking <= 5;
        $isTop1 = $ranking === 1;

        $this->grantOrRevoke($idSiswa, 'leaderboard_top5', $isTop5);
        $this->grantOrRevoke($idSiswa, 'leaderboard_top1', $isTop1);
    }

    // -------------------------------------------------------------------------
    // PRIVATE HELPERS
    // -------------------------------------------------------------------------

    /**
     * Berikan badge jika eligible. Tidak melakukan apa-apa jika sudah punya.
     * Digunakan untuk badge challenge & tugas (tidak pernah dicabut).
     */
    private function grantIfEligible(int $idSiswa, string $syarat, bool $eligible): void
    {
        if (!$eligible) {
            return;
        }

        $badge = Badge::where('syarat', $syarat)->first();
        if (!$badge) {
            return;
        }

        $sudahPunya = SiswaBadge::where('id_siswa', $idSiswa)
            ->where('id_badge', $badge->id_badge)
            ->exists();

        if (!$sudahPunya) {
            SiswaBadge::create([
                'id_siswa'          => $idSiswa,
                'id_badge'          => $badge->id_badge,
                'tanggal_diberikan' => Carbon::now(),
            ]);
        }
    }

    /**
     * Berikan badge jika eligible, CABUT jika tidak.
     * Digunakan khusus untuk badge leaderboard (real-time).
     */
    private function grantOrRevoke(int $idSiswa, string $syarat, bool $eligible): void
    {
        $badge = Badge::where('syarat', $syarat)->first();
        if (!$badge) {
            return;
        }

        $record = SiswaBadge::where('id_siswa', $idSiswa)
            ->where('id_badge', $badge->id_badge)
            ->first();

        if ($eligible && !$record) {
            SiswaBadge::create([
                'id_siswa'          => $idSiswa,
                'id_badge'          => $badge->id_badge,
                'tanggal_diberikan' => Carbon::now(),
            ]);
        } elseif (!$eligible && $record) {
            $record->delete();
        }
    }

    /**
     * Mengembalikan [semester, tahun_ajaran] berdasarkan tanggal sekarang.
     */
    private function semesterAktif(): array
    {
        $now         = Carbon::now();
        $semester    = $now->month >= 7 ? '1' : '2';
        $tahunAjaran = $now->month >= 7
            ? $now->year . '/' . ($now->year + 1)
            : ($now->year - 1) . '/' . $now->year;

        return [$semester, $tahunAjaran];
    }
}