"""
AI Service — LegalEase Ai (Rotating Multiple Gemini Keys for 24/7 Free Access)
"""
import json
import re
import time
import os
from typing import Optional

from ..config import GEMINI_API_KEYS, GEMINI_MODEL, GROQ_API_KEY

# Fallback models for max free-tier quota
FALLBACK_MODELS = ["gemini-2.5-flash", "gemini-2.0-flash", "gemma-3-27b-it", "gemini-flash-latest"]

# Track which key we are currently using globally
_current_key_index = 0

VALID_CATEGORIES = [
    "Land Dispute", "Property Inheritance", "Family Divorce",
    "Contract Breach", "Tenant Eviction", "Loan Recovery",
    "Consumer Rights", "Business Partnership Dispute",
    "Defamation", "Civil Appeal",
]

def get_gemini_client(api_key: str, model_name: str = None):
    try:
        import google.generativeai as genai
        genai.configure(api_key=api_key)
        # Use provided model or default from config
        return genai.GenerativeModel(model_name or GEMINI_MODEL)
    except Exception as e:
        print(f"[AI] Model Init Error: {e}")
        return None

def call_with_retry(prompt: str, gen_config: dict) -> str:
    """Try every provided key with every fallback model to bypass free-tier limits."""
    global _current_key_index
    
    if not GEMINI_API_KEYS:
        raise ValueError("No Gemini keys found in .env")

    # Sequence: Try all keys on primary model first, then fall through to next models
    models_to_try = [GEMINI_MODEL] + [m for m in FALLBACK_MODELS if m != GEMINI_MODEL]
    
    # We will try every key-model combination until success
    for model_name in models_to_try:
        # Start from current index and try every key once
        for _ in range(len(GEMINI_API_KEYS)):
            api_key = GEMINI_API_KEYS[_current_key_index]
            try:
                model = get_gemini_client(api_key, model_name)
                if not model:
                    raise Exception("Failed to initialize model")
                
                resp = model.generate_content(prompt, generation_config=gen_config)
                return resp.text.strip()
            except Exception as e:
                err_msg = str(e).lower()
                # Quota or key issue (rate limit, invalid, revoked/leaked) — rotate to the next key
                if ("429" in err_msg or "quota" in err_msg or "api_key_invalid" in err_msg
                        or "403" in err_msg or "leaked" in err_msg):
                    print(f"[AI] Key index {_current_key_index} failed on {model_name}. Rotating...")
                    _current_key_index = (_current_key_index + 1) % len(GEMINI_API_KEYS)
                    continue
                # Model retired/unavailable — skip to the next fallback model
                if "404" in err_msg or "not found" in err_msg or "not supported" in err_msg:
                    print(f"[AI] Model {model_name} unavailable. Trying next model...")
                    break
                # Empty response (e.g. thinking model spent the whole token
                # budget, finish_reason=MAX_TOKENS) — try the next model
                if "valid `part`" in err_msg or "finish_reason" in err_msg:
                    print(f"[AI] {model_name} returned no text. Trying next model...")
                    break
                # Critical error (e.g. safety block) — raise immediately
                raise e
                
    raise Exception("All Gemini keys and models are currently rate-limited.")

def analyze_case(description: str) -> dict:
    prompt = f"""You are an expert Pakistani civil law assistant. Analyze the following case.

Respond with ONLY valid JSON (no markdown, no extra text) with these keys:
- "category": EXACTLY one of {json.dumps(VALID_CATEGORIES)}
- "summary": 2-3 sentence plain language summary
- "legal_guidance": practical guidance as bullet points separated by newlines
- "confidence": "High", "Medium", or "Low"

CASE: {description}

JSON:"""
    try:
        raw_text = call_with_retry(prompt, {"temperature": 0.2, "max_output_tokens": 2048})
        raw = re.sub(r"^```(?:json)?\s*", "", raw_text)
        raw = re.sub(r"\s*```$", "", raw)
        result = json.loads(raw)
        category = result.get("category", "Civil Appeal")
        if category not in VALID_CATEGORIES:
            category = "Civil Appeal"
        return {
            "category": category,
            "summary": result.get("summary", ""),
            "legal_guidance": result.get("legal_guidance", ""),
            "confidence": result.get("confidence", "Medium"),
        }
    except Exception as e:
        print(f"[AI] Gemini Error: {e}")
        return _fallback_analysis(description)

def _fallback_analysis(description: str) -> dict:
    return {
        "category": "Civil Appeal",
        "summary": "This case requires a detailed review. It appears to be a civil matter under Pakistani law.",
        "legal_guidance": "• Consult a lawyer in your city.\n• Gather all relevant documents.\n• File your response within 30 days.",
        "confidence": "Low",
    }

# ═══════════════════════════════════════════════════════════════
# Knowledge Base (Offline Fallback)
# ═══════════════════════════════════════════════════════════════

LEGAL_KB = [
    # ── Land Disputes ──
    {
        "keywords": ["land", "dispute", "plot", "zameen", "boundary", "encroachment"],
        "answer": (
            "**Land Disputes in Pakistan** are governed by the Specific Relief Act 1877 and various revenue laws.\n\n"
            "**Key steps:**\n"
            "• File a declaratory suit under Section 42 of the Specific Relief Act.\n"
            "• Obtain a 'Fard' (ownership record) from the local Patwari/Revenue Office.\n"
            "• Gather documents: sale deed, registry, mutation records, and Fard Malkiat.\n"
            "• Limitation period: **12 years** from the date of dispossession.\n"
            "• For boundary disputes, request a demarcation from the Revenue Department.\n\n"
            "⚖️ *Always consult a qualified property lawyer for specific legal advice.*"
        ),
    },
    {
        "keywords": ["documents", "land", "need", "required", "papers"],
        "answer": (
            "**Documents needed for a land dispute case:**\n\n"
            "1. **Sale Deed / Registry** — proof of ownership transfer\n"
            "2. **Fard Malkiat** — ownership record from Revenue Department\n"
            "3. **Mutation Record (Intiqal)** — shows transfer in revenue records\n"
            "4. **Property Tax Receipts** — proof of payment and possession\n"
            "5. **Site Plan / Map** — from the local development authority\n"
            "6. **CNIC copies** of all parties involved.\n\n"
            "⚖️ *Consult a property lawyer to verify your documentation.*"
        ),
    },
    # ── Divorce & Khula ──
    {
        "keywords": ["khula", "wife divorce", "apply khula"],
        "answer": (
            "**Khula in Pakistan** allows a wife to seek divorce through the Family Court.\n\n"
            "**Process:**\n"
            "1. File a suit for Khula in the Family Court.\n"
            "2. The court will attempt reconciliation for **90 days**.\n"
            "3. If reconciliation fails, the court grants Khula — usually the wife returns the *haq mehr*.\n"
            "4. **Timeline:** Typically 3-6 months.\n"
            "5. **Iddat period:** 3 menstrual cycles or 3 months after Khula.\n\n"
            "⚖️ *A family lawyer can guide you through your specific case.*"
        ),
    },
    {
        "keywords": ["divorce", "talaq", "separation", "husband divorce"],
        "answer": (
            "**Divorce (Talaq) in Pakistan** is governed by the Muslim Family Laws Ordinance 1961.\n\n"
            "**For Husband (Talaq):**\n"
            "• Send written notice to the Chairman of the Union Council and a copy to the wife.\n"
            "• Talaq becomes effective after **90 days** from the notice date.\n"
            "• The Union Council will attempt reconciliation during this period.\n\n"
            "⚖️ *Consult a family lawyer for your specific situation.*"
        ),
    },
    {
        "keywords": ["custody", "child", "children", "bachay", "guardian"],
        "answer": (
            "**Child Custody in Pakistan** follows the Guardians and Wards Act 1890.\n\n"
            "**General Rules:**\n"
            "• Mother has custody rights for boys until age **7** and girls until **puberty**.\n"
            "• After these ages, custody usually transfers to the father.\n"
            "• The court prioritizes the **best interest of the child**.\n"
            "• Both parents retain visitation rights.\n\n"
            "⚖️ *A family lawyer can help you file for custody or visitation rights.*"
        ),
    },
    # ── Inheritance ──
    {
        "keywords": ["inheritance", "wirasat", "property share", "heir", "will", "succession"],
        "answer": (
            "**Inheritance Law in Pakistan** follows Islamic Shariah principles for Muslims.\n\n"
            "**Key shares:**\n"
            "• **Sons** get double the share of daughters.\n"
            "• **Wife** gets 1/8th if children exist, 1/4th if no children.\n"
            "• **Husband** gets 1/4th if children exist, 1/2 if no children.\n\n"
            "**To claim:** Obtain a succession certificate from Civil Court, then get mutation done.\n"
            "• Limitation: **12 years** for immovable property.\n\n"
            "⚖️ *Consult a lawyer specializing in inheritance law.*"
        ),
    },
    # ── Contracts ──
    {
        "keywords": ["contract", "agreement", "breach", "default", "violation"],
        "answer": (
            "**Contract Law in Pakistan** is governed by the Contract Act 1872.\n\n"
            "**In case of breach:**\n"
            "• Sue for **damages** or **specific performance** (Specific Relief Act 1877).\n"
            "• Limitation: **3 years** for breach of contract.\n\n"
            "**Documents needed:** Original signed contract/agreement, and evidence of breach.\n\n"
            "⚖️ *A civil lawyer can assess the strength of your claim.*"
        ),
    },
    {
        "keywords": ["limitation", "limitation period", "time limit", "deadline"],
        "answer": (
            "**Limitation Periods in Pakistan (Limitation Act 1908):**\n\n"
            "• Breach of Contract — **3 years**\n"
            "• Recovery of Immovable Property — **12 years**\n"
            "• Recovery of Movable Property — **3 years**\n"
            "• Tort/Compensation Claims — **1 year**\n"
            "• Inheritance/Succession — **12 years**\n"
            "• Defamation — **1 year**\n"
            "• Rent Recovery — **3 years**\n\n"
            "⚠️ After the period expires, the right to sue is barred.\n\n"
            "⚖️ *Consult a lawyer if your limitation period may be expiring.*"
        ),
    },
    # ── Tenant / Eviction ──
    {
        "keywords": ["tenant", "rent", "eviction", "landlord", "kiraya"],
        "answer": (
            "**Tenant Eviction in Pakistan** is governed by provincial Rent Restriction Acts.\n\n"
            "**Grounds for eviction:**\n"
            "• Non-payment of rent for **2+ months**\n"
            "• Subletting without consent or illegal use\n"
            "• Landlord's personal need\n\n"
            "**Process:** Serve a legal notice, then file eviction petition. Timeline: 3-12 months.\n\n"
            "⚖️ *Both landlords and tenants should consult a property lawyer.*"
        ),
    },
    # ── Loan Recovery ──
    {
        "keywords": ["loan", "debt", "recovery", "payment", "cheque bounce"],
        "answer": (
            "**Loan/Debt Recovery in Pakistan:**\n\n"
            "**Civil Recovery:** File a suit in Civil Court (Order XXXVII CPC for summary procedure). Limitation is **3 years**.\n\n"
            "**Cheque Bounce:** File criminal complaint under Section 489-F PPC. Punishment: up to 3 years imprisonment.\n\n"
            "⚖️ *A civil lawyer can help expedite the recovery process.*"
        ),
    },
    # ── Consumer Rights ──
    {
        "keywords": ["consumer", "product", "defective", "refund", "warranty"],
        "answer": (
            "**Consumer Protection in Pakistan:**\n\n"
            "1. File with the **Consumer Court** in your district.\n"
            "2. No lawyer required — you can represent yourself.\n"
            "3. Resolution typically within **60-90 days**.\n\n"
            "⚖️ *Consumer Courts are designed to be accessible.*"
        ),
    },
    # ── Defamation ──
    {
        "keywords": ["defamation", "slander", "libel", "reputation"],
        "answer": (
            "**Defamation Law in Pakistan:**\n"
            "• Civil Defamation: Defamation Ordinance 2002 — limitation **1 year**.\n"
            "• Criminal Defamation: Section 499 PPC — up to 2 years imprisonment.\n"
            "• Must prove: false statement and damage to reputation.\n\n"
            "⚖️ *Consult a lawyer to assess whether your case qualifies.*"
        ),
    },
    # ── Civil Appeal ──
    {
        "keywords": ["appeal", "court order", "judgment", "decree", "challenge"],
        "answer": (
            "**Filing a Civil Appeal in Pakistan:**\n"
            "• Hierarchy: Civil Court → District Court → High Court → Supreme Court\n"
            "• Appeal within **30 days** of judgment. High Court appeals: **90 days**.\n"
            "• Can request a **stay order** to suspend execution during appeal.\n\n"
            "⚖️ *An experienced litigation lawyer is essential for appeals.*"
        ),
    },
    # ── Greetings ──
    {
        "keywords": ["hello", "hi", "hey", "salam", "assalam", "good morning", "good evening"],
        "answer": (
            "Hello! Welcome to **LegalEase Ai** 👋\n\n"
            "I'm your AI legal assistant for Pakistani law. I can help with:\n"
            "• 🏠 Land & Property Disputes\n"
            "• 👨‍👩‍👧 Family Law (Divorce, Khula, Custody)\n"
            "• 📜 Inheritance & Succession\n"
            "• 📝 Contracts & Agreements\n"
            "• 💰 Loan Recovery & Cheque Bounce\n"
            "• 🛡️ Consumer Rights & Defamation\n\n"
            "How can I assist you today?"
        ),
    },
    {
        "keywords": ["thank", "thanks", "shukriya", "jazak"],
        "answer": "You're welcome! 😊 If you have more legal questions, feel free to ask anytime. Use our **Browse Lawyers** page to find local experts."
    },
    {
        "keywords": ["help", "what can you do", "features"],
        "answer": "I can analyze your case, provide legal guidance on Pakistani civil law, and help you find lawyers. Just type your legal problem!"
    }
]

def _match_knowledge(user_message: str) -> Optional[str]:
    text = user_message.lower()
    for entry in LEGAL_KB:
        # Whole-word matching so e.g. "land" doesn't match inside "landlord"
        if any(re.search(rf"\b{re.escape(kw)}\b", text) for kw in entry["keywords"]):
            return entry["answer"]
    return None

def _groq_chat(prompt: str) -> str:
    if not GROQ_API_KEY:
        raise ValueError("GROQ_API_KEY missing")
    from groq import Groq
    client = Groq(api_key=GROQ_API_KEY)
    response = client.chat.completions.create(
        model="llama-3.3-70b-versatile",
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content.strip()


def _detect_input_language(text: str) -> str:
    """
    Lightweight language detection for routing fallback messages.
    Returns 'ur' if Urdu script characters are present, otherwise 'en'.
    Note: this is only used for offline fallback text — Gemini/Groq
    handle the real auto-detection (including Roman Urdu) via the prompt.
    """
    if re.search(r'[\u0600-\u06FF\u0750-\u077F]', text):
        return "ur"
    return "en"


def get_chatbot_response(user_message: str, case_context: Optional[str] = None, language: Optional[str] = None) -> str:
    """
    Auto-detects the language of the user's message (English, Urdu script,
    or Roman Urdu) and replies naturally in that same language/style —
    no manual language selection needed.
    """
    context = f"\nContext: {case_context}" if case_context else ""

    lang_instruction = (
        "You are a legal assistant for Pakistani civil law. "
        "Detect the language and style the user wrote their question in — "
        "whether English, Urdu script (اردو), or Roman Urdu (Urdu written in English letters) — "
        "and reply naturally in that SAME language and script. "
        "Do not mix languages unless the user did. "
        "Keep legal terminology accurate. Answer in 3-5 sentences."
    )

    prompt = f"{lang_instruction}\n{context}\n\nQ: {user_message}\nA:"

    # 1. Try Gemini (Rotating all keys/models)
    try:
        return call_with_retry(prompt, {"temperature": 0.4, "max_output_tokens": 1536})
    except Exception as e:
        print(f"[AI] Gemini failed: {e}")

    # 2. Try Groq
    try:
        return _groq_chat(prompt)
    except Exception as e:
        print(f"[AI] Groq failed: {e}")

    # 3. Last Resort: KB (English only) — detect language for the apology message
    fallback = _match_knowledge(user_message)
    if fallback:
        return fallback
    detected = _detect_input_language(user_message)
    if detected == "ur":
        return "معذرت، اے آئی سے رابطہ نہیں ہو سکا۔ براہ کرم کسی مستند وکیل سے رجوع کریں۔"
    return "I'm having trouble connecting to the AI. Please consult a qualified lawyer."

