import os
import json
import re
import time
from celery import shared_task
from django.conf import settings
from openai import OpenAI  # <-- Tambah baris ini
from .models import Bengkel, BengkelContribution, BengkelLaporan

def _extract_text_from_file(file_path):
    """Extract plain text from PDF, DOCX, or plain-text files."""
    ext = os.path.splitext(file_path)[1].lower()
    try:
        if ext == ".pdf":
            import pdfplumber
            with pdfplumber.open(file_path) as pdf:
                return "\n".join(p.extract_text() or "" for p in pdf.pages)
        elif ext in (".docx", ".doc"):
            import docx as _docx
            doc = _docx.Document(file_path)
            return "\n".join(p.text for p in doc.paragraphs)
        else:
            with open(file_path, encoding="utf-8", errors="ignore") as fh:
                return fh.read()
    except Exception:
        return ""

def analisis_fail_dengan_ai(teks_fail, tajuk_bengkel):
    """
    Fungsi AI: Meminta Google Gemini menilai dokumen untuk Dashboard Penganjur.
    """
    prompt = f"""
    Analyze the following text from a participant's submission for the workshop: "{tajuk_bengkel}".
    
    Provide the analysis in EXACT JSON format with these keys:
    - relevance_score: (float between 0.0 to 10.0). Give 0 if the text is random garbage, a receipt/invoice, or completely irrelevant to the workshop title.
    - novelty_score: (float between 1.0 to 10.0)
    - actionability_index: (integer between 0 to 100)
    - sentiment: (string: "Positif", "Negatif", or "Neutral")
    - main_theme: (string: single category name e.g. "Teknologi", "Dasar", "Klinikal", "Kewangan", "Pengurusan")
    - cognitive_complexity: (string: "Pemikiran Sistem", "Pemikiran Linear", or "Berwawasan")

    Text to analyze:
    {teks_fail[:3000]} 

    Return ONLY the raw JSON object without markdown tags.
    """

    import json
    
    # Gunakan OpenAI GPT untuk analisis
    try:
        if settings.OPENAI_API_KEY:
            client = OpenAI(api_key=settings.OPENAI_API_KEY)
            resp = client.chat.completions.create(
                model=getattr(settings, 'LLM_MODEL', 'gpt-4o-mini'),
                messages=[{"role": "user", "content": prompt}],
                response_format={"type": "json_object"}
            )
            raw = resp.choices[0].message.content.strip()
            # Pembersihan tag markdown jika ada
            raw = re.sub(r"^```json\s*", "", raw, flags=re.MULTILINE)
            raw = re.sub(r"^```\s*$", "", raw, flags=re.MULTILINE)
            
            print(f"✅ [Tasks] Analisis disempurnakan oleh OpenAI GPT")
            return json.loads(raw)
    except Exception as e:
        print(f"❌ [Tasks] Ralat Analisis OpenAI GPT: {e}")
        
    return None


@shared_task
def process_bengkel_task(bengkel_pk):
    """
    Background task (Celery): Kumpul sumbangan, proses vektor, analitik Dashboard, dan jana PDF.
    """
    import django
    django.setup()
    
    bengkel = Bengkel.objects.get(pk=bengkel_pk)

    # Padam laporan pending lama, ganti dengan status processing
    BengkelLaporan.objects.filter(bengkel=bengkel, status__in=["pending", "failed"]).delete()
    placeholder = BengkelLaporan.objects.create(
        bengkel=bengkel,
        tajuk="Sedang memproses semua sumbangan AI...",
        status="processing",
    )

    try:
        # 1. Kumpul semua sumbangan peserta
        corpus = []
        for contrib in BengkelContribution.objects.filter(bengkel=bengkel).select_related("jemputan"):
            name = contrib.jemputan.nama or "Peserta"
            parts = [f"### Nama: {name}"]
            if contrib.comment:
                parts.append(f"**Ulasan/Pendapat:**\n{contrib.comment}")
            from .chroma_service import simpan_dokumen_ke_vektor
            
            for cf in contrib.files.all():
                # --- PERUBAHAN HIBRID CELERY ---
                # Kita tidak lagi menggunakan abs_path dan _extract_text_from_file.
                # Sebaliknya, kita ambil teks terus dari pangkalan data!
                text = cf.teks_diekstrak or ""
                
                if text.strip():
                    # --- A. Simpan ke Pangkalan Data Vektor (ChromaDB) ---
                    try:
                        simpan_dokumen_ke_vektor(
                            bengkel_id=bengkel.pk,
                            dokumen_id=cf.pk,
                            nama_dokumen=cf.original_name,
                            teks_penuh=text
                        )
                    except Exception as e:
                        print(f"Ralat menyimpan vektor untuk fail {cf.original_name}: {e}")
                    
                    # --- B. Analitik Llama 3.1 untuk Dashboard ---
                    try:
                        hasil_analisis = analisis_fail_dengan_ai(text, bengkel.title)
                        if hasil_analisis:
                            cf.skor_relevansi = hasil_analisis.get('relevance_score', 0) # --- SIMPAN MARKAH ANTI-SAMPAH ---
                            cf.skor_novelty = hasil_analisis.get('novelty_score', 0)
                            cf.indeks_kebolehtindakan = hasil_analisis.get('actionability_index', 0)
                            cf.nada_dokumen = hasil_analisis.get('sentiment', 'Neutral')
                            cf.tema_utama = hasil_analisis.get('main_theme', 'Lain-lain')
                            cf.kompleksiti_kognitif = hasil_analisis.get('cognitive_complexity', 'Pemikiran Linear')
                            cf.analitik_data = hasil_analisis
                            cf.save() # Simpan data analitik ke database
                            print(f"✅ Analitik Dashboard berjaya disimpan untuk: {cf.original_name}")
                    except Exception as e:
                        print(f"Ralat menjana analitik untuk fail {cf.original_name}: {e}")

                file_part = f"**Fail: {cf.original_name}**"
                if cf.summary:
                    file_part += f"\nRingkasan peserta: {cf.summary}"
                if text.strip():
                    file_part += f"\nKandungan fail:\n{text[:5000]}"
                parts.append(file_part)
            corpus.append("\n".join(parts))

        # =====================================================================
        # 2. Panggil OpenAI GPT (Batches) untuk Ringkasan PDF
        # =====================================================================
        client = OpenAI(api_key=settings.OPENAI_API_KEY)
        BATCH_SIZE = 50
        batch_summaries = []

        def _call_ai(prompt_text, retries=3):
            for attempt in range(retries):
                try:
                    resp = client.chat.completions.create(
                        model=getattr(settings, 'LLM_MODEL', 'gpt-4o-mini'),
                        messages=[{"role": "user", "content": prompt_text}],
                        response_format={"type": "json_object"}
                    )
                    return resp.choices[0].message.content.strip()
                except Exception:
                    if attempt < retries - 1:
                        time.sleep(5)
                    else:
                        raise

        def _strip_fences(text):
            text = re.sub(r"^```json\s*", "", text, flags=re.MULTILINE)
            text = re.sub(r"^```\s*$", "", text, flags=re.MULTILINE)
            return text.strip()

        for i in range(0, len(corpus), BATCH_SIZE):
            batch = corpus[i:i + BATCH_SIZE]
            batch_text = "\n\n---\n\n".join(batch)
            batch_num = i // BATCH_SIZE + 1
            total_batches = (len(corpus) + BATCH_SIZE - 1) // BATCH_SIZE

            placeholder.tajuk = f"Memproses kumpulan {batch_num}/{total_batches}…"
            placeholder.save()

            batch_prompt = f"""
Anda ialah penganalisis bengkel digital kesihatan Malaysia: "{bengkel.title}".
Ini adalah sumbangan daripada kumpulan {batch_num} (peserta {i+1}–{i+len(batch)}).

TUGASAN: Analisis sumbangan dan hasilkan ringkasan structured.
Kembalikan HANYA JSON sah (tanpa markdown, tanpa ```):
{{
  "domains": [
    {{
      "tajuk": "nama domain",
      "isu_utama": ["isu 1"],
      "cadangan": ["cadangan 1"],
      "sumber": ["Nama: petikan"],
      "isu_berulang": ["isu disebut >1 kali"]
    }}
  ]
}}
=== SUMBANGAN ===
{batch_text}
"""
            raw = _call_ai(batch_prompt)
            raw = _strip_fences(raw)
            try:
                batch_summaries.append(json.loads(raw))
            except json.JSONDecodeError:
                batch_summaries.append({"raw": raw, "domains": []})
            if i + BATCH_SIZE < len(corpus):
                time.sleep(4)

        placeholder.tajuk = "Menyatukan semua analisis kumpulan…"
        placeholder.save()
        summaries_text = json.dumps(batch_summaries, ensure_ascii=False, indent=2)

        final_prompt = f"""
Anda ialah penganalisis bengkel digital kesihatan Malaysia: "{bengkel.title}".
TUGASAN: Gabungkan domains, susun isu utama, senaraikan cadangan.
Kembalikan HANYA JSON sah (tanpa markdown, tanpa ```):
{{
  "ringkasan_eksekutif": "...",
  "domains": [
    {{
      "tajuk": "...",
      "isu_utama": ["..."],
      "cadangan": ["..."],
      "sumber": ["..."],
      "isu_duplikat": [ {{"isu": "...", "disebut_oleh": ["nama1"]}} ]
    }}
  ]
}}
=== RINGKASAN KUMPULAN ===
{summaries_text[:80000]}
"""
        raw_final = _strip_fences(_call_ai(final_prompt))
        data = json.loads(raw_final)

        # 3. Jana PDF (Ringkasan)
        from fpdf import FPDF
        import datetime, tempfile, shutil
        from django.core.files import File

        placeholder.delete()

        def _make_pdf(tajuk_laporan, ringkasan, domains_subset):
            pdf = FPDF()
            pdf.set_auto_page_break(auto=True, margin=15)
            pdf.add_page()
            pdf.set_font("Helvetica", "B", 16)
            pdf.cell(0, 12, tajuk_laporan[:80].encode("latin-1", "ignore").decode("latin-1"), ln=True, align="C")
            
            with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
                tmp_path = tmp.name
            pdf.output(tmp_path)

            laporan = BengkelLaporan.objects.create(bengkel=bengkel, tajuk=tajuk_laporan, status="done")
            with open(tmp_path, "rb") as f:
                laporan.pdf_file.save(f"laporan_{laporan.pk}.pdf", File(f), save=True)
            os.unlink(tmp_path)

        for domain in data.get("domains", []):
            _make_pdf(domain["tajuk"], None, [domain])
        _make_pdf(f"Ringkasan Eksekutif — {bengkel.title}", data.get("ringkasan_eksekutif", ""), data.get("domains", []))

    except Exception as exc:
        placeholder.tajuk = "Gagal memproses sumbangan"
        placeholder.status = "failed"
        placeholder.ralat  = str(exc)
        placeholder.save()