"""Progres belajar: dasbor mahasiswa, penanda "sudah dipelajari", rekap dosen."""

from __future__ import annotations

import csv
import io
from datetime import datetime

from flask import (Blueprint, Response, abort, flash, jsonify, redirect, render_template,
                   request, url_for)

from keamanan import butuh, pengguna_sekarang
import progres

bp = Blueprint("belajar", __name__)


def _kelas_atau_404(kelas_id: int) -> dict:
    from app import kueri
    kelas = kueri("SELECT * FROM kelas WHERE id = %s", (kelas_id,), satu=True)
    if not kelas:
        abort(404)
    saya = pengguna_sekarang()
    if saya["peran"] == "admin":
        return kelas
    if saya["peran"] != "dosen" or kelas["dosen_id"] != saya["id"]:
        abort(404)
    return kelas


@bp.get("/belajar")
@butuh("admin", "dosen", "mahasiswa")
def dasbor():
    from app import kueri
    saya = pengguna_sekarang()
    if saya["peran"] != "mahasiswa":
        kelas = kueri("SELECT k.*, (SELECT COUNT(*) FROM kelas_anggota ka WHERE ka.kelas_id=k.id) anggota "
                      "FROM kelas k WHERE %s = 'admin' OR k.dosen_id = %s ORDER BY k.nama",
                      (saya["peran"], saya["id"]))
        return render_template("belajar.html", ringkas=[], kelas_dosen=kelas,
                               nama=saya["nama"], peran=saya["peran"])

    ringkas = progres.ringkasan_mahasiswa(saya["id"])
    detail = []
    for r in ringkas:
        baris = kueri(
            "SELECT g.id, g.judul, g.kategori, (b.id IS NOT NULL) dipelajari "
            "FROM gambar g LEFT JOIN belajar b ON b.gambar_id = g.id AND b.pengguna_id = %s "
            "JOIN kelas k ON k.id = %s "
            "WHERE g.aktif = 1 AND (g.publik = 1 OR g.dosen_id = k.dosen_id) "
            "ORDER BY g.created_at, g.id", (saya["id"], r["id"]))
        detail.append({**r, "preparat": baris})
    return render_template("belajar.html", ringkas=detail, kelas_dosen=[], nama=saya["nama"],
                           peran=saya["peran"])


@bp.post("/api/belajar")
@butuh("mahasiswa")
def tandai():
    from app import kueri
    saya = pengguna_sekarang()
    data = request.get_json(silent=True) or request.form
    try:
        gid = int(data.get("gambar_id"))
    except (TypeError, ValueError):
        return jsonify({"ok": False, "error": "gambar_id tidak sah"}), 400
    nilai = str(data.get("nilai", "1")).lower() not in ("0", "false", "tidak")
    if not kueri("SELECT id FROM gambar WHERE id = %s AND aktif = 1", (gid,), satu=True):
        return jsonify({"ok": False, "error": "preparat tidak ada"}), 404
    status = progres.tandai(saya["id"], gid, nilai)
    return jsonify({"ok": True, "gambar_id": gid, "dipelajari": status})


@bp.post("/preparat/<int:gid>/belajar")
@butuh("admin", "dosen", "mahasiswa")
def tandai_form(gid: int):
    """Jalur tanpa JS: form POST biasa lalu kembali ke preparat."""
    saya = pengguna_sekarang()
    if saya["peran"] != "mahasiswa":
        abort(403)
    nilai = request.form.get("nilai", "1") not in ("0", "", "tidak")
    progres.tandai(saya["id"], gid, nilai)
    flash("Ditandai sudah dipelajari." if nilai else "Tanda dipelajari dibatalkan.", "ok")
    return redirect(url_for("preparat", gid=gid))


@bp.get("/kelas/<int:kelas_id>")
@butuh("admin", "dosen")
def rekap(kelas_id: int):
    from app import kueri
    kelas = _kelas_atau_404(kelas_id)
    baris = progres.rekap_kelas(kelas_id)
    rata = round(sum(b["persen"] for b in baris) / len(baris)) if baris else 0
    daftar_ujian = kueri(
        "SELECT u.*, (SELECT COUNT(*) FROM soal s WHERE s.ujian_id = u.id) jumlah_soal, "
        "(SELECT COUNT(*) FROM pengerjaan p WHERE p.ujian_id = u.id) jumlah_peserta "
        "FROM ujian u WHERE u.kelas_id = %s ORDER BY u.dibuat_pada DESC", (kelas_id,))
    return render_template("kelas.html", kelas=kelas, baris=baris, rata=rata,
                           total_materi=len(progres.materi_kelas(kelas_id)),
                           daftar_ujian=daftar_ujian)


@bp.get("/kelas/<int:kelas_id>.csv")
@butuh("admin", "dosen")
def rekap_csv(kelas_id: int):
    kelas = _kelas_atau_404(kelas_id)
    buf = io.StringIO()
    tulis = csv.writer(buf)
    tulis.writerow(["nama", "pengguna", "dipelajari", "total", "persen", "terakhir"])
    for b in progres.rekap_kelas(kelas_id):
        tulis.writerow([b["nama"], b["pengguna"], b["dipelajari"], b["total"], b["persen"],
                        b["terakhir"].isoformat() if b["terakhir"] else ""])
    nama = f"rekap-{kelas['nama'].lower().replace(' ', '-')}-{datetime.now():%Y%m%d}.csv"
    return Response(buf.getvalue(), mimetype="text/csv",
                    headers={"Content-Disposition": f'attachment; filename="{nama}"'})
