import uuid
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from apps.users.models import Session
from apps.conversations.models import Conversation, UserTurn, AgentResponse
from .livekit_tokens import create_user_token


@api_view(["POST"])
@permission_classes([AllowAny])
def start_session(request):
    """Create conversation and return LiveKit token + room_name + conversation_id."""
    room_name = request.data.get("room_name") or f"room-{uuid.uuid4().hex[:12]}"
    session_id = request.data.get("session_id")
    identity = request.data.get("identity") or f"user-{uuid.uuid4().hex[:8]}"

    session_obj = None
    if session_id:
        session_obj, _ = Session.objects.get_or_create(
            session_id=session_id,
            defaults={"session_id": session_id},
        )

    conv = Conversation.objects.create(
        session=session_obj,
        room_name=room_name,
        status=Conversation.Status.ACTIVE,
    )

    try:
        token = create_user_token(
            api_key=settings.LIVEKIT_API_KEY,
            api_secret=settings.LIVEKIT_API_SECRET,
            room_name=room_name,
            identity=identity,
        )
    except Exception as e:
        return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({
        "token": token,
        "room_name": room_name,
        "conversation_id": str(conv.id),
        "identity": identity,
    })


@api_view(["GET"])
@permission_classes([AllowAny])
def get_token(request):
    """GET /api/token/?room=...&identity=...&conversation_id=... (optional)."""
    room_name = request.query_params.get("room") or f"room-{uuid.uuid4().hex[:12]}"
    identity = request.query_params.get("identity") or f"user-{uuid.uuid4().hex[:8]}"
    conversation_id = request.query_params.get("conversation_id")

    conv = None
    if conversation_id:
        try:
            conv = Conversation.objects.get(id=conversation_id)
            room_name = conv.room_name
        except Conversation.DoesNotExist:
            pass

    if not conv:
        session_obj, _ = Session.objects.get_or_create(
            session_id=request.query_params.get("session_id") or uuid.uuid4().hex,
            defaults={},
        )
        conv = Conversation.objects.create(
            session=session_obj,
            room_name=room_name,
            status=Conversation.Status.ACTIVE,
        )

    try:
        token = create_user_token(
            api_key=settings.LIVEKIT_API_KEY,
            api_secret=settings.LIVEKIT_API_SECRET,
            room_name=room_name,
            identity=identity,
        )
    except Exception as e:
        return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({
        "token": token,
        "room_name": room_name,
        "conversation_id": str(conv.id),
        "identity": identity,
    })


@api_view(["POST", "GET"])
@permission_classes([AllowAny])
def turns_list_create(request, conversation_id):
    """POST: worker creates UserTurn. GET: list turns."""
    try:
        conv = Conversation.objects.get(id=conversation_id)
    except Conversation.DoesNotExist:
        return Response({"error": "Conversation not found"}, status=status.HTTP_404_NOT_FOUND)

    if request.method == "POST":
        order_index = conv.user_turns.count()
        turn = UserTurn.objects.create(
            conversation=conv,
            order_index=order_index,
            transcribed_text=request.data.get("transcript", ""),
            detected_language=request.data.get("detected_language"),
            stt_provider=request.data.get("stt_provider"),
            stt_confidence=request.data.get("stt_confidence"),
        )
        if request.data.get("detected_language"):
            conv.detected_language = request.data.get("detected_language")
            conv.save(update_fields=["detected_language", "updated_at"])
        return Response({"turn_id": str(turn.id), "order_index": order_index}, status=status.HTTP_201_CREATED)

    turns = conv.user_turns.prefetch_related("agent_response").order_by("order_index")
    data = []
    for t in turns:
        data.append({
            "turn_id": str(t.id),
            "order_index": t.order_index,
            "transcribed_text": t.transcribed_text,
            "detected_language": t.detected_language,
            "stt_provider": t.stt_provider,
            "created_at": t.created_at.isoformat(),
            "agent_response": {
                "response_text": t.agent_response.response_text,
                "language_used": t.agent_response.language_used,
                "created_at": t.agent_response.created_at.isoformat(),
            } if getattr(t, "agent_response", None) else None,
        })
    return Response(data)


@api_view(["POST"])
@permission_classes([AllowAny])
def turn_response(request, conversation_id, turn_id):
    """Worker posts agent response for a user turn."""
    try:
        conv = Conversation.objects.get(id=conversation_id)
        turn = conv.user_turns.get(id=turn_id)
    except (Conversation.DoesNotExist, UserTurn.DoesNotExist):
        return Response({"error": "Not found"}, status=status.HTTP_404_NOT_FOUND)

    AgentResponse.objects.update_or_create(
        user_turn=turn,
        defaults={
            "conversation": conv,
            "response_text": request.data.get("response_text", ""),
            "llm_provider": request.data.get("llm_provider"),
            "tts_provider": request.data.get("tts_provider"),
            "voice_id": request.data.get("voice_id"),
            "language_used": request.data.get("language_used"),
        },
    )
    return Response({"status": "ok"})


@api_view(["GET"])
@permission_classes([AllowAny])
def transcript(request, conversation_id):
    """Full transcript: list of { role, text, language?, created_at }."""
    try:
        conv = Conversation.objects.get(id=conversation_id)
    except Conversation.DoesNotExist:
        return Response({"error": "Conversation not found"}, status=status.HTTP_404_NOT_FOUND)

    turns = conv.user_turns.prefetch_related("agent_response").order_by("order_index")
    data = []
    for t in turns:
        data.append({
            "role": "user",
            "text": t.transcribed_text,
            "language": t.detected_language,
            "created_at": t.created_at.isoformat(),
        })
        if getattr(t, "agent_response", None):
            r = t.agent_response
            data.append({
                "role": "agent",
                "text": r.response_text,
                "created_at": r.created_at.isoformat(),
            })
    return Response(data)
