import logging
import os
import shutil
from datetime import datetime
import time
import re
from typing import List, Dict, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Header, UploadFile, File
from google.cloud import firestore
from pydantic import BaseModel, Field, validator
from fastapi.responses import StreamingResponse
from firebase_admin import auth as firebase_admin_auth
from database.firebase_client import get_firestore
from core.security import get_current_user, require_admin, require_subscriber
from services.vector_service import (
    index_faq,
    remove_faq,
    reindex_domain,
    get_collection,
    get_provider_for_domain,
)
from services.ai_service import stream_chatbot_response, generate_embedding

logger = logging.getLogger("chatbot.routers.api")
router = APIRouter(prefix="/api", tags=["API-driven CRM & Dashboard"])

# ── Pydantic Request schemas ──────────────────────────────────────────────────


class DomainCreate(BaseModel):
    name: str
    domain_url: str
    # normalized_domain: str
    welcome_message: Optional[str] = "Welcome to Acme Support."
    fallback_message: Optional[str] = (
        "Sorry, we could not find an answer. Please contact support."
    )
    helpline_number: Optional[str] = ""
    widget_title: Optional[str] = "Support Assistant"
    widget_color: Optional[str] = "#7C3AED"
    bot_avatar: Optional[str] = ""
    is_active: Optional[bool] = True


class DomainUpdate(BaseModel):
    name: Optional[str] = None
    domain_url: Optional[str] = None
    # normalized_domain: Optional[str] = None
    welcome_message: Optional[str] = None
    fallback_message: Optional[str] = None
    helpline_number: Optional[str] = None
    widget_title: Optional[str] = None
    widget_color: Optional[str] = None
    bot_avatar: Optional[str] = None
    is_active: Optional[bool] = None


class FAQGroupCreate(BaseModel):
    name: str
    description: Optional[str] = ""


class FAQCreate(BaseModel):
    domain_id: str
    # group_id: str
    group_id: Optional[str] = None
    question: str
    answer: str
    aliases: List[str] = []
    keywords: List[str] = []


class FAQUpdate(BaseModel):
    question: Optional[str] = None
    answer: Optional[str] = None
    aliases: Optional[List[str]] = None
    keywords: Optional[List[str]] = None
    group_id: Optional[str] = None


class PaginationParams(BaseModel):
    page: int = Field(1, ge=1)
    page_size: int = Field(10, ge=1, le=100)
    search: Optional[str] = None
    domain_id: Optional[str] = None


class SubscriberCreate(BaseModel):
    email: str
    password: str
    display_name: str
    dashboard_logo_url: Optional[str] = None
    ai_call_limit: Optional[int] = 100


class SubscriberUpdate(BaseModel):
    display_name: Optional[str] = None
    dashboard_logo_url: Optional[str] = None
    ai_call_limit: Optional[int] = None


class PromoteRequest(BaseModel):
    action: str  # "new_faq" or "add_alias"
    faq_id: Optional[str] = None  # for add_alias
    group_id: Optional[str] = None  # for new_faq
    answer: Optional[str] = None  # for new_faq
    question: Optional[str] = None
    aliases: Optional[List[str]] = []
    keywords: Optional[List[str]] = []
    domain_id: Optional[str] = None


class AISuggestRequest(BaseModel):
    query: str
    domain_id: str


class VectorSearchRequest(BaseModel):
    query: str
    domain_id: str
    limit: int = 5


class WidgetStyleUpdate(BaseModel):
    theme_color: str
    title: str
    placeholder: str
    position: str = "right"  # left or right
    welcome_message: str = "Hello! How can I help you today?"
    logo_url: Optional[str] = ""
    border_radius: str = "12px"
    font_color: str = "#ffffff"


# ── Auth Endpoints ────────────────────────────────────────────────────────────

# ── Helpher Functions ────────────────────────────────────────────────────────────

DOMAIN_REGEX = re.compile(r"^(?!:\/\/)([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$")


def validate_domain(domain: str) -> str:

    domain = domain.strip().lower()

    if (
        "http://" in domain
        or "https://" in domain
        or "/" in domain
        or "?" in domain
        or "&" in domain
        or " " in domain
    ):
        raise HTTPException(
            status_code=400, detail="Enter domain only. Example: example.com"
        )

    if not DOMAIN_REGEX.match(domain):
        raise HTTPException(status_code=400, detail="Invalid domain format")

    return domain


@router.get("/auth/profile")
async def get_profile(user: dict = Depends(get_current_user)):
    """Returns the profile and role details of the logged in user."""
    return user


# ── Subscriber: Domains ────────────────────────────────────────────────────────


@router.get("/domains")
async def list_domains(
    user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Lists domains. Admins see all, subscribers see only theirs."""
    try:
        if user["role"] == "admin":
            docs = db.collection("domains").stream()
        else:
            docs = db.collection("domains").where("user_id", "==", user["uid"]).stream()

        domains = []
        for doc in docs:
            domains.append({"id": doc.id, **doc.to_dict()})
        return domains
    except Exception as e:
        logger.error(f"Error listing domains: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch domains")


@router.post("/upload-logo")
async def upload_logo(
    file: UploadFile = File(...),
    user: dict = Depends(get_current_user),
):
    """Uploads a logo to the local static directory and returns its URL."""
    try:
        # Check file extension
        ext = os.path.splitext(file.filename)[1].lower()
        if ext not in [".png", ".jpg", ".jpeg", ".svg", ".gif", ".webp"]:
            raise HTTPException(status_code=400, detail="Invalid image file format")
            
        # Ensure uploads folder exists
        os.makedirs("static/uploads", exist_ok=True)
        
        # Generate safe filename
        filename = f"{int(time.time())}_{file.filename.replace(' ', '_')}"
        file_path = os.path.join("static/uploads", filename)
        
        # Save file
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
            
        return {"url": f"/static/uploads/{filename}"}
    except Exception as e:
        logger.error(f"Error uploading logo: {e}")
        raise HTTPException(status_code=500, detail="Failed to upload logo file")


@router.post("/domains")
async def create_domain(
    payload: DomainCreate,
    user: dict = Depends(require_subscriber),
    db=Depends(get_firestore),
):
    """Creates a new domain for a subscriber."""
    try:
        normalized_domain = validate_domain(payload.domain_url)

        existing_query = (
            db.collection("domains")
            .where("normalized_domain", "==", normalized_domain)
            .stream()
        )

        existing = list(existing_query)

        if existing:
            raise HTTPException(status_code=400, detail="Domain already exists")
        doc_ref = db.collection("domains").document()

        is_active_val = payload.is_active if payload.is_active is not None else True
        welcome_val = (
            payload.welcome_message.strip()
            if payload.welcome_message
            else "Welcome to Acme Support."
        )
        fallback_val = (
            payload.fallback_message.strip()
            if payload.fallback_message
            else "Sorry, we could not find an answer. Please contact support."
        )
        helpline_val = (
            payload.helpline_number.strip() if payload.helpline_number else ""
        )
        title_val = (
            payload.widget_title.strip()
            if payload.widget_title
            else "Support Assistant"
        )
        color_val = payload.widget_color.strip() if payload.widget_color else "#7C3AED"
        avatar_val = payload.bot_avatar.strip() if payload.bot_avatar else ""

        domain_data = {
            "user_id": user["uid"],
            "name": payload.name.strip(),
            "domain_url": payload.domain_url.strip(),
            "normalized_domain": normalized_domain,
            "embedding_provider": "openai",  # default internal setting
            "is_active": is_active_val,
            "welcome_message": welcome_val,
            "fallback_message": fallback_val,
            "helpline_number": helpline_val,
            # Legacy styling keys for compatibility with direct style router
            "widget_title": title_val,
            "widget_theme_color": color_val,
            "widget_welcome_message": welcome_val,
            "widget_logo_url": avatar_val,
            "widget_placeholder": "Type your question...",
            "widget_position": "right",
            "widget_border_radius": "12px",
            "widget_font_color": "#ffffff",
            "created_at": datetime.utcnow().isoformat(),
        }
        doc_ref.set(domain_data)

        # Firestore SERVER_TIMESTAMP won't be in the local domain_data dict returned to client, so fetch/mock it
        domain_data["id"] = doc_ref.id
        return domain_data
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error creating domain: {e}")
        raise HTTPException(status_code=500, detail="Failed to register domain")


@router.put("/domains/{domain_id}")
async def update_domain(
    domain_id: str,
    payload: DomainUpdate,
    user: dict = Depends(get_current_user),
    db=Depends(get_firestore),
):
    """Updates domain configuration settings."""
    try:
        domain_ref = db.collection("domains").document(domain_id)
        snap = domain_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Domain not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("user_id") != user["uid"]:
            raise HTTPException(status_code=403, detail="Forbidden")

        updates = {}
        if payload.name is not None:
            updates["name"] = payload.name.strip()
        if payload.domain_url is not None:
            normalized_domain = validate_domain(payload.domain_url)

            existing_query = (
                db.collection("domains")
                .where("normalized_domain", "==", normalized_domain)
                .stream()
            )

            for existing_doc in existing_query:

                # Ignore same document
                if existing_doc.id != domain_id:

                    raise HTTPException(status_code=400, detail="Domain already exists")

            updates["domain_url"] = payload.domain_url.strip()
            updates["normalized_domain"] = normalized_domain
            # updates["domain_url"] = payload.domain_url.strip()
        if payload.welcome_message is not None:
            updates["welcome_message"] = payload.welcome_message.strip()
            updates["widget_welcome_message"] = payload.welcome_message.strip()
        if payload.fallback_message is not None:
            updates["fallback_message"] = payload.fallback_message.strip()
        if payload.helpline_number is not None:
            updates["helpline_number"] = payload.helpline_number.strip()
        if payload.widget_title is not None:
            updates["widget_title"] = payload.widget_title.strip()
        if payload.widget_color is not None:
            updates["widget_theme_color"] = payload.widget_color.strip()
        if payload.bot_avatar is not None:
            updates["widget_logo_url"] = payload.bot_avatar.strip()
        if payload.is_active is not None:
            updates["is_active"] = payload.is_active

        if updates:
            domain_ref.update(updates)

        return {"success": True, "message": "Domain updated successfully"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error updating domain: {e}")
        raise HTTPException(status_code=500, detail="Failed to update domain")


@router.delete("/domains/{domain_id}")
async def delete_domain(
    domain_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Deletes a domain, confirming ownership or admin rights."""
    try:
        doc_ref = db.collection("domains").document(domain_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Domain not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("user_id") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this domain"
            )

        doc_ref.delete()
        # Clean up related faqs
        faq_docs = db.collection("faqs").where("domain_id", "==", domain_id).get()
        for doc in faq_docs:
            db.collection("faqs").document(doc.id).delete()
            remove_faq(domain_id, doc.id, db)

        return {
            "success": True,
            "message": "Domain and related FAQs deleted successfully",
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting domain: {e}")
        raise HTTPException(status_code=500, detail="Failed to delete domain")


@router.post("/domains/{domain_id}/retrain")
async def retrain_domain(
    domain_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Retrains the vector database for a specific domain."""
    try:
        # 1. Verify ownership or admin rights
        doc_ref = db.collection("domains").document(domain_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Domain not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("user_id") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this domain"
            )

        # 2. Trigger retrain
        reindex_domain(domain_id, db)

        return {"success": True, "message": "Domain vectors retrained successfully"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error retraining domain: {e}")
        raise HTTPException(status_code=500, detail="Failed to retrain domain vectors")

# ── Subscriber: FAQ Groups ────────────────────────────────────────────────────


@router.get("/faq-groups")
async def list_faq_groups(
    user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Lists FAQ groups. Admins see all, subscribers see only theirs."""
    try:
        if user["role"] == "admin":
            docs = db.collection("faq_groups").stream()
        else:
            docs = (
                db.collection("faq_groups")
                .where("subscriber_uid", "==", user["uid"])
                .stream()
            )

        groups = []
        for doc in docs:
            groups.append({"id": doc.id, **doc.to_dict()})
        return groups
    except Exception as e:
        logger.error(f"Error listing FAQ groups: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch FAQ groups")


@router.post("/faq-groups")
async def create_faq_group(
    payload: FAQGroupCreate,
    user: dict = Depends(require_subscriber),
    db=Depends(get_firestore),
):
    """Creates a new FAQ group for the subscriber."""
    try:
        doc_ref = db.collection("faq_groups").document()
        group_data = {
            "subscriber_uid": user["uid"],
            "name": payload.name.strip(),
            "description": payload.description.strip(),
            "created_at": datetime.utcnow().isoformat(),
        }
        doc_ref.set(group_data)
        return {"id": doc_ref.id, **group_data}
    except Exception as e:
        logger.error(f"Error creating FAQ group: {e}")
        raise HTTPException(status_code=500, detail="Failed to create FAQ group")


@router.delete("/faq-groups/{group_id}")
async def delete_faq_group(
    group_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Deletes an FAQ group."""
    try:
        doc_ref = db.collection("faq_groups").document(group_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="FAQ Group not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("subscriber_uid") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this group"
            )

        doc_ref.delete()
        return {"success": True, "message": "FAQ Group deleted successfully"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting FAQ group: {e}")
        raise HTTPException(status_code=500, detail="Failed to delete FAQ group")


# ── Subscriber: FAQs ──────────────────────────────────────────────────────────


@router.get("/faqs")
async def list_faqs(
    page: int = 1,
    page_size: Optional[int] = None,
    search: Optional[str] = None,
    domain_id: Optional[str] = None,
    user: dict = Depends(get_current_user), 
    db=Depends(get_firestore)
):
    """
    Lists FAQs. If page_size is specified, returns paginated results.
    Otherwise, returns all FAQs for the domain.
    """
    try:
        # Build base query
        if user["role"] == "admin":
            query = db.collection("faqs")
        else:
            query = db.collection("faqs").where("subscriber_uid", "==", user["uid"])
        
        # Filter by domain if specified
        if domain_id:
            query = query.where("domain_id", "==", domain_id)
        
        # Get total count
        count_query = query
        total_count = len(list(count_query.stream()))
        
        # Fetch all matching docs
        all_docs = list(query.stream())
        
        # Apply search filter if provided
        if search and search.strip():
            search_lower = search.lower().strip()
            filtered_docs = []
            for doc in all_docs:
                data = doc.to_dict()
                if (
                    search_lower in data.get("question", "").lower() or
                    search_lower in data.get("answer", "").lower() or
                    any(search_lower in alias.lower() for alias in data.get("aliases", [])) or
                    any(search_lower in keyword.lower() for keyword in data.get("keywords", []))
                ):
                    filtered_docs.append((doc.id, data))
        else:
            filtered_docs = [(doc.id, doc.to_dict()) for doc in all_docs]
            
        total_filtered = len(filtered_docs)
        
        # Sort by created_at DESC safely
        def get_created_at(item_tuple):
            val = item_tuple[1].get("created_at")
            if not val:
                return ""
            if hasattr(val, "isoformat"):
                return val.isoformat()
            return str(val)
            
        filtered_docs.sort(key=get_created_at, reverse=True)
        
        # Apply pagination if page_size is provided
        if page_size is not None:
            page = max(1, page)
            page_size = min(max(1, page_size), 1000)
            start_idx = (page - 1) * page_size
            end_idx = start_idx + page_size
            paginated_docs = filtered_docs[start_idx:end_idx]
            total_pages = max(1, (total_filtered + page_size - 1) // page_size)
            has_next = page < total_pages
            has_prev = page > 1
        else:
            paginated_docs = filtered_docs
            page = 1
            page_size = total_filtered
            total_pages = 1
            has_next = False
            has_prev = False
            
        faqs = [{"id": doc_id, **data} for doc_id, data in paginated_docs]
        
        return {
            "data": faqs,
            "pagination": {
                "page": page,
                "page_size": page_size,
                "total_items": total_filtered,
                "total_pages": total_pages,
                "has_next": has_next,
                "has_prev": has_prev
            },
            "meta": {
                "total_faqs": total_count,
                "search_applied": bool(search and search.strip()),
                "domain_filter": domain_id
            }
        }
        
    except Exception as e:
        logger.error(f"Error listing FAQs: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch FAQs")


# Also add a lightweight endpoint to get FAQ counts per domain
@router.get("/faqs/counts")
async def get_faq_counts(
    user: dict = Depends(get_current_user),
    db=Depends(get_firestore)
):
    """
    Returns FAQ counts grouped by domain.
    Useful for displaying counts in tabs without loading all FAQs.
    """
    try:
        # Get user's domains
        if user["role"] == "admin":
            domain_docs = db.collection("domains").stream()
        else:
            domain_docs = db.collection("domains").where("user_id", "==", user["uid"]).stream()
        
        domain_ids = [doc.id for doc in domain_docs]
        
        # Count FAQs per domain
        counts = {}
        for domain_id in domain_ids:
            if user["role"] == "admin":
                query = db.collection("faqs").where("domain_id", "==", domain_id)
            else:
                query = (
                    db.collection("faqs")
                    .where("subscriber_uid", "==", user["uid"])
                    .where("domain_id", "==", domain_id)
                )
            
            counts[domain_id] = len(list(query.stream()))
        
        return counts
        
    except Exception as e:
        logger.error(f"Error getting FAQ counts: {e}")
        raise HTTPException(status_code=500, detail="Failed to get FAQ counts")


@router.post("/faqs")
async def create_faq(
    payload: FAQCreate,
    user: dict = Depends(require_subscriber),
    db=Depends(get_firestore),
):
    """Creates a new FAQ and indexes it in the vector DB."""
    try:
        # Validate domain ownership
        domain_snap = db.collection("domains").document(payload.domain_id).get()
        if (
            not domain_snap.exists
            or domain_snap.to_dict().get("user_id") != user["uid"]
        ):
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this domain"
            )

        provider = get_provider_for_domain(payload.domain_id, db)
        text_to_embed = f"Question: {payload.question.strip()}\nAnswer: {payload.answer.strip()}"
        embedding = []
        try:
            embedding = await generate_embedding(text_to_embed, provider)
        except Exception as e:
            logger.error(f"Failed to generate embedding for new FAQ: {e}")

        doc_ref = db.collection("faqs").document()
        faq_data = {
            "subscriber_uid": user["uid"],
            "domain_id": payload.domain_id,
            "group_id": payload.group_id or "default",
            "question": payload.question.strip(),
            "answer": payload.answer.strip(),
            "aliases": [a.strip() for a in payload.aliases if a.strip()],
            "keywords": [k.strip() for k in payload.keywords if k.strip()],
            "embedding": embedding,
            "created_at": datetime.utcnow().isoformat(),
        }
        doc_ref.set(faq_data)

        # Index in ChromaDB
        index_faq(
            payload.domain_id, doc_ref.id, faq_data["question"], faq_data["answer"], db
        )

        return {"id": doc_ref.id, **faq_data}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error creating FAQ: {e}")
        raise HTTPException(status_code=500, detail="Failed to create FAQ")


@router.put("/faqs/{faq_id}")
async def update_faq(
    faq_id: str,
    payload: FAQUpdate,
    user: dict = Depends(get_current_user),
    db=Depends(get_firestore),
):
    """Updates an existing FAQ and vector indexes."""
    try:
        doc_ref = db.collection("faqs").document(faq_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="FAQ not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("subscriber_uid") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this FAQ"
            )

        updates = {}
        if payload.question is not None:
            updates["question"] = payload.question.strip()
        if payload.answer is not None:
            updates["answer"] = payload.answer.strip()
        if payload.aliases is not None:
            updates["aliases"] = [a.strip() for a in payload.aliases if a.strip()]
        if payload.keywords is not None:
            updates["keywords"] = [k.strip() for k in payload.keywords if k.strip()]
        if payload.group_id is not None:
            updates["group_id"] = payload.group_id or "default"

        if "question" in updates or "answer" in updates:
            # Re-generate embedding
            q = updates.get("question", data.get("question", ""))
            a = updates.get("answer", data.get("answer", ""))
            provider = get_provider_for_domain(data["domain_id"], db)
            text_to_embed = f"Question: {q}\nAnswer: {a}"
            try:
                updates["embedding"] = await generate_embedding(text_to_embed, provider)
            except Exception as e:
                logger.error(f"Failed to generate embedding on update: {e}")

        if updates:
            doc_ref.update(updates)

        # Re-index in ChromaDB
        updated_snap = doc_ref.get().to_dict()
        index_faq(
            updated_snap["domain_id"],
            faq_id,
            updated_snap["question"],
            updated_snap["answer"],
            db,
        )

        return {"id": faq_id, **updated_snap}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error updating FAQ: {e}")
        raise HTTPException(status_code=500, detail="Failed to update FAQ")


@router.delete("/faqs/{faq_id}")
async def delete_faq(
    faq_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Deletes an FAQ and removes it from the vector DB."""
    try:
        doc_ref = db.collection("faqs").document(faq_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="FAQ not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("subscriber_uid") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this FAQ"
            )

        doc_ref.delete()
        remove_faq(data["domain_id"], faq_id, db)
        return {"success": True, "message": "FAQ deleted successfully"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting FAQ: {e}")
        raise HTTPException(status_code=500, detail="Failed to delete FAQ")


# ── Failed Questions & Promotion ──────────────────────────────────────────────


@router.get("/failed-questions")
async def list_failed_questions(
    page: int = 1,
    page_size: Optional[int] = None,
    search: Optional[str] = None,
    user: dict = Depends(get_current_user),
    db=Depends(get_firestore)
):
    """Lists failed questions. Admins see all, subscribers see only those for their domains."""
    try:
        if user["role"] == "admin":
            query = db.collection("failed_questions")
        else:
            query = (
                db.collection("failed_questions")
                .where("subscriber_uid", "==", user["uid"])
            )

        all_docs = list(query.stream())

        # Apply search filter if provided
        if search and search.strip():
            search_lower = search.lower().strip()
            filtered_docs = []
            for doc in all_docs:
                data = doc.to_dict()
                q_text = data.get("customer_question") or data.get("query") or ""
                resp_text = data.get("ai_response") or data.get("failed_response") or ""
                if (
                    search_lower in q_text.lower() or
                    search_lower in resp_text.lower()
                ):
                    filtered_docs.append((doc.id, data))
        else:
            filtered_docs = [(doc.id, doc.to_dict()) for doc in all_docs]

        total_filtered = len(filtered_docs)

        # Sort by created_at DESC safely
        def get_created_at(item_tuple):
            val = item_tuple[1].get("created_at")
            if not val:
                return ""
            if hasattr(val, "isoformat"):
                return val.isoformat()
            return str(val)

        filtered_docs.sort(key=get_created_at, reverse=True)

        if page_size is not None or page > 1:
            page = max(1, page)
            page_size = min(max(1, page_size or 10), 100)
            start_idx = (page - 1) * page_size
            end_idx = start_idx + page_size
            paginated_docs = filtered_docs[start_idx:end_idx]
            total_pages = max(1, (total_filtered + page_size - 1) // page_size)
            has_next = page < total_pages
            has_prev = page > 1

            failed = [{"id": doc_id, **data} for doc_id, data in paginated_docs]
            return {
                "data": failed,
                "pagination": {
                    "page": page,
                    "page_size": page_size,
                    "total_items": total_filtered,
                    "total_pages": total_pages,
                    "has_next": has_next,
                    "has_prev": has_prev
                }
            }
        else:
            return [{"id": doc_id, **data} for doc_id, data in filtered_docs]
    except Exception as e:
        logger.error(f"Error listing failed questions: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch failed questions")


@router.delete("/failed-questions/{failed_id}")
async def delete_failed_question(
    failed_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Dismisses/deletes a failed question."""
    try:
        doc_ref = db.collection("failed_questions").document(failed_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Question not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("subscriber_uid") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this domain's logs"
            )

        doc_ref.delete()
        return {"success": True, "message": "Failed question dismissed"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting failed question: {e}")
        raise HTTPException(status_code=500, detail="Failed to delete question")


@router.post("/failed-questions/{failed_id}/promote")
async def promote_failed_question(
    failed_id: str,
    payload: PromoteRequest,
    user: dict = Depends(get_current_user),
    db=Depends(get_firestore),
):
    """Promotes a failed question by creating a new FAQ or adding it as an alias to an existing FAQ."""
    try:
        failed_ref = db.collection("failed_questions").document(failed_id)
        failed_snap = failed_ref.get()
        if not failed_snap.exists:
            raise HTTPException(status_code=404, detail="Failed question not found")

        failed_data = failed_snap.to_dict()
        if user["role"] != "admin" and failed_data.get("subscriber_uid") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this domain's logs"
            )

        domain_id = payload.domain_id or failed_data.get("domain_id")
        customer_question = (payload.question or failed_data.get("customer_question") or failed_data.get("query") or "").strip()

        if payload.action == "new_faq":
            if not payload.answer or not payload.group_id:
                raise HTTPException(
                    status_code=400,
                    detail="Answer and Group ID are required to create a new FAQ",
                )

            provider = get_provider_for_domain(domain_id, db)
            text_to_embed = f"Question: {customer_question}\nAnswer: {payload.answer.strip()}"
            embedding = []
            try:
                embedding = await generate_embedding(text_to_embed, provider)
            except Exception as e:
                logger.error(f"Failed to generate embedding for promoted FAQ: {e}")

            # Create new FAQ
            faq_ref = db.collection("faqs").document()
            faq_data = {
                "subscriber_uid": failed_data["subscriber_uid"],
                "domain_id": domain_id,
                "group_id": payload.group_id,
                "question": customer_question,
                "answer": payload.answer.strip(),
                "aliases": [a.strip() for a in payload.aliases if a.strip()] if payload.aliases else [],
                "keywords": [k.strip() for k in payload.keywords if k.strip()] if payload.keywords else [],
                "embedding": embedding,
                "created_at": datetime.utcnow().isoformat(),
            }
            faq_ref.set(faq_data)
            index_faq(domain_id, faq_ref.id, customer_question, faq_data["answer"], db)

        elif payload.action == "add_alias":
            if not payload.faq_id:
                raise HTTPException(
                    status_code=400, detail="FAQ ID is required to append an alias"
                )

            faq_ref = db.collection("faqs").document(payload.faq_id)
            faq_snap = faq_ref.get()
            if not faq_snap.exists:
                raise HTTPException(status_code=404, detail="Target FAQ not found")

            faq_data = faq_snap.to_dict()
            aliases = faq_data.get("aliases", [])
            if customer_question not in aliases:
                aliases.append(customer_question)
                faq_ref.update({"aliases": aliases})

            # Reindex
            index_faq(
                domain_id, payload.faq_id, faq_data["question"], faq_data["answer"], db
            )

        else:
            raise HTTPException(status_code=400, detail="Invalid promotion action")

        # Delete from failed questions queue
        failed_ref.delete()
        return {"success": True, "message": "Failed question successfully promoted"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Failed question promotion error: {e}")
        raise HTTPException(status_code=500, detail="Promotion failed")


# ── Spam Protection & Questions ──────────────────────────────────────────────


@router.get("/spam-questions")
async def list_spam_questions(
    user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Lists spam questions. Admins see all, subscribers see only those for their domains."""
    try:
        if user["role"] == "admin":
            docs = db.collection("spam_questions").stream()
        else:
            docs = (
                db.collection("spam_questions")
                .where("subscriber_uid", "==", user["uid"])
                .stream()
            )

        spam = []
        for doc in docs:
            spam.append({"id": doc.id, **doc.to_dict()})
        return spam
    except Exception as e:
        logger.error(f"Error listing spam questions: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch spam questions")


@router.delete("/spam-questions/{spam_id}")
async def delete_spam_question(
    spam_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Dismisses/deletes a spam question."""
    try:
        doc_ref = db.collection("spam_questions").document(spam_id)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Question not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("subscriber_uid") != user["uid"]:
            raise HTTPException(
                status_code=403, detail="Forbidden: You do not own this domain's logs"
            )

        doc_ref.delete()
        return {"success": True, "message": "Spam log deleted"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting spam question: {e}")
        raise HTTPException(status_code=500, detail="Failed to delete spam log")


# ── Customer Conversations ────────────────────────────────────────────────────


@router.get("/conversations")
async def list_conversations(
    user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Lists customer conversation logs."""
    try:
        if user["role"] == "admin":
            docs = (
                db.collection("conversations")
                .order_by("created_at", direction="DESCENDING")
                .limit(200)
                .stream()
            )
        else:
            # First fetch subscriber's domains
            domain_docs = (
                db.collection("domains").where("user_id", "==", user["uid"]).get()
            )
            domain_ids = [d.id for d in domain_docs]
            if not domain_ids:
                return []

            docs = (
                db.collection("conversations")
                .where("domain_id", "in", domain_ids)
                .stream()
            )

        conversations = []
        for doc in docs:
            conversations.append({"id": doc.id, **doc.to_dict()})
            
        # If subscriber, sort and limit in memory to avoid composite index requirements
        if user["role"] != "admin":
            def get_created_at(item):
                val = item.get("created_at")
                if not val:
                    return ""
                if hasattr(val, "isoformat"):
                    return val.isoformat()
                return str(val)
            conversations.sort(key=get_created_at, reverse=True)
            conversations = conversations[:200]
            
        return conversations
    except Exception as e:
        logger.error(f"Error listing conversations: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch conversations")


@router.get("/leads")
async def list_leads(
    user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Lists captured leads."""
    try:
        if user["role"] == "admin":
            docs = (
                db.collection("leads")
                .order_by("created_at", direction="DESCENDING")
                .limit(200)
                .stream()
            )
        else:
            domain_docs = (
                db.collection("domains").where("user_id", "==", user["uid"]).get()
            )
            domain_ids = [d.id for d in domain_docs]
            if not domain_ids:
                return []

            docs = (
                db.collection("leads")
                .where("domain_id", "in", domain_ids)
                .stream()
            )

        leads = []
        for doc in docs:
            leads.append({"id": doc.id, **doc.to_dict()})
            
        if user["role"] != "admin":
            def get_created_at(item):
                val = item.get("created_at")
                if not val:
                    return ""
                if hasattr(val, "isoformat"):
                    return val.isoformat()
                return str(val)
            leads.sort(key=get_created_at, reverse=True)
            leads = leads[:200]
            
        return leads
    except Exception as e:
        logger.error(f"Error listing leads: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch leads")


# ── Widget Styling & Customizable Settings ────────────────────────────────────


@router.get("/style/{domain_id}")
async def get_widget_style(
    domain_id: str, user: dict = Depends(get_current_user), db=Depends(get_firestore)
):
    """Gets style custom settings for a domain widget."""
    try:
        domain_ref = db.collection("domains").document(domain_id)
        snap = domain_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Domain not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("user_id") != user["uid"]:
            raise HTTPException(status_code=403, detail="Forbidden")

        return {
            "theme_color": data.get("widget_theme_color", "#7C3AED"),
            "title": data.get("widget_title", "Support Chat"),
            "placeholder": data.get("widget_placeholder", "Type your question..."),
            "position": data.get("widget_position", "right"),
            "welcome_message": data.get(
                "widget_welcome_message", "Hello! How can I help you today?"
            ),
            "logo_url": data.get("widget_logo_url", ""),
            "border_radius": data.get("widget_border_radius", "12px"),
            "font_color": data.get("widget_font_color", "#ffffff"),
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Widget style fetch failed: {e}")
        raise HTTPException(status_code=500, detail="Failed to fetch style settings")


@router.post("/style/{domain_id}")
async def update_widget_style(
    domain_id: str,
    payload: WidgetStyleUpdate,
    user: dict = Depends(get_current_user),
    db=Depends(get_firestore),
):
    """Updates style configuration for a specific domain widget."""
    try:
        domain_ref = db.collection("domains").document(domain_id)
        snap = domain_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Domain not found")

        data = snap.to_dict()
        if user["role"] != "admin" and data.get("user_id") != user["uid"]:
            raise HTTPException(status_code=403, detail="Forbidden")

        domain_ref.update(
            {
                "widget_theme_color": payload.theme_color,
                "widget_title": payload.title,
                "widget_placeholder": payload.placeholder,
                "widget_position": payload.position,
                "widget_welcome_message": payload.welcome_message,
                "widget_logo_url": payload.logo_url,
                "widget_border_radius": payload.border_radius,
                "widget_font_color": payload.font_color,
            }
        )
        return {"success": True, "message": "Widget custom style updated"}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Widget style update failed: {e}")
        raise HTTPException(status_code=500, detail="Failed to update style")


# ── Admin Only subscriber Management ──────────────────────────────────────────


@router.get("/admin/subscribers")
async def admin_list_subscribers(
    user: dict = Depends(require_admin), db=Depends(get_firestore)
):
    """Lists all subscribers."""
    try:
        docs = db.collection("users").where("role", "==", "subscriber").stream()
        subscribers = []
        for doc in docs:
            subscribers.append({"uid": doc.id, **doc.to_dict()})
        return subscribers
    except Exception as e:
        logger.error(f"Error listing subscribers: {e}")
        raise HTTPException(status_code=500, detail="Failed to list subscribers")


@router.post("/admin/subscribers")
async def admin_create_subscriber(
    payload: SubscriberCreate,
    user: dict = Depends(require_admin),
    db=Depends(get_firestore),
):
    """Creates a new subscriber in Firebase Auth and Firestore (Admin only)."""
    try:
        # Create user in Firebase Auth
        user_record = firebase_admin_auth.create_user(
            email=payload.email,
            password=payload.password,
            display_name=payload.display_name,
        )

        # Save profile in Firestore
        uid = user_record.uid
        user_data = {
            "email": payload.email,
            "role": "subscriber",
            "display_name": payload.display_name,
            "dashboard_logo_url": payload.dashboard_logo_url or "",
            "ai_call_limit": payload.ai_call_limit if payload.ai_call_limit is not None else 100,
            "ai_call_count": 0,
            "created_at": datetime.utcnow().isoformat(),
        }
        db.collection("users").document(uid).set(user_data)
        return {"uid": uid, **user_data}
    except firebase_admin_auth.EmailAlreadyExistsError:
        raise HTTPException(
            status_code=400,
            detail="A user with this email already exists in Firebase Auth",
        )
    except Exception as e:
        logger.error(f"Admin failed to create subscriber: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.put("/admin/subscribers/{uid}")
async def admin_update_subscriber(
    uid: str,
    payload: SubscriberUpdate,
    user: dict = Depends(require_admin),
    db=Depends(get_firestore),
):
    """Updates a subscriber profile (Admin only)."""
    try:
        doc_ref = db.collection("users").document(uid)
        snap = doc_ref.get()
        if not snap.exists:
            raise HTTPException(status_code=404, detail="Subscriber profile not found")

        updates = {}
        if payload.display_name is not None:
            updates["display_name"] = payload.display_name
        if payload.dashboard_logo_url is not None:
            updates["dashboard_logo_url"] = payload.dashboard_logo_url
        if payload.ai_call_limit is not None:
            updates["ai_call_limit"] = payload.ai_call_limit

        if updates:
            doc_ref.update(updates)

        return {"uid": uid, **doc_ref.get().to_dict()}
    except Exception as e:
        logger.error(f"Admin failed to update subscriber: {e}")
        raise HTTPException(status_code=500, detail="Failed to update subscriber")


@router.delete("/admin/subscribers/{uid}")
async def admin_delete_subscriber(
    uid: str, user: dict = Depends(require_admin), db=Depends(get_firestore)
):
    """Deletes subscriber from Firebase Auth and Firestore (Admin only)."""
    try:
        # Delete from Firestore
        db.collection("users").document(uid).delete()

        # Delete from Firebase Auth
        try:
            firebase_admin_auth.delete_user(uid)
        except firebase_admin_auth.UserNotFoundError:
            pass

        return {"success": True, "message": "Subscriber deleted successfully"}
    except Exception as e:
        logger.error(f"Admin failed to delete subscriber: {e}")
        raise HTTPException(status_code=500, detail="Failed to delete subscriber")


# ── AI Logs & Performance Lab Search ──────────────────────────────────────────


@router.get("/admin/ai-logs")
async def admin_list_ai_logs(
    user: dict = Depends(require_admin), db=Depends(get_firestore)
):
    """Lists logs of AI queries from conversations (Admin only)."""
    try:
        # Fetch conversations where message_type == 'ai' or 'failed'
        docs = (
            db.collection("conversations")
            .where("message_type", "in", ["ai", "failed"])
            .order_by("created_at", direction="DESCENDING")
            .limit(200)
            .stream()
        )
        logs = []
        for doc in docs:
            logs.append({"id": doc.id, **doc.to_dict()})
        return logs
    except Exception as e:
        logger.error(f"Error listing AI logs: {e}")
        # Return empty array if index hasn't completed or build error
        return []


@router.post("/admin/ai-suggest")
async def admin_ai_suggest(
    request: AISuggestRequest,
    user: dict = Depends(require_admin),
    db=Depends(get_firestore),
):
    try:
        domain_doc = db.collection("domains").document(request.domain_id).get()
        context = "No specific context available."
        if domain_doc.exists:
            context = f"You are a helpful support assistant for the domain: {domain_doc.to_dict().get('name')}. "
            context += domain_doc.to_dict().get("base_prompt", "")

        return StreamingResponse(
            stream_chatbot_response(request.query, context), media_type="text/plain"
        )
    except Exception as e:
        logger.error(f"AI Suggest Streaming error: {e}")
        raise HTTPException(status_code=500, detail="Streaming generation failed")


@router.post("/admin/vector-search")
async def admin_vector_search(
    request: VectorSearchRequest,
    user: dict = Depends(require_admin),
    db=Depends(get_firestore),
):
    """Returns raw vector search results for the AI Lab comparison tool."""
    try:
        provider = get_provider_for_domain(request.domain_id, db)
        start = time.perf_counter()
        collection = get_collection(request.domain_id, db)
        results = collection.query(query_texts=[request.query], n_results=request.limit)
        elapsed = round(time.perf_counter() - start, 4)

        matches = []
        if results and results.get("documents") and results["documents"][0]:
            for i, doc_text in enumerate(results["documents"][0]):
                distance = (
                    results["distances"][0][i]
                    if results.get("distances") and results["distances"][0]
                    else 1.0
                )
                similarity = round(max(0.0, min(1.0, 1.0 - distance)), 4)
                meta = (
                    results["metadatas"][0][i]
                    if results.get("metadatas") and results["metadatas"][0]
                    else {}
                )
                matches.append(
                    {
                        "faq_id": (
                            results["ids"][0][i]
                            if results.get("ids") and results["ids"][0]
                            else None
                        ),
                        "question": meta.get("question", ""),
                        "answer": meta.get("answer", ""),
                        "similarity": similarity,
                        "distance": round(distance, 4),
                    }
                )
        return {
            "matches": matches,
            "provider": provider,
            "vector_count": collection.count(),
            "retrieval_time": elapsed,
            "domain_id": request.domain_id,
        }
    except Exception as e:
        logger.error(f"Vector search error: {e}")
        raise HTTPException(status_code=500, detail=str(e))


# ── Health & Diagnostics Monitoring ───────────────────────────────────────────


@router.get("/admin/health")
async def admin_get_health(
    user: dict = Depends(require_admin), db=Depends(get_firestore)
):
    """Checks API health, Firebase access, and Vector search service (Admin only)."""
    health = {
        "status": "healthy",
        "timestamp": time.time(),
        "services": {
            "api_server": "online",
            "firebase_firestore": "unknown",
            "vector_search_db": "unknown",
        },
    }

    # Check Firestore
    try:
        # Simple read request
        db.collection("users").limit(1).get()
        health["services"]["firebase_firestore"] = "online"
    except Exception as e:
        logger.error(f"Healthcheck: Firestore connection failed: {e}")
        health["services"]["firebase_firestore"] = "offline"
        health["status"] = "degraded"

    # Check ChromaDB
    try:
        from services.vector_service import chroma_client

        chroma_client.heartbeat()
        health["services"]["vector_search_db"] = "online"
    except Exception as e:
        logger.error(f"Healthcheck: Vector Search connection failed: {e}")
        health["services"]["vector_search_db"] = "offline"
        health["status"] = "degraded"

    return health
