# ========================
# Python Standard Library
# ========================
import os
import uuid
import shutil
import tempfile
import subprocess
from io import BytesIO
import io

import requests

# ========================
# Third-Party Libraries
# ========================
import fitz  # PyMuPDF
from PIL import Image
from PyPDF2 import PdfReader
from pdf2docx import Converter
from pdf2image import convert_from_bytes, convert_from_path
from docx import Document
from docx.shared import Inches
from docx2pdf import convert
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

# ========================
# Django Core
# ========================
from django.conf import settings
from django.contrib import messages
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db import connection
from django.db.models import Q, Value, F, CharField, TextField, IntegerField
from django.db.models.functions import Cast
from django.http import (
    HttpResponse,
    HttpResponseRedirect,
    JsonResponse,
    Http404,
    FileResponse,
    HttpResponseBadRequest,
    HttpResponseServerError,
)
from django.shortcuts import render, get_object_or_404
from django.utils.text import slugify
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

# ========================
# Local Apps
# ========================
from webapp.common import dump, currency, tgl_indo
from webapp.models import koleksi as m_koleksi, master as m_master
from webapp.models.koleksi import (
    ContentVersion,
    ContentVersionAttachment,
    Contents,
    ContentTag,
    Tag,
)
from webapp.models.master import Users
from webapp.utils import upload_to_drive, convert_to_images
import pytesseract

# =====================================
# Konversi WORD ke PDF (Windows + Linux)
# =====================================
import os
import platform
import subprocess
import tempfile
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

try:
    from docx2pdf import convert as docx2pdf_convert
except:
    docx2pdf_convert = None

import platform


# =====================================
# Konversi IMAGE to PDF (hasil teks, bukan gambar)
# =====================================
def convert_image_to_pdf(request):
    if request.method == "POST" and request.FILES.get("file"):
        img_file = request.FILES["file"]
        img = Image.open(img_file)

        # OCR ekstrak teks dari gambar
        text = pytesseract.image_to_string(img, lang="ind")  # pakai "ind" kalau bahasa Indonesia

        response = HttpResponse(content_type="application/pdf")
        response["Content-Disposition"] = f'attachment; filename="{img_file.name}.pdf"'

        c = canvas.Canvas(response, pagesize=letter)
        width, height = letter

        # tulis teks hasil OCR ke PDF (multi-baris)
        y = height - 50
        for line in text.splitlines():
            c.drawString(50, y, line)
            y -= 15
            if y < 50:  # kalau halaman penuh, lanjut halaman baru
                c.showPage()
                y = height - 50

        c.save()
        return response
    return HttpResponse("Invalid request", status=400)


# =====================================
# Konversi IMAGE to WORD (hasil teks, bukan gambar)
# =====================================
def convert_image_to_docx(request):
    if request.method == "POST" and request.FILES.get("file"):
        img_file = request.FILES["file"]
        img = Image.open(img_file)

        # OCR ekstrak teks dari gambar
        text = pytesseract.image_to_string(img, lang="eng")

        doc = Document()
        doc.add_paragraph(text)

        # simpan ke buffer
        buffer = io.BytesIO()
        doc.save(buffer)
        buffer.seek(0)

        # kirim buffer ke response
        response = HttpResponse(
            buffer.getvalue(),
            content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        )
        response["Content-Disposition"] = f'attachment; filename="{img_file.name}.docx"'
        return response
    return HttpResponse("Invalid request", status=400)


# ==========================================
#  🔒 SAFE DOCX → PDF (UNIVERSAL, WINDOWS & LINUX)
# ==========================================
def safe_docx2pdf(input_path, output_path):
    """
    Konversi DOCX ke PDF secara universal:
    - Windows  → menggunakan docx2pdf (Microsoft Word via COM)
    - Linux    → menggunakan LibreOffice headless (lebih stabil dengan writer_pdf_Export)
    """

    system = platform.system().lower()

    # ================================================================
    # 🟦 WINDOWS (LOCAL) — 100% menggunakan Microsoft Word (COM)
    # ================================================================
    if "windows" in system:
        try:
            import pythoncom
            from docx2pdf import convert as docx2pdf_convert

            pythoncom.CoInitialize()
            docx2pdf_convert(input_path, output_path)
            pythoncom.CoUninitialize()

            return output_path

        except Exception as e:
            raise Exception(f"docx2pdf Windows gagal: {str(e)}")

    # ================================================================
    # 🟩 LINUX (SERVER) — LibreOffice Headless (STABIL)
    # ================================================================
    try:
        tmpdir = os.path.dirname(output_path)

        # buat profil terisolasi agar LibreOffice tidak bentrok
        lo_profile = os.path.join(tmpdir, "lo_profile")
        os.makedirs(lo_profile, exist_ok=True)

        # environment aman untuk Apache (www-data)
        env = os.environ.copy()
        env["HOME"] = tmpdir
        env["USER"] = "www-data"
        env["UserInstallation"] = f"file://{lo_profile}"

        # disable harfbuzz untuk menghindari bug layout logo+header terpisah
        env["SAL_DISABLE_HARFBUZZ"] = "1"

        # Gunakan writer_pdf_Export agar layout paling mendekati Word
        cmd = [
            "soffice",
            "--headless",
            "--nologo",
            "--nofirststartwizard",
            "--convert-to", "pdf:writer_pdf_Export",
            "--outdir", tmpdir,
            input_path
        ] 

        result = subprocess.run(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            env=env
        )

        if result.returncode != 0:
            raise Exception(result.stderr)

        return output_path

    except Exception as e:
        raise Exception(f"LibreOffice gagal konversi DOCX → PDF: {str(e)}") 


# =====================================
# Konversi WORD ke IMAGE
# =====================================
@csrf_exempt
@require_POST
def convert_docx_url_to_jpg(request):
    import json

    try:
        data = json.loads(request.body.decode('utf-8'))
    except:
        return JsonResponse({'error': 'Payload tidak valid'}, status=400)

    url = data.get('url')
    name = data.get('name', 'document.docx')

    if not url or not url.lower().endswith('.docx'):
        return JsonResponse({'error': 'URL tidak valid atau bukan DOCX'}, status=400)

    # download file
    r = requests.get(url)
    if r.status_code != 200:
        return JsonResponse({'error': 'Tidak bisa mengunduh DOCX'}, status=400)

    try:
        with tempfile.TemporaryDirectory() as tmpdir:

            # -----------------------------------
            # Siapkan path DOCX & PDF sementara
            # -----------------------------------
            base = slugify(os.path.splitext(name)[0])
            uniq = uuid.uuid4().hex[:8]

            docx_path = os.path.join(tmpdir, f"{base}-{uniq}.docx")
            pdf_path  = os.path.join(tmpdir, f"{base}-{uniq}.pdf")

            # simpan DOCX
            with open(docx_path, "wb") as f:
                f.write(r.content)

            # -----------------------------------
            # Konversi DOCX → PDF universal
            # -----------------------------------
            safe_docx2pdf(docx_path, pdf_path)

            if not os.path.exists(pdf_path):
                return JsonResponse({'error': 'PDF gagal dibuat'}, status=500)

            # -----------------------------------
            # Konversi PDF → IMAGE
            # -----------------------------------
            images = convert_from_path(pdf_path, dpi=200)

            out_folder = os.path.join(settings.MEDIA_ROOT, "converted_images", f"{base}-{uniq}")
            os.makedirs(out_folder, exist_ok=True)

            urls = []
            for i, img in enumerate(images, start=1):
                filename = f"page_{i}.jpg"
                save_path = os.path.join(out_folder, filename)
                img.save(save_path, "JPEG")

                urls.append(f"{settings.MEDIA_URL}converted_images/{base}-{uniq}/{filename}")

        return JsonResponse({"status": "success", "images": urls})

    except Exception as e:
        return JsonResponse({"error": str(e)}, status=500)


# =====================================
# Konversi WORD ke PDF (UNIVERSAL)
# =====================================
def convert_docx_universal(input_path, tmpdir):
    system = platform.system().lower()

    # ---------------------------
    # Local Windows
    # ---------------------------
    if "windows" in system:
        if docx2pdf_convert is None:
            raise Exception("docx2pdf tidak tersedia di Windows.")
        output_path = os.path.join(tmpdir, os.path.basename(input_path).replace(".docx", ".pdf"))

        import pythoncom
        pythoncom.CoInitialize()
        docx2pdf_convert(input_path, output_path)
        pythoncom.CoUninitialize()

        return output_path

    # ---------------------------
    # Server Linux (Apache)
    # ---------------------------
    lo_profile = os.path.join(tmpdir, "lo_profile")
    os.makedirs(lo_profile, exist_ok=True)

    env = os.environ.copy()
    env["HOME"] = tmpdir                  # FIX: hindari /var/www/.cache
    env["USER"] = "www-data"             # Penting untuk Apache
    env["UserInstallation"] = f"file://{lo_profile}"

    cmd = [
        "soffice",
        "--headless",
        "--nologo",
        "--nofirststartwizard",
        "--invisible",
        "--convert-to", "pdf:writer_pdf_Export",
        "--outdir", tmpdir,
        input_path
    ]

    result = subprocess.run(
        cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True,
        env=env
    )

    if result.returncode != 0:
        raise Exception(
            "LibreOffice error:\n" + result.stderr
        )

    filename = os.path.basename(input_path).replace(".docx", ".pdf")
    return os.path.join(tmpdir, filename)


# =====================================
# Endpoint: Konversi WORD ke PDF
# =====================================
@csrf_exempt
@require_POST
def convert_word_to_pdf(request):
    try:
        uploaded_file = request.FILES['file']

        with tempfile.TemporaryDirectory() as tmpdir:
            original_path = os.path.join(tmpdir, uploaded_file.name)

            # Simpan file sementara
            with open(original_path, "wb+") as f:
                for chunk in uploaded_file.chunks():
                    f.write(chunk)

            # Hapus spasi di nama file (WAJIB)
            safe_name = uploaded_file.name.replace(" ", "_")
            input_path = os.path.join(tmpdir, safe_name)
            os.rename(original_path, input_path)

            # ---------------------------
            # Konversi universal
            # ---------------------------
            output_path = convert_docx_universal(input_path, tmpdir)

            if not os.path.exists(output_path):
                return JsonResponse({"error": "PDF gagal dibuat"}, status=500)

            with open(output_path, "rb") as pdf_file:
                pdf_data = pdf_file.read()

            # Kirim PDF
            response = HttpResponse(pdf_data, content_type="application/pdf")
            response['Content-Disposition'] = f'attachment; filename="{os.path.basename(output_path)}"'
            return response

    except Exception as e:
        return JsonResponse({"error": str(e)}, status=500)

# =====================================
# Konversi PDF URL ke WORD
# =====================================
@csrf_exempt
@require_POST
def convert_pdf_url_to_word(request):
    """
    Konversi PDF berdasarkan URL lampiran menjadi DOCX dan kirim langsung.
    """
    data = request.body.decode('utf-8')
    try:
        payload = json.loads(data)
    except:
        return JsonResponse({'error': 'Payload tidak valid'}, status=400)

    url = payload.get('url')
    name = payload.get('name', 'document.pdf')
    if not url or not url.lower().endswith('.pdf'):
        return JsonResponse({'error': 'URL tidak valid atau bukan PDF'}, status=400)

    r = requests.get(url)
    if r.status_code != 200:
        return JsonResponse({'error': 'Tidak bisa mengunduh PDF dari URL'}, status=400)

    with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmpf:
        tmpf.write(r.content)
        tmp_path = tmpf.name

    docx_path = tmp_path.replace('.pdf', '.docx')
    cv = Converter(tmp_path)
    cv.convert(docx_path, start=0, end=None)
    cv.close()

    with open(docx_path, 'rb') as fp:
        resp = HttpResponse(fp.read(), content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
        resp['Content-Disposition'] = f'attachment; filename="{slugify(name).replace(".pdf","")}.docx"'

    os.remove(tmp_path)
    os.remove(docx_path)
    return resp


# =====================================
# Konversi PDF URL ke Gambar
# =====================================
import json
@csrf_exempt
@require_POST
def convert_pdf_url_to_jpg(request):
    """
    Konversi PDF berdasarkan URL menjadi satu atau beberapa gambar JPG, kembalikan JSON array URL gambar.
    """
    data = request.body.decode('utf-8')
    try:
        payload = json.loads(data)
    except:
        return JsonResponse({'error': 'Payload tidak valid'}, status=400)

    url = payload.get('url')
    name = payload.get('name', 'document.pdf')
    if not url or not url.lower().endswith('.pdf'):
        return JsonResponse({'error': 'URL tidak valid atau bukan PDF'}, status=400)

    r = requests.get(url)
    if r.status_code != 200:
        return JsonResponse({'error': 'Tidak bisa mengunduh PDF dari URL'}, status=400)

    try:
        images = convert_from_bytes(r.content, dpi=200)
    except Exception as e:
        return JsonResponse({'error': f'Konversi gagal: {e}'}, status=500)

    base = slugify(os.path.splitext(name)[0])
    unique = uuid.uuid4().hex[:8]
    folder = os.path.join(settings.MEDIA_ROOT, 'converted_images', f"{base}-{unique}")
    os.makedirs(folder, exist_ok=True)

    urls = []
    for idx, img in enumerate(images, start=1):
        fn = f"page_{idx}.jpg"
        path = os.path.join(folder, fn)
        img.save(path, 'JPEG')
        urls.append(f"{settings.MEDIA_URL}converted_images/{base}-{unique}/{fn}")

    return JsonResponse({'status': 'success', 'images': urls})


# =====================================
# Upload PDF ke Google Drive
# =====================================
def upload_pdf_to_drive(request):
    """
    Upload PDF ke Google Drive dan kembalikan link.
    """
    if request.method == 'POST':
        file = request.FILES.get('file')
        if file:
            try:
                link = upload_to_drive(file, file.name)
                return JsonResponse({
                    'status': 'success',
                    'file_name': file.name,
                    'web_link': 'https://drive.google.com/drive/folders/19pH19iCJ8hNr9OF0TwyWwMiKeR-_iecS'
                })
            except Exception as e:
                return JsonResponse({'status': 'error', 'message': str(e)})
        else:
            return JsonResponse({'status': 'error', 'message': 'File tidak ditemukan.'})

    return JsonResponse({'status': 'error', 'message': 'Metode request harus POST'})


# =====================================
# Konversi PDF ke Gambar
# =====================================
@csrf_exempt
@require_POST
def convert_to_images(request):
    """
    Konversi PDF ke beberapa gambar (PNG).
    """
    pdf_file = request.FILES.get('file')
    if not pdf_file:
        return JsonResponse({'status': 'error', 'message': 'No PDF file provided'}, status=400)

    unique_id = uuid.uuid4().hex[:8]
    base_name = slugify(os.path.splitext(pdf_file.name)[0])
    filename = f"{base_name}-{unique_id}.pdf"
    pdf_path = os.path.join(settings.MEDIA_ROOT, 'converted_pdfs', filename)

    os.makedirs(os.path.dirname(pdf_path), exist_ok=True)

    # Simpan PDF
    with default_storage.open(pdf_path, 'wb+') as destination:
        for chunk in pdf_file.chunks():
            destination.write(chunk)

    # Konversi ke gambar
    doc = fitz.open(pdf_path)
    image_urls = []
    image_folder = os.path.join(settings.MEDIA_ROOT, 'converted_images', f"{base_name}-{unique_id}")
    os.makedirs(image_folder, exist_ok=True)

    for i in range(len(doc)):
        page = doc.load_page(i)
        pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))  # Resolusi lebih tinggi
        image_filename = f"page_{i+1}.png"
        image_path = os.path.join(image_folder, image_filename)
        pix.save(image_path)

        image_url = f"{settings.MEDIA_URL}converted_images/{base_name}-{unique_id}/{image_filename}"
        image_urls.append(image_url)

    doc.close()
    return JsonResponse({'status': 'success', 'images': image_urls})


# =====================================
# Konversi PDF ke Word
# =====================================
@csrf_exempt
@require_POST
def convert_to_word(request):
    """
    Konversi PDF ke file Word (.docx).
    """
    file = request.FILES.get('file')
    if not file or not file.name.endswith('.pdf'):
        return HttpResponse("File tidak valid. Harap unggah file PDF.", status=400)

    with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_pdf:
        tmp_pdf.write(file.read())
        tmp_pdf_path = tmp_pdf.name

    tmp_docx_path = tmp_pdf_path.replace('.pdf', '.docx')
    cv = Converter(tmp_pdf_path)
    cv.convert(tmp_docx_path, start=0, end=None)
    cv.close()

    with open(tmp_docx_path, 'rb') as docx_file:
        response = HttpResponse(
            docx_file.read(),
            content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        )
        response['Content-Disposition'] = f'attachment; filename="{os.path.basename(tmp_docx_path)}"'

    os.remove(tmp_pdf_path)
    os.remove(tmp_docx_path)
    return response


def safe_str(val):
    if isinstance(val, bytes):
        try:
            return val.decode("utf-8", errors="ignore")
        except Exception:
            return val.decode("latin-1", errors="ignore")
    return str(val) if val is not None else ""

# =====================================
# Daftar Konten (List)
# =====================================
def page_list(request, pk=None):
    """
    Tampilkan daftar konten dengan filter, sorting, dan pagination.
    """
    my_filter = {}
    f = Q()
    if not request.GET:
        for key in ['term', 'search_skpd', 'search_kategori', 'tahun', 'search_tag', 'display', 'show', 'sorting']:
            request.session.pop(key, None)
    if 'sorting' not in request.session:
        request.session['sorting'] = 'desc'

    term = request.GET.get('term', '').strip()
    if term:
        request.session["term"] = term
    else:
        request.session.pop("term", None)

    # kalau kosong, hapus session lama biar nggak nempel
    request.session.pop("term", None)
    
    search_skpd = request.GET.get('pk_skpd_dg')
    tahun = request.GET.get('tahun')
    disp = request.GET.get('disp')
    item_jml = request.GET.get('item_jml')
    sorting = request.GET.get('sorting')
    reset = request.GET.get('reset', 0)
    page = int(request.GET.get('page', 1) or 1)
    tag_term = request.GET.get('tag', '').strip()
    if tag_term:
        request.session["tag"] = tag_term
    else:
        request.session.pop("tag", None)

    if pk and pk != 1 and str(pk).isdigit():
        request.session['search_kategori'] = int(pk)
    elif pk is None and 'search_kategori' not in request.GET:
        request.session.pop('search_kategori', None)

    if search_skpd:
        request.session['search_skpd'] = search_skpd

    if tahun and tahun.isnumeric():
        request.session['tahun'] = int(tahun)

    if disp:
        request.session['display'] = 'list' if disp == 'list' else 'col'

    if item_jml and item_jml.isnumeric():
        request.session['show'] = int(item_jml)

    if sorting:
        request.session['sorting'] = sorting

    if term:
        request.session['term'] = term
    
    if tag_term:
        request.session['search_tag'] = tag_term

    if reset == '1':
        for key in ['term', 'search_skpd', 'search_kategori', 'tahun','search_tag']:
            request.session.pop(key, None)

    if request.session.get('search_skpd'):
        my_filter['pk_skpd_dg'] = int(request.session['search_skpd'])
    if request.session.get('search_kategori'):
        my_filter['pk_categories'] = int(request.session['search_kategori'])
    if request.session.get('tahun'):
        my_filter['tahun'] = int(request.session['tahun'])
    if request.session.get('search_tag'):
        tag_filter = request.session['search_tag']
        f &= Q(contenttag_tagname_icontains=tag_filter)

    for key, value in my_filter.items():
        f &= Q(**{key: value})

    if request.session.get('term'):
        term_value = request.session['term']
        fields = [
            field.name
            for field in m_koleksi.Contents._meta.get_fields()
            if isinstance(field, (CharField, TextField)) and not field.is_relation
        ]
        if fields:
            q = Q()
            for field in fields:
                q |= Q(**{f"{field}__icontains": term_value})
            f &= q

    order = '-created' if request.session.get('sorting') == 'desc' else 'created'
    query = m_koleksi.Contents.objects.filter(f).order_by(order).annotate(
        attributess=Cast('attributes', CharField())
    ).defer('attributes')

    item_per_page = request.session.get('show', 8)
    if item_per_page not in [4, 8, 12, 16, 20]:
        item_per_page = 8
    paginator = Paginator(query, item_per_page)
    paging = paginator.get_page(page)

    result = []
    for item in paging:
        item = m_koleksi.Contents._sanitize_result(item)
        # item['attachments'] = m_koleksi.Attachments._read_many(asis=1, pk_contents=item['pk']).count()
        attachments_qs = m_koleksi.Attachments._read_many(asis=1, pk_contents=item['pk'], is_deleted=False)
        item['attachments'] = attachments_qs.count()
        item['attachments_list'] = [
            {'name': safe_str(a.name), 'path': safe_str(a.path)} for a in attachments_qs
        ]

        item['thumbnail'] = [
                {'path': safe_str(a.path)} for a in m_koleksi.Attachments._read_many(asis=1, pk_contents=item['pk'])
        ]
        item['pk_skpd_dg'] = m_master.Skpddg._read_many(asis=1, pk=item['pk_skpd_dg']).count()
        result.append(item)

    return render(request, 'fileman/list.html', {
        'pk_categories': int(pk) if pk and str(pk).isdigit() else '',
        'categories_list': m_koleksi.Categories._recursive(pk_parent=0, deep=0),
        'skpd_list': m_master.Skpddg.objects.all(),
        'list': result,
        'paging': paging,
        'term_current': request.session.get('term', ''),
        'search_skpd_dg': int(request.session.get('search_skpd')) if str(request.session.get('search_skpd')).isdigit() else '',
        'search_kategori': int(request.session.get('search_kategori', '')) if str(request.session.get('search_kategori', '')).isdigit() else '',
        'search_tahun': int(request.session.get('tahun')) if str(request.session.get('tahun')).isdigit() else '',
        'display': request.session.get('display', 'list'),
        'show': item_per_page,
        'sorting': request.session.get('sorting', 'desc'),
        'search_tag': request.session.get('search_tag', ''),
        
    })


def page_item(request, pk):
    """
    Detail satu konten.
    """
    result = m_koleksi.Contents._read_one(asis=1, pk=pk)
    attachments = m_koleksi.Attachments._read_many(asis=1, pk_contents=pk, is_deleted=False)
    status_konten = result.status_konten

    user_pk = request.session.get('pk')
    user_role = request.session.get('role')
    allow = 'yes' if result.user_input == user_pk or user_role in ['ADMIN', 'KOORDINATOR'] else 'no'

    categories, attributes, skpd = None, None, None

    if result.pk_categories:
        categories = m_koleksi.Categories._recursive_reverse(pk=result.pk_categories.pk)
        attr_obj = m_koleksi.Categories._read_one(pk=result.pk_categories.pk)
        attributes = attr_obj['attributes'] if attr_obj else None

        for key in result.attributes:
            if attributes and attributes[key]['type'] == 'money':
                result.attributes[key] = currency(result.attributes[key])
            if attributes and attributes[key]['type'] == 'date':
                result.attributes[key] = tgl_indo(result.attributes[key])

    if result.pk_skpd_dg:
        skpd = m_master.Skpddg._read_one(pk=result.pk_skpd_dg.pk)

    user_yg_input = m_master.Users._read_one(asis=1, pk=result.user_input).usr.upper()
    versions = ContentVersion.objects.filter(pk_contents=pk).order_by('-created')

    # Ambil versi PDF terbaru
    latest_version = versions.first()
    latest_attachment = None
    if latest_version:
        latest_attachment = (
            ContentVersionAttachment.objects.filter(pk_version=latest_version.pk)
            .order_by('-created')
            .first()
        )

    # Sama seperti di page_list → bawa path
    result.latest_pdf = latest_attachment.path if latest_attachment else None

    return render(request, 'fileman/item.html', {
        'item': result,
        'attachments': attachments,
        'categories': categories,
        'attributes': attributes,
        'skpd': skpd,
        'allow': allow,
        'user_yg_input': user_yg_input,
        'status_konten': status_konten,
        'versions': versions,
    })



# # =====================================
# # Riwayat Versi
# # =====================================
# def page_history(request, pk):
#     """
#     Tampilkan riwayat versi konten.
#     """
#     content = m_koleksi.Contents._read_one(pk=pk)

#     with connection.cursor() as cursor:
#         cursor.execute("""
#             SELECT cv.*, u.usr AS user_nama
#             FROM content_versions cv
#             LEFT JOIN users u ON u.pk = cv.user_input
#             WHERE cv.pk_contents = %s
#             ORDER BY cv.created DESC
#         """, [pk])
#         columns = [col[0] for col in cursor.description]
#         versions = [dict(zip(columns, row)) for row in cursor.fetchall()]

#     for v in versions:
#         v['attachments'] = ContentVersionAttachment.objects.filter(pk_version=v['pk'])

#     return render(request, 'fileman/history.html', {
#         'item': content,
#         'versions': versions,
#     })

def page_history(request, pk):
    """
    Tampilkan riwayat versi konten.
    """
    content = m_koleksi.Contents._read_one(pk=pk)

    with connection.cursor() as cursor:
        cursor.execute("""
            SELECT cv.*, u.usr AS user_nama
            FROM content_versions cv
            LEFT JOIN users u ON u.pk = cv.user_input
            WHERE cv.pk_contents = %s
            ORDER BY cv.created DESC
        """, [pk])
        columns = [col[0] for col in cursor.description]
        versions_list = [dict(zip(columns, row)) for row in cursor.fetchall()]

    # Lampirkan attachments
    for v in versions_list:
        v['attachments'] = ContentVersionAttachment.objects.filter(pk_version=v['pk'])

    # ==== PAGINATOR ====
    paginator = Paginator(versions_list, 6)  # 6 per halaman
    page_number = request.GET.get('page')
    versions_page = paginator.get_page(page_number)

    return render(request, 'fileman/history.html', {
        'item': content,
        'versions': versions_page,  # yang dipakai di template: paginated
    })


# # =====================================
# # Detail Tag
# # =====================================
# def page_tag_detail(request, tag_name):
#     """
#     Detail tag dan daftar konten dengan tag tersebut.
#     """
#     tag = get_object_or_404(Tag, name=tag_name.lower())
#     contents = Contents.objects.filter(contenttag__tag=tag).order_by('-created')

#     return render(request, 'fileman/tags_detail.html', {
#         'tag': tag,
#         'contents': contents,
#     })



# =====================================
# Detail Tag dengan Paginasi
# =====================================
def page_tag_detail(request, tag_name):
    """
    Detail tag dan daftar konten dengan tag tersebut.
    """
    tag = get_object_or_404(Tag, name=tag_name.lower())
    contents_list = Contents.objects.filter(contenttag__tag=tag).order_by('-created')

    # Tambahkan Paginator
    paginator = Paginator(contents_list, 8)
    page = request.GET.get('page')

    try:
        contents = paginator.page(page)
    except PageNotAnInteger:
        contents = paginator.page(1)
    except EmptyPage:
        contents = paginator.page(paginator.num_pages)

    return render(request, 'fileman/tags_detail.html', {
        'tag': tag,
        'contents': contents,
    })


def _get_queryset(request):
    """
    Helper untuk API & view biasa
    Supaya query list berkas konsisten.
    """
    query = Contents.objects.all().order_by("-created")

    # optional: filter by search, kategori, dll
    search = request.GET.get("search")
    if search:
        query = query.filter(title__icontains=search)

    kategori = request.GET.get("kategori")
    if kategori:
        query = query.filter(category=kategori)

    return query