import os
import json
import requests
import logging
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.shortcuts import get_object_or_404
from pxy_openai.assistants import OpenAIAssistant
from .models import WhatsAppBot
from .models import WhatsAppBot, Conversation, Message
from django.utils import timezone


logger = logging.getLogger(__name__)

# Utility Functions
def send_whatsapp_message(phone_number_id, sender_number, bot_response, graph_api_token):
    """
    Sends a message back to the user via WhatsApp.
    """
    try:
        response = requests.post(
            f"https://graph.facebook.com/v18.0/{phone_number_id}/messages",
            headers={"Authorization": f"Bearer {graph_api_token}"},
            json={
                "messaging_product": "whatsapp",
                "to": sender_number,
                "text": {"body": bot_response},
            },
        )
        response.raise_for_status()
    except Exception as e:
        logger.error(f"Error sending message via WhatsApp: {e}")


def verify_webhook_token(mode, token, challenge, verify_token):
    """
    Verifies the webhook token and mode.
    """
    if mode == "subscribe" and token == verify_token:
        return HttpResponse(challenge, status=200)
    return HttpResponse("Forbidden", status=403)


def parse_webhook_payload(payload):
    """
    Parses the webhook payload and extracts relevant data.
    """
    entry = payload.get("entry", [{}])[0]
    changes = entry.get("changes", [{}])[0]
    value = changes.get("value", {})
    message = value.get("messages", [{}])[0]
    return value, message


# Webhook Endpoint
@csrf_exempt
def webhook(request):
    """
    Handles incoming webhook requests from WhatsApp.
    """
    if request.method == "GET":
        # Webhook verification
        mode = request.GET.get("hub.mode")
        token = request.GET.get("hub.verify_token")
        challenge = request.GET.get("hub.challenge")

        # Use the first active bot for verification
        bot = WhatsAppBot.objects.filter(is_active=True).first()
        if bot:
            return verify_webhook_token(mode, token, challenge, bot.webhook_verify_token)
        return HttpResponse("No active bots configured", status=500)

    elif request.method == "POST":
        try:
            # Parse the incoming payload
            payload = json.loads(request.body)
            value, message = parse_webhook_payload(payload)

            if message.get("type") == "text":
                user_message    = message["text"]["body"]
                phone_number_id = value.get("metadata", {}).get("phone_number_id")
                sender_number   = message["from"]

                logger.info(f"Received phone_number_id from webhook payload: {phone_number_id}")

                # 1) Fetch the active bot
                bot = get_object_or_404(
                    WhatsAppBot,
                    phone_number_id=phone_number_id,
                    is_active=True
                )

                # 2) Get or create Conversation
                conv, _ = Conversation.objects.get_or_create(
                    bot=bot,
                    user_number=sender_number,
                    defaults={'started_at': timezone.now()}
                )

                # 3) Save inbound message
                Message.objects.create(
                    conversation=conv,
                    direction="in",
                    content=user_message
                )

                # 4) Generate assistant response and measure time
                assistant = OpenAIAssistant(name=bot.assistant.name)
                start     = timezone.now()
                try:
                    bot_response = assistant.handle_message(user_message)
                except Exception as e:
                    bot_response = f"Assistant error: {e}"
                    logger.error(bot_response)
                end = timezone.now()

                # 5) Send the response back to the user
                send_whatsapp_message(
                    phone_number_id,
                    sender_number,
                    bot_response,
                    bot.graph_api_token
                )

                # 6) Save outbound message with response time
                resp_ms = int((end - start).total_seconds() * 1000)
                Message.objects.create(
                    conversation=conv,
                    direction="out",
                    content=bot_response,
                    response_time_ms=resp_ms
                )

        except Exception as e:
            logger.error(f"Error processing webhook: {e}")

        return JsonResponse({}, status=200)

    return HttpResponse("Method Not Allowed", status=405)



# Webhook Verification Endpoint
@require_http_methods(["GET"])
def webhook_verification(request):
    """
    Verifies the webhook token from WhatsApp.
    """
    mode = request.GET.get("hub.mode")
    token = request.GET.get("hub.verify_token")
    challenge = request.GET.get("hub.challenge")

    # Use the first active bot for verification
    bot = WhatsAppBot.objects.filter(is_active=True).first()
    if bot:
        return verify_webhook_token(mode, token, challenge, bot.webhook_verify_token)
    return HttpResponse("No active bots configured", status=500)


# Root Endpoint
def root(request):
    """
    A root endpoint for basic connectivity testing.
    """
    return HttpResponse("<pre>Nothing to see here.\nCheckout README.md to start.</pre>", content_type="text/html")

from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.db.models import Avg
from .models import Conversation, Message

@login_required
def whatsapp_stats(request):
    # Total de conversaciones registradas
    total_conversations = Conversation.objects.count()

    # Total de mensajes entrantes y salientes de todo el tiempo
    messages_in  = Message.objects.filter(direction="in").count()
    messages_out = Message.objects.filter(direction="out").count()

    # Tiempo de respuesta promedio (solo salientes con tiempo registrado)
    avg_rt_qs = Message.objects.filter(direction="out", response_time_ms__isnull=False)
    avg_rt = avg_rt_qs.aggregate(Avg("response_time_ms"))["response_time_ms__avg"] or 0

    return JsonResponse({
        "total_conversations": total_conversations,
        "messages_in": messages_in,
        "messages_out": messages_out,
        "avg_response_time": int(avg_rt),
    })

