from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse, HttpResponseForbidden
from django.template.loader import render_to_string
from django.utils.dateparse import parse_date
from django.contrib.auth.decorators import login_required

from .models import Student, MadrasahProfile


def index(request):
    student = None
    query = ''
    if request.method == 'POST':
        query = request.POST.get('nisn', '').strip()
        if query:
            try:
                student = Student.objects.get(nisn=query)
                return redirect('kelulusan:result', nisn=student.nisn)
            except Student.DoesNotExist:
                student = None
    return render(request, 'index.html', {'query': query, 'student': student})


def result_view(request, nisn):
    student = get_object_or_404(Student, nisn=nisn)
    token = f"VERIF|{student.nisn}|{student.full_name}"

    # Halaman loading (buat jeda/\"surprise\") sebelum tampilkan hasil asli
    if request.GET.get('loaded') != '1':
        redirect_url = f"/result/{student.nisn}/?loaded=1"
        return render(
            request,
            'loading_result.html',
            {
                'student': student,
                'token': token,
                'redirect_url': redirect_url,
            }
        )

    return render(request, 'result.html', {'student': student, 'token': token})


def _generate_filled_pdf_bytes(student: Student, profile: MadrasahProfile) -> bytes:
    """
    Generate PDF final bytes dari base PDF template_pdf.pdf dengan overlay data dinamis.
    Fokus menyesuaikan elemen yang berubah terhadap pdf_template_safe.html.
    """
    from io import BytesIO
    import os
    from django.conf import settings

    from reportlab.pdfgen import canvas
    from reportlab.lib.units import mm
    from pypdf import PdfReader, PdfWriter

    # Path absolut yang konsisten (hindari masalah os.getcwd() di Windows/WSGI)
    base_pdf_path = os.path.join(
        str(settings.BASE_DIR),
        'media',
        'template_pdf',
        'template_pdf.pdf',
    )

    if not os.path.exists(base_pdf_path):
        raise FileNotFoundError(f'Base PDF template tidak ditemukan: {base_pdf_path}')

    reader = PdfReader(base_pdf_path)
    page0 = reader.pages[0]
    media_box = page0.mediabox
    page_w = float(media_box.width)
    page_h = float(media_box.height)

    # === Helper: formatting ===
    # Pastikan “Tanggal Terbit” pada PDF selalu 2 Juni 2026
    from datetime import date
    try:
        issued_str = '02 Juni 2026'
    except Exception:
        issued_str = '02 Juni 2026'


    status_text = 'LULUS' if (student.status == 'L') else 'TIDAK LULUS'

    nomor_sk = student.nomor_sk if getattr(student, 'nomor_sk', None) else ''
    if not nomor_sk:
        nomor_sk = '123/01'

    kepala = getattr(profile, 'kepala_madrasah', '') if profile else ''

    # sk_barcode (barcode-right) di template safe
    sk_barcode_path = None
    if getattr(student, 'sk_barcode', None) and getattr(student.sk_barcode, 'path', None):
        if os.path.exists(student.sk_barcode.path):
            sk_barcode_path = student.sk_barcode.path

    buf_overlay = BytesIO()
    c = canvas.Canvas(buf_overlay, pagesize=(page_w, page_h))

    # =============================================
    # CALIBRATION AWAL (berdasarkan @page margin)
    # template safe: margin:12mm 15mm (top/bottom=12, left/right=15)
    # reportlab coord: (0,0) bottom-left
    # =============================================
    margin_top = 12 * mm
    margin_left = 15 * mm
    margin_right = 15 * mm
    usable_top = page_h - margin_top

    center_x = page_w / 2

    # Untuk mapping posisi, kita gunakan jarak dari atas (usable_top) dengan estimasi
    # mengikuti struktur HTML (title -> content table -> status -> footer).
    text_left = margin_left + 20 + 17 * mm  # geser ke kanan +5mm agar menjorok
    # 1) NOMOR (bagian title)
    # HTML: .title .nomor margin-top:8px; font-size 14px; teks terpusat-ish
    c.setFont('Times-Bold', 12)
    nomor_y = usable_top - 73 * mm  # posisi awal nomor
    c.drawCentredString(center_x -2, nomor_y,'Nomor : ' f'{nomor_sk}')

    # 2) TABEL IDENTITAS (Full Name, NISN, Kelas, Issued Date)
    # HTML: .content margin-top:35px; .student-table margin-top:25px; line-height:2;
    # Kita tempatkan baris-baris sejajar di kotak tabel.
    c.setFont('Times-Roman', 12)
    base_table_y = usable_top - 110 * mm

    line_gap = 6 * mm

    c.drawString(text_left, base_table_y,'Nama                : ' f'{student.full_name or ""}')
    c.drawString(text_left, base_table_y - line_gap, 'NISN                : ' f'{student.nisn or ""}')
    c.drawString(text_left, base_table_y - 2 * line_gap, 'Kelas                : ' f'{student.kelas or ""}')
    c.drawString(text_left, base_table_y - 3 * line_gap, 'Tanggal Terbit : ' f'{issued_str}')

    # 3) STATUS BESAR (LULUS/TIDAK LULUS)
    # HTML: .status h1 font-size 54px; letter-spacing:5px;
    # reportlab: 54px ~ 40pt (estimasi). Mulai dari 46pt.
    c.setFont('Times-Bold', 30)
    status_y = usable_top - 182 * mm
    full_text = "LULUS / TIDAK LULUS"

# Tampilkan teks di tengah
    c.drawCentredString(center_x, status_y, full_text)

    # =========================
    # CORET "TIDAK LULUS"
    # =========================

    # Lebar seluruh teks
    full_width = c.stringWidth(full_text, 'Times-Bold', 46)

    # Lebar teks sebelum "TIDAK LULUS"
    before_text = "LULUS / "
    before_width = c.stringWidth(before_text, 'Times-Bold', 51)

    # Lebar "TIDAK LULUS"
    strike_text = "TIDAK LULUS"
    strike_width = c.stringWidth(strike_text, 'Times-Bold', 31)

    # Posisi awal teks keseluruhan
    start_x = center_x - (full_width / 2)

    # Posisi awal dan akhir garis coret
    strike_x1 = start_x + before_width
    strike_x2 = strike_x1 + strike_width

    # Posisi garis tengah tulisan
    line_y = status_y + 10

    # Gambar garis coret
    c.setLineWidth(2)
    c.line(strike_x1, line_y, strike_x2, line_y)

    #

    # 4) BARIS “Klaten, <issued_date>” (footer)
    c.setFont('Times-Roman', 12)
    klaten_y = 85 * mm
    line_gap = 5 * mm
    c.drawString(margin_left + 318, klaten_y, f'Tulung, {issued_str}'.replace('  ', ' ').strip())
    c.drawString(margin_left + 318, klaten_y - line_gap, 'Kepala Madrasah')  # posisi bawahnya kepala
    c.drawString(margin_left + 318, klaten_y - 2 * line_gap, 'MTs Sunan Kalijaga')  # signature line

    # 5) NAMA KEPALA (bagian bawah signature)
    c.setFont('Times-Roman', 13)

    kepala_y = 38 * mm
    center_x = margin_left +    208 + 56 * mm  # posisi tengah di area signature
    c.drawCentredString(center_x, kepala_y, f'{kepala or ""}')

    # NIP di bawah nama kepala (untuk download PDF)
    nip_text = "NIP. 197312072009011006"
    c.setFont('Times-Roman', 11)
    center_x = margin_left +    208 + 61 * mm
    c.drawCentredString(center_x, kepala_y - 5 * mm, nip_text)

    # 6) BARCODE-RIGHT
    # HTML: .barcode-right img width:120px; kira-kira ~40mm-45mm
    if sk_barcode_path:
        bc_w = 27 * mm
        bc_h = 27 * mm
        bc_x = margin_left + 157 + 56 * mm   # geser ke kanan +20 untuk jarak dari nama kepala
        bc_y = 44 * mm

        # gambar barcode
        c.drawImage(
            sk_barcode_path,
            bc_x,
            bc_y,
            width=bc_w,
            height=bc_h
        )

        # overlay logo MTS di tengah barcode agar terlihat profesional dan tetap scanable
        # (logo dibuat kecil + ditimpa setelah barcode)
        from django.conf import settings as dj_settings
        logo_path = os.path.join(str(dj_settings.BASE_DIR), 'media', 'madrasah_logos', 'LOGOMDA.png')
        if os.path.exists(logo_path):
            # Paling aman untuk scan: logo kecil tanpa background putih yang menutup modul barcode
            logo_size = 6 * mm
            logo_x = bc_x + (bc_w - logo_size) / 2
            logo_y = bc_y + (bc_h - logo_size) / 2

            c.drawImage(
                logo_path,
                logo_x,
                logo_y,
                width=logo_size,
                height=logo_size,
                mask='auto'
            )

    c.showPage()
    c.save()

    buf_overlay.seek(0)
    overlay_reader = PdfReader(buf_overlay)
    overlay_page = overlay_reader.pages[0]

    writer = PdfWriter()
    for i, p in enumerate(reader.pages):
        if i == 0:
            p.merge_page(overlay_page)
        writer.add_page(p)

    out_buf = BytesIO()
    writer.write(out_buf)
    out_buf.seek(0)
    return out_buf.getvalue()


def download_pdf(request, nisn):
    student = get_object_or_404(Student, nisn=nisn)
    profile = MadrasahProfile.objects.first()

    try:
        pdf_bytes = _generate_filled_pdf_bytes(student, profile)
    except Exception as e:
        return HttpResponse(f'Gagal membuat PDF: {type(e).__name__}: {e}', status=500)

    response = HttpResponse(pdf_bytes, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename=surat_kelulusan_{nisn}.pdf'
    return response



def preview_pdf_html(request, nisn):
    """
    Halaman preview (HTML) yang menampilkan PDF di dalam iframe.
    Menggunakan URL relatif agar origin/port match dan tidak memicu penolakan iframe.
    """
    preview_pdf_path = f'/preview-pdf/{nisn}/'  # relatif
    return HttpResponse(
        f'''<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Preview Surat Kelulusan</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body {{ margin:0; padding:0; font-family: Arial, sans-serif; background:#f6f6f6; }}
    header {{ padding:12px 16px; background:#fff; border-bottom:1px solid #e6e6e6; }}
    .wrap {{ padding:16px; }}
    iframe {{ width:100%; height:calc(100vh - 120px); border:1px solid #ddd; background:#fff; }}
    a {{ color:#1f6feb; text-decoration:none; }}
  </style>
</head>
<body>
  <header>
    <div style="display:flex; gap:12px; align-items:center; justify-content:space-between;">
      <strong>Preview PDF</strong>
      <a href="{preview_pdf_path}" target="_blank" rel="noopener">Buka PDF</a>
    </div>
  </header>
  <div class="wrap">
    <iframe src="{preview_pdf_path}" title="Preview PDF"></iframe>
  </div>
</body>
</html>''',
        content_type='text/html; charset=utf-8'
    )


def preview_pdf_file(request, nisn):
    """Kirim PDF untuk iframe preview (inline).

    Preview harus sama dengan hasil download.
    """
    student = get_object_or_404(Student, nisn=nisn)
    profile = MadrasahProfile.objects.first()

    try:
        pdf_bytes = _generate_filled_pdf_bytes(student, profile)
    except Exception as e:
        return HttpResponse(f'Gagal membuat preview PDF: {type(e).__name__}: {e}', status=500)

    response = HttpResponse(pdf_bytes, content_type='application/pdf')
    response['Content-Disposition'] = f'inline; filename=preview_surat_kelulusan_{nisn}.pdf'
    return response



def verify_token(request, token):
    parts = token.split('|')
    student = None
    valid = False

    profile = MadrasahProfile.objects.first()
    kepala = getattr(profile, 'kepala_madrasah', '') if profile else ''

    if len(parts) >= 2 and parts[0] == 'VERIF':
        nisn = parts[1]
        try:
            student = Student.objects.get(nisn=nisn)
            valid = True
        except Student.DoesNotExist:
            valid = False

    return render(
        request,
        'verify.html',
        {
            'valid': valid,
            'student': student,
            'token': token,
            'kepala': kepala,
        }
    )


@login_required
def download_template_excel(request):
    if not request.user.is_staff:
        return HttpResponseForbidden("Anda tidak memiliki akses.")

    try:
        import openpyxl
        from openpyxl.workbook import Workbook
    except Exception as e:
        return HttpResponse(f"openpyxl tidak tersedia: {e}", status=500)

    wb = Workbook()
    ws = wb.active
    ws.title = "Template"

    headers = ["nisn", "full_name", "kelas", "status", "issued_date", "nomor_sk"]
    ws.append(headers)

    # contoh row kosong
    ws.append(["1234567890", "Nama Siswa", "VII-A", "L", "2026-01-01", ""])

    for col in range(1, len(headers) + 1):
        ws.cell(row=1, column=col).font = openpyxl.styles.Font(bold=True)

    import io
    output = io.BytesIO()
    wb.save(output)
    output.seek(0)

    response = HttpResponse(
        output.getvalue(),
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    response["Content-Disposition"] = 'attachment; filename="template_import_kelulusan.xlsx"'
    return response


@login_required
def import_excel(request):
    if not request.user.is_staff:
        return HttpResponseForbidden("Anda tidak memiliki akses.")

    result = None

    if request.method == "POST" and request.FILES.get("file"):
        upload = request.FILES["file"]
        filename = upload.name.lower()

        try:
            import pandas as pd
        except Exception as e:
            result = {
                "ok": False,
                "message": f"pandas tidak tersedia: {e}",
                "created": 0,
                "updated": 0,
                "skipped": 0,
                "errors": 1,
            }
            return render(request, "import_excel.html", {"result": result})

        try:
            if filename.endswith(".csv"):
                df = pd.read_csv(upload)
            else:
                # default: xlsx/xls
                df = pd.read_excel(upload)
        except Exception as e:
            result = {
                "ok": False,
                "message": f"Gagal membaca file Excel: {e}",
                "created": 0,
                "updated": 0,
                "skipped": 0,
                "errors": 1,
            }
            return render(request, "import_excel.html", {"result": result})

        required = ["nisn", "full_name", "kelas", "status", "issued_date"]
        missing = [c for c in required if c not in df.columns]
        if missing:
            result = {
                "ok": False,
                "message": f"Kolom wajib tidak ditemukan: {', '.join(missing)}",
                "created": 0,
                "updated": 0,
                "skipped": 0,
                "errors": 1,
            }
            return render(request, "import_excel.html", {"result": result})

        created = 0
        updated = 0
        skipped = 0
        errors = 0

        for idx, row in df.iterrows():
            try:
                nisn = str(row.get("nisn", "")).strip()
                full_name = str(row.get("full_name", "")).strip()
                kelas = "" if pd.isna(row.get("kelas")) else str(row.get("kelas")).strip()
                status_raw = row.get("status")

                if not nisn or not full_name:
                    skipped += 1
                    continue

                status = "T"
                if isinstance(status_raw, str):
                    status_clean = status_raw.strip().upper()
                    if status_clean in ["L", "T"]:
                        status = status_clean

                issued_raw = row.get("issued_date")
                issued_date = None
                if not pd.isna(issued_raw):
                    # try pandas timestamp/string -> date
                    if hasattr(issued_raw, "to_pydatetime"):
                        issued_date = issued_raw.to_pydatetime().date()
                    else:
                        issued_date = parse_date(str(issued_raw).strip())

                nomor_sk = ""
                if "nomor_sk" in df.columns:
                    nomor_sk_raw = row.get("nomor_sk")
                    nomor_sk = "" if pd.isna(nomor_sk_raw) else str(nomor_sk_raw).strip()

                if not nomor_sk:
                    # Auto-generate nomor SK jika kolom nomor_sk kosong/tidak ada
                    # Format: SK-LULUS-YYYY-<nisn>
                    from django.utils import timezone as dj_timezone
                    tahun = dj_timezone.now().year
                    nomor_sk = f"SK-LULUS-{tahun}-{nisn}"

                student, was_created = Student.objects.get_or_create(nisn=nisn, defaults={})
                if was_created:
                    created += 1

                student.full_name = full_name
                student.kelas = kelas
                student.status = status
                student.issued_date = issued_date
                student.nomor_sk = nomor_sk
                student.save()

                if not was_created:
                    updated += 1
            except Exception:
                errors += 1

        result = {
            "ok": True,
            "message": f"Import selesai. Total: {len(df)} baris.",
            "created": created,
            "updated": updated,
            "skipped": skipped,
            "errors": errors,
        }

    return render(request, "import_excel.html", {"result": result})
