# feedback/utils.py
import base64
from PIL import Image
import io
import re
import logging
import json
from .models import ChatCategory, PredefinedQA, ChatLog
from django.http import JsonResponse
import openai
from django.db.models import Q

logger = logging.getLogger(__name__)

def decode_base64_image(base64_string):
    try:
        header, data = base64_string.split(';base64,')
        image_data = base64.b64decode(data)
        image = Image.open(io.BytesIO(image_data))
        return image
    except Exception:
        return None


# OpenAI API key
openai.api_key = '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'

# Logging configuration
logger = logging.getLogger(__name__)

STOP_WORDS = {"a", "an", "the", "is", "are", "in", "on", "and", "or", "at", "to", "for", "with", "of"}

# Clean words function to process user message and remove stop words
def clean_words(text):
    return {word for word in re.findall(r'\w+', text.lower()) if word not in STOP_WORDS}

# Function to generate AI response
def generate_ai_response(user_message, session_data, conversation=None):
    try:
        messages = []

        # Add previous exchanges to maintain context
        if conversation:
            for item in conversation[-6:]:
                role = "user" if item["sender"] == "user" else "assistant"
                messages.append({"role": role, "content": item["message"]})

        # Add the new user message
        user_name = session_data.get("name", "User")
        messages.append({
            "role": "user",
            "content": f"My name is {user_name}. {user_message}"
        })

        response = openai.ChatCompletion.create(
            model="gpt-4o",  # Ensure this is the correct model name you want to use
            messages=messages,
            max_tokens=150,
        )

        return response['choices'][0]['message']['content'].strip()
    except Exception as e:
        logger.exception("OpenAI API error:")
        return "Sorry, I'm having trouble answering right now."

# Function to get or create session data
def get_or_create_session_data(session, session_key, user_name, user_contact):
    session_data = session.get(session_key, {})

    if user_name and "name" not in session_data:
        session_data["name"] = user_name
    if user_contact and "contact" not in session_data:
        session_data["contact"] = user_contact

    session[session_key] = session_data
    session.modified = True  # <-- important for persisting session data

    return session_data

# Function to handle category selection based on user message
def handle_category_selection(message, session_data):
    categories = ChatCategory.objects.all()
    category_names = [cat.name.lower() for cat in categories]

    if not categories:
        return {"answer": "No categories available at the moment. Please try again later."}, session_data

    if message.lower() in category_names:
        selected_category = ChatCategory.objects.get(name__iexact=message.strip())
        session_data["category"] = selected_category.name
        return None, session_data  # No error message, category set
    else:
        return {
            "answer": "Thanks! Now, please choose a category from the following:",
            "categories": [cat.name for cat in categories]
        }, session_data  # Return categories list if no match found

# Function to identify email or phone number from user contact
def identify_contact(contact):
    user_email = ""
    user_phone = ""
    if re.match(r'^[^\s@]+@[^\s@]+\.[^\s@]+$', contact):
        user_email = contact
    else:
        user_phone = contact
    return user_email, user_phone

# Function to find the best matching predefined Q&A for the selected category
def find_best_match_qa(message, category):
       # Build the query to match the provided category or category is null
    if category is not None:
        matched_qas = PredefinedQA.objects.filter(
            Q(category=category) | Q(category__isnull=True)
        )
    else:
        # If no category is provided, select all questions (including uncategorized ones)
        matched_qas = PredefinedQA.objects.filter(category__isnull=True) | PredefinedQA.objects.all()

    user_words = clean_words(message)

    best_matches = []
    max_overlap = 0

    for qa in matched_qas:
        question_words = clean_words(qa.question)
        overlap = len(user_words & question_words)
        if overlap > max_overlap:
            best_matches = [qa]
            max_overlap = overlap
        elif overlap == max_overlap and overlap > 0:
            best_matches.append(qa)

    return best_matches


# Function to save conversation in the ChatLog model
def save_conversation(session_id, session_data, message, answer):
    try:
        chat_log = ChatLog.objects.get(session_id=session_id)
        conversation = json.loads(chat_log.conversation)
    except ChatLog.DoesNotExist:
        chat_log = ChatLog(
            user_name=session_data["name"],
            user_email=session_data.get("email", ""),
            user_phone=session_data.get("contact", ""),
            session_id=session_id,
            conversation="[]",
        )
        conversation = []

    conversation.append({"sender": "user", "message": message})
    conversation.append({"sender": "bot", "message": answer})

    chat_log.conversation = json.dumps(conversation)
    chat_log.save()