
from http import HTTPStatus

from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
from django.urls import reverse
from django.contrib import messages
from django.shortcuts import render,redirect

from webapp.views.base import CommonView,CommonForm,CommonModelForm
from webapp.models import (koleksi as m_koleksi, master as m_master)
from webapp.common import dump, log_activity
from webapp.models.koleksi import ContentVersion, ContentVersionAttachment, Tag, ContentTag
import json
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from webapp.ml_utils_before1 import extract_text_from_file, predict_category, suggest_tags
from django.views import View



from . import (upload as fileman_upload)

class UploadFormCreateView(CommonView):
    def get(self, request, form=None):
        if form is None:
            form = UploadFormHandle()

        skpd_list = m_master.Skpddg.objects.all()
        categories_tree = m_koleksi.Categories._recursive(pk_parent=0, deep=0)
        categories_flat = m_koleksi.Categories._recursive(pk_parent=0, deep=0, flat=True)
        categories_flat = {i['pk']: i['attributes'] for i in categories_flat}

        return render(request, 'fileman/form.html', {
            'form': form,
            'skpd_list': skpd_list,
            'categories_tree': categories_tree,
            'categories_flat': categories_flat,
        })

    def post(self, request):
        form = UploadFormHandle(request.POST, request.FILES)
        files = request.FILES.getlist('attachments')

        EXCLUDE_KEYS = ['csrfmiddlewaretoken', 'pending_delete_ids', 'tags']
        values = {k: v for k, v in request.POST.items() if k not in EXCLUDE_KEYS}

        is_ajax = request.is_ajax()
        json_data = dict(redirect=None, message=None)

        if form.is_valid():
            values['tahun'] = m_master.Ta._read_one(asis=1, tahun=values['tahun'])
            values['pk_categories'] = m_koleksi.Categories._read_one(asis=1, pk=values['pk_categories'])
            values['pk_skpd_dg'] = m_master.Skpddg._read_one(asis=1, pk=values['pk_skpd_dg'])
            values['user_input'] = request.session.get('pk')
            values['status_konten'] = form.cleaned_data['status_konten']

            contents = m_koleksi.Contents._create(**values)
            tags_raw = request.POST.get('tags', '')
            tags = [t.strip().lower() for t in tags_raw.split(',') if t.strip()]
            for tag_name in tags:
                tag, _ = Tag.objects.get_or_create(name=tag_name)
                ContentTag.objects.get_or_create(content=contents, tag=tag)
            pk = contents.pk

            # Simpan lampiran ke attachments
            fileman_upload.deploy(request, pk, files)
            values['attributes'] = fix_json_attributes(values.get('attributes', '{}'))
            tag_objs = ContentTag.objects.filter(content_id=pk).select_related('tag')
            tag_names = [t.tag.name for t in tag_objs if t.tag.name] or []

            # Simpan versi metadata & file sebagai versi awal
            version = ContentVersion.objects.create(
                pk_contents=pk,
                judul=values.get('judul'),
                deskripsi=values.get('deskripsi'),
                attributes=values['attributes'],
                tahun=values['tahun'].tahun,
                pk_categories=values['pk_categories'].pk,
                pk_skpd_dg=values['pk_skpd_dg'].pk,
                status_konten=values['status_konten'],
                user_input=values['user_input'],
                tags=tag_names,
            )

            attachments = m_koleksi.Attachments._read_many(asis=1, pk_contents=pk, is_deleted=False)
            for a in attachments:
                ContentVersionAttachment.objects.create(
                    pk_version=version,
                    name=a. name,
                    path=a. path,
                    content_type=a. _type,
                    size=a. size
                )

            log_activity(request, 'upload', 'contents', pk, f"Upload dokumen {values.get('judul', '')}")
            messages.info(request, 'berhasil menyimpan data.')

            if is_ajax:
                json_data['redirect'] = reverse('content_item', kwargs={'pk': pk})
                json_data['message'] = 'berhasil menyimpan data.'
                return JsonResponse(json_data, status=HTTPStatus.OK)

        if is_ajax:
            json_data['message'] = 'gagal menyimpan, data belum lengkap.'
            return JsonResponse(json_data, status=HTTPStatus.BAD_REQUEST)

        for k, v in values.items():
            if k in form.fields:
                form.fields[k].initial = v

        return self.get(request, form=form)

class UploadFormHandle(CommonModelForm):
	# tahun = CommonForm.base().ModelChoiceField(label='Tahun',queryset=m_master.Ta.objects.all(),to_field_name='tahun')
	# judul = CommonForm.base().CharField(label='Judul', max_length=128)
	# deskripsi = CommonForm.base().CharField(label='Deskripsi Singkat', max_length=512)
	def __init__(self,*args,**kwargs):
		super().__init__(*args, **kwargs)
		self.fields['pk_categories'].label = 'Kategori'
		self.fields['pk_skpd_dg'].label = '---Pilih SKPD---'
		self.fields['deskripsi'].label = 'Deskripsi Singkat'
	# # 
	# class Meta:
	# 	model = m_koleksi.Contents
	# 	fields = ['tahun','pk_categories','pk_skpd_dg','attributes','judul','deskripsi',]
	# # 
	
	#start agus 28/4/25
		self.fields['status_konten'].label = 'Jenis Berkas'
	
	class Meta:
		model = m_koleksi.Contents
		fields = ['tahun','pk_categories','pk_skpd_dg','attributes','judul','deskripsi','status_konten']
	#end

 

def get_val(obj, field):
    return obj.get(field) if isinstance(obj, dict) else getattr(obj, field, None)
class UploadFormUpdateView(CommonView):
    def get(self, request, pk, form=None):
        if form is None:
            form = UploadFormHandle()

        contents = m_koleksi.Contents._read_one(pk=pk)
        tags_qs = ContentTag.objects.filter(content_id=pk).select_related('tag')
        tags_str = ', '.join([t.tag.name for t in tags_qs])
        attachments = [
            a for a in m_koleksi.Attachments._read_many(asis=1, pk_contents=pk)
            if not get_val(a, 'is_deleted')
        ]

        for k, v in contents.items():
            if k in form.fields:
                form.fields[k].initial = v

        skpd_list = m_master.Skpddg.objects.all()
        categories_tree = m_koleksi.Categories._recursive(pk_parent=0, deep=0)
        categories_flat = {
            i['pk']: i['attributes']
            for i in m_koleksi.Categories._recursive(pk_parent=0, deep=0, flat=True)
        }

        if contents['user_input'] != request.session.get('pk') and request.session.get('role') not in ['ADMIN', 'KOORDINATOR']:
            return render(request, 'forbidden.html', {'urlnya': reverse('content_item', args=[pk])})

        return render(request, 'fileman/form.html', {
            'pk': pk,
            'form': form,
            'skpd_list': skpd_list,
            'attachments': attachments,
            'categories_tree': categories_tree,
            'categories_flat': categories_flat,
            'tags_initial': tags_str,
        })

    def post(self, request, pk):
        form = UploadFormHandle(request.POST, request.FILES)
        values = {k: v for k, v in request.POST.items() if k not in ['csrfmiddlewaretoken', 'pending_delete_ids', 'tags']}
        attachments = request.FILES.getlist('attachments')
        is_ajax = request.is_ajax()
        json_data = dict(redirect=None, message=None)

        if form.is_valid():
            # Parse dan siapkan tags baru lebih awal
            tags_raw = request.POST.get('tags', '')
            tags = [t.strip().lower() for t in tags_raw.split(',') if t.strip()]
            tag_names = tags.copy()

            old = m_koleksi.Contents._read_one(pk=pk)
            old_attr_fixed = fix_json_attributes(old.get('attributes', '{}'))

            version = ContentVersion.objects.create(
                pk_contents=pk,
                judul=old.get('judul'),
                deskripsi=old.get('deskripsi'),
                attributes=old_attr_fixed,
                tahun=old.get('tahun'),
                pk_categories=old.get('pk_categories'),
                pk_skpd_dg=old.get('pk_skpd_dg'),
                status_konten=old.get('status_konten'),
                user_input=request.session.get('pk'),
                tags=tag_names,
            )

            old_files = m_koleksi.Attachments._read_many(asis=1, pk_contents=pk)
            for a in old_files:
                if not getattr(a, 'is_deleted', False):
                    ContentVersionAttachment.objects.create(
                        pk_version=version,
                        name=get_val(a, 'name'),
                        path=get_val(a, 'path'),
                        content_type=get_val(a, '_type'),
                        size=get_val(a, 'size')
                    )

            pending_ids = request.POST.get('pending_delete_ids', '')
            for att_id in pending_ids.split(','):
                if att_id.strip().isdigit():
                    m_koleksi.Attachments._update({'is_deleted': True}, {'pk': int(att_id)})

            values['tahun'] = m_master.Ta._read_one(asis=1, tahun=values['tahun'])
            values['pk_categories'] = m_koleksi.Categories._read_one(asis=1, pk=values['pk_categories'])
            values['pk_skpd_dg'] = m_master.Skpddg._read_one(asis=1, pk=values['pk_skpd_dg'])
            values['status_konten'] = form.cleaned_data['status_konten']

            m_koleksi.Contents._update(values, {'pk': pk})

            ContentTag.objects.filter(content_id=pk).delete()
            for tag_name in tags:
                tag, _ = Tag.objects.get_or_create(name=tag_name)
                ContentTag.objects.get_or_create(content_id=pk, tag=tag)

            if attachments:
                fileman_upload.deploy(request, pk, attachments)

            log_activity(request, 'edit', 'contents', pk, f"Edit dokumen {values.get('judul', '')}")
            messages.info(request, 'Berhasil memperbarui data.')

            if is_ajax:
                json_data['redirect'] = reverse('content_item', args=[pk])
                json_data['message'] = 'Berhasil menyimpan data.'
                return JsonResponse(json_data, status=HTTPStatus.OK)

        if is_ajax:
            json_data['message'] = 'Gagal menyimpan data.'
            return JsonResponse(json_data, status=HTTPStatus.BAD_REQUEST)

        return self.get(request, pk, form=form)
def rollback_version(request, pk):
    version = get_object_or_404(ContentVersion, _pk=pk)
    pk_contents = version.pk_contents
    content_obj = m_koleksi.Contents.objects.get(pk=pk_contents)

    # Simpan versi metadata & file aktif saat ini ke histori
    current = m_koleksi.Contents._read_one(pk=pk_contents)
    raw_attr = current.get('attributes', '{}')
    attributes_fixed = fix_json_attributes(raw_attr)
    tag_qs = ContentTag.objects.filter(content_id=pk_contents).select_related('tag')
    tag_names = [t.tag.name for t in tag_qs if t.tag.name]
    backup_version = ContentVersion.objects.create(
        pk_contents=pk_contents,
        judul=current.get('judul'),
        deskripsi=current.get('deskripsi'),
        attributes=attributes_fixed,
        tahun=current.get('tahun'),
        pk_categories=current.get('pk_categories'),
        pk_skpd_dg=current.get('pk_skpd_dg'),
        status_konten=current.get('status_konten'),
        user_input=request.session.get('pk'),
        tags=tag_names
    )

    active_files = m_koleksi.Attachments._read_many(asis=1, pk_contents=pk_contents, is_deleted=False)
    for a in active_files:
        ContentVersionAttachment.objects.create(
            pk_version=backup_version,
            name=get_val(a, 'name'),
            path=get_val(a, 'path'),
            content_type=get_val(a, '_type'),
            size=get_val(a, 'size')
        )

    m_koleksi.Attachments._update({'is_deleted': True}, {'pk_contents': pk_contents})

    restored_files = ContentVersionAttachment.objects.filter(pk_version=version._pk)
    for f in restored_files:
        m_koleksi.Attachments._create(
            pk_contents=content_obj,
            name=f.name,
            path=f.path,
            _type=f.content_type,
            size=f.size,
            is_deleted=False
        )
    
    attr = version.attributes
    if isinstance(attr, dict):
        attr = json.dumps(attr)

    m_koleksi.Contents._update({
        'judul': version.judul,
        'deskripsi': version.deskripsi,
        'attributes': attr,
        'tahun': m_master.Ta.objects.get(tahun=version.tahun),
        'pk_categories': m_koleksi.Categories.objects.get(pk=version.pk_categories),
        'pk_skpd_dg': m_master.Skpddg.objects.get(pk=version.pk_skpd_dg),
        'status_konten': version.status_konten,
    }, {'pk': version.pk_contents})

    ContentTag.objects.filter(content_id=pk_contents).delete()
    tag_names = version.tags or []
    for tag_name in tag_names:
        tag, _ = Tag.objects.get_or_create(name=tag_name)
        ContentTag.objects.get_or_create(content_id=pk_contents, tag=tag)

    log_activity(request, 'rollback', 'contents', pk_contents, f"Rollback ke versi ID {version._pk}")
    messages.success(request, 'Rollback metadata & file berhasil.')
    return redirect('content_item', pk=pk_contents)

# --- Soft Remove Lampiran ---
def remove(request, pk):
    m_koleksi.Attachments._update({'is_deleted': True}, {'pk': pk})
    return HttpResponse(None)


# --- Delete Permanen ---
def delete(request, pk):
    try:
        contents = m_koleksi.Contents._read_one(pk=pk)

        if contents['user_input'] != request.session.get('pk') and request.session.get('role') not in ['ADMIN', 'KOORDINATOR']:
            return render(request, 'forbidden.html', {'urlnya': reverse('content_item', args=[pk])})

        attachment_list = m_koleksi.Attachments._read_many(asis=1, pk_contents=pk)
        for a in attachment_list:
            fileman_upload.destroy_one_permanent(pk=get_val(a, 'pk'))

        m_koleksi.Contents._delete(pk=pk)

        log_activity(
            request,
            action='delete',
            content_type='contents',
            object_pk=pk,
            description=f'Hapus dokumen {contents["judul"]}'
        )

        messages.warning(request, 'Berhasil menghapus data.')
        return redirect('content_list')

    except m_koleksi.Contents.DoesNotExist:
        messages.error(request, 'Data yang ingin dihapus tidak ditemukan.')
        return redirect('content_list')
    except Exception as e:
        print('Error:', e)
        messages.error(request, 'Terjadi kesalahan saat menghapus data.')
        return redirect('content_list')

def fix_json_attributes(attr_raw):
    if not attr_raw:
        return "{}"
    if isinstance(attr_raw, dict):
        return json.dumps(attr_raw)
    try:
        json.loads(attr_raw)
        return attr_raw
    except json.JSONDecodeError:
        attr_fixed = attr_raw.replace("'", '"')
        try:
            json.loads(attr_fixed)
            return attr_fixed
        except json.JSONDecodeError:
            return "{}"
        
@csrf_exempt
def predict_category_tags(request):
    file = request.FILES.get('file')
    if not file:
        return JsonResponse({'error': 'Tidak ada File atau  category yang cocok'}, status=400)

    try:
        text = extract_text_from_file(file)
        pred_category = predict_category(text)
        suggested_tags = suggest_tags(text)

        return JsonResponse({
            'pred_category': pred_category,
            'suggested_tags': suggested_tags
        })
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

