import json
import jwt
import requests
from datetime import datetime, timedelta
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from .models import Reuniao, SolicitacaoEntrada
from .forms import ReuniaoForm
from .utils.livekit import gerar_token_reuniao
import uuid
import logging
from .utils.livekit import gerar_token_admin
from django.views.decorators.http import require_POST  
from django.contrib.auth import logout as dj_logout

logger = logging.getLogger(__name__)





# Configurações LiveKit
LIVEKIT_API_KEY = getattr(settings, "LIVEKIT_API_KEY", "APIJK8nTcNANfTX")
LIVEKIT_API_SECRET = getattr(settings, "LIVEKIT_API_SECRET",
    "cRwOxXlflTc1THe4Y1rp0v8ZBvznzvU4ynTS5fvdzDIB")
LIVEKIT_URL = getattr(settings, 'LIVEKIT_URL', 'wss://rtc.agenda.grfgraph.com:4443')


import time  # precisa importar

import time  # garantir que tenha importado

def update_participant_permissions(room_name, participant_identity, can_publish):
    """Atualiza permissões de um participante via API LiveKit"""
    try:
        payload = {
            "iss": LIVEKIT_API_KEY,  # sua API Key
            "aud": "livekit",         # obrigatório para chamadas REST
            "exp": int(time.time()) + 60,  # token expira em 60 segundos
        }
        jwt_token = jwt.encode(payload, LIVEKIT_API_SECRET, algorithm="HS256")

        url = f"{LIVEKIT_URL.replace('wss://', 'https://')}/twirp/livekit.RoomService/UpdateParticipant"
        headers = {
            "Authorization": f"Bearer {jwt_token}",
            "Content-Type": "application/json",
        }
        data = {
            "room": room_name,
            "identity": participant_identity,
            "permission": {
                "canPublish": can_publish,
                "canSubscribe": True,
                "canPublishData": True,
            },
        }
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
        logger.info(f"Permissões atualizadas para {participant_identity} em {room_name}: can_publish={can_publish}")
        return response.json()
    except Exception as e:
        logger.error(f"Erro ao atualizar permissões para {participant_identity}: {str(e)}")
        return None


from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.models import AnonymousUser

@csrf_exempt
def obter_token_convidado(request, codigo):
    try:
        reuniao = get_object_or_404(Reuniao, codigo=codigo)

        # Se o usuário estiver autenticado (host), usa o nome dele
        if request.user.is_authenticated:
            usuario = request.user.username
        else:
            usuario = request.session.get('nome_convidado', f"Convidado_{uuid.uuid4().hex[:6]}")

        token = gerar_token_reuniao(
            room=reuniao.codigo,
            user=usuario,
            can_publish=True  # Libera a publicação agora
        )
        return JsonResponse({'token': token})
    except Exception as e:
        logger.error(f"Erro ao gerar token novo para {codigo}: {str(e)}")
        return JsonResponse({'error': f"Erro interno: {str(e)}"}, status=500)


@login_required
def dashboard(request):
    reunioes = Reuniao.objects.filter(
        host=request.user, 
        data_hora__gte=timezone.now() - timedelta(hours=24)
    ).order_by('-data_hora')
    logger.debug(f"Carregando dashboard para {request.user.username}: {reunioes.count()} reuniões encontradas")
    return render(request, 'reunioes/dashboard.html', {'reunioes': reunioes})

@login_required
def agendar_reuniao(request):
    if request.method == 'POST':
        form = ReuniaoForm(request.POST)
        if form.is_valid():
            reuniao = form.save(commit=False)
            reuniao.host = request.user
            reuniao.codigo = uuid.uuid4().hex[:10]
            reuniao.save()
            logger.info(f"Reunião agendada por {request.user.username}: codigo={reuniao.codigo}")
            return redirect('dashboard')
        else:
            logger.warning(f"Erro no formulário de agendamento por {request.user.username}: {form.errors}")
    else:
        form = ReuniaoForm()
    return render(request, 'reunioes/agendar.html', {'form': form})

@csrf_exempt
def entrar_reuniao(request, codigo):
    try:
        reuniao = Reuniao.objects.get(codigo=codigo)
    except Reuniao.DoesNotExist:
        logger.warning(f"Tentativa de acessar reunião expirada: {codigo}")
        return render(request, 'reunioes/reuniao_expirada.html', status=410)  # HTTP 410 Gone

    if request.user.is_authenticated:
        user = request.user.username
        papel = "host" if request.user == reuniao.host else "convidado"
    else:
        user = request.session.get('nome_convidado', f"Convidado_{uuid.uuid4().hex[:6]}")
        request.session['nome_convidado'] = user
        papel = "convidado"

    token = gerar_token_reuniao(
        room=reuniao.codigo,
        user=user,
        can_publish=True
    )

    logger.info(f"Usuário {user} entrando na reunião {codigo} como {papel}")
    return render(request, 'reunioes/reuniao.html', {
        'reuniao': reuniao,
        'token': token,
        'ws_url': LIVEKIT_URL.replace('https://', 'wss://'),
        'usuario': user,
        'papel': papel,
    })



@csrf_exempt
def solicitar_entrada(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body.decode('utf-8'))
            codigo = data.get('codigo')
            nome = data.get('nome')

            if not nome:
                nome = request.session.get('nome_convidado')
                if not nome:
                    nome = f"Convidado_{uuid.uuid4().hex[:6]}"
                    request.session['nome_convidado'] = nome

            if not codigo:
                logger.warning("Tentativa de solicitação sem código da reunião")
                return JsonResponse({'error': 'Código da reunião ausente'}, status=400)

            reuniao = get_object_or_404(Reuniao, codigo=codigo)

            obj, created = SolicitacaoEntrada.objects.update_or_create(
                reuniao=reuniao,
                nome=nome,
                defaults={'autorizado': False}
            )
            logger.info(f"Solicitação de entrada: nome={nome}, codigo={codigo}, created={created}, id={obj.id}")

            return JsonResponse({'ok': True, 'created': created, 'id': obj.id})
        except Exception as e:
            logger.error(f"Erro ao processar solicitação de entrada: {str(e)}")
            return JsonResponse({'error': f"Erro interno: {str(e)}"}, status=500)
    logger.warning(f"Método inválido para solicitação de entrada: {request.method}")
    return JsonResponse({'error': 'Método inválido'}, status=405)

@login_required
def listar_solicitacoes(request, codigo):
    try:
        reuniao = get_object_or_404(Reuniao, codigo=codigo, host=request.user)
        pendentes = reuniao.solicitacoes.filter(autorizado=False)
        solicitacoes = [
            {
                'id': s.id,
                'nome': s.nome,
                'data': s.data_solicitacao.strftime('%H:%M:%S')
            } for s in pendentes
        ]
        logger.info(f"Solicitações pendentes para {codigo}: {len(solicitacoes)} encontradas - {[s['nome'] for s in solicitacoes]}")
        return JsonResponse({'solicitacoes': solicitacoes})
    except Exception as e:
        logger.error(f"Erro ao listar solicitações para {codigo}: {str(e)}")
        return JsonResponse({'error': f"Erro ao listar solicitações: {str(e)}"}, status=500)



@csrf_exempt
@login_required
def autorizar_entrada(request):
    if request.method != 'POST':
        return JsonResponse({'error': 'Método inválido'}, status=405)
    try:
        data = json.loads(request.body)
        sid = data.get('id')
        acao = data.get('acao')
        if not sid or acao not in ('permitir','negar'):
            return JsonResponse({'error': 'ID ou ação inválidos'}, status=400)

        solicitacao = SolicitacaoEntrada.objects.get(id=sid)
        reuniao = solicitacao.reuniao

        # Só o host da reunião pode autorizar
        if request.user != reuniao.host:
            return JsonResponse({'error': 'Permissão negada'}, status=403)

        if acao == 'permitir':
            solicitacao.autorizado = True
            solicitacao.save()
            # Atualiza permissão no LiveKit: agora o convidado pode publicar
            update_participant_permissions(
                room_name=reuniao.codigo,
                participant_identity=solicitacao.nome,
                can_publish=True
            )
            logger.info(f"Permissão de publish habilitada para {solicitacao.nome} em {reuniao.codigo}")
        else:  # negar
            solicitacao.delete()
            logger.info(f"Solicitação de {solicitacao.nome} negada e removida de {reuniao.codigo}")

        return JsonResponse({'ok': True})
    except SolicitacaoEntrada.DoesNotExist:
        return JsonResponse({'error': 'Solicitação não encontrada'}, status=404)
    except Exception as e:
        logger.error(f"Erro ao autorizar entrada: {e}")
        return JsonResponse({'error': f"Erro interno: {e}"}, status=500)




@csrf_exempt
def check_autorizacao(request, codigo):
    try:
        usuario = request.GET.get('usuario')
        if not usuario:
            logger.warning(f"Tentativa de verificação de autorização sem usuário: codigo={codigo}")
            return JsonResponse({'error': 'Usuário não especificado'}, status=400)
        
        reuniao = get_object_or_404(Reuniao, codigo=codigo)
        
        autorizado = SolicitacaoEntrada.objects.filter(
            reuniao=reuniao,
            nome=usuario,
            autorizado=True
        ).exists()
        
        logger.debug(f"Verificação de autorização: usuario={usuario}, codigo={codigo}, autorizado={autorizado}")
        return JsonResponse({'autorizado': autorizado})
    except Exception as e:
        logger.error(f"Erro ao verificar autorização para {codigo}: {str(e)}")
        return JsonResponse({'error': f"Erro interno: {str(e)}"}, status=500)

@require_POST
@login_required
def encerrar_reuniao(request, codigo):
    """
    • Autorizado somente ao host da sala
    • Fecha a sala no LiveKit (DeleteRoom)
    • Remove registro da reunião no Django
    """
    reuniao = get_object_or_404(Reuniao, codigo=codigo, host=request.user)

    # ---- encerra sala no LiveKit --------------------------------------
    jwt_token = jwt.encode(
        {"iss": LIVEKIT_API_KEY, "aud": "livekit", "exp": int(time.time()) + 30},
        LIVEKIT_API_SECRET,
        algorithm="HS256"
    )

    try:
        resp = requests.post(
            f"{LIVEKIT_REST}/twirp/livekit.RoomService/DeleteRoom",
            headers={"Authorization": f"Bearer {jwt_token}"},
            json={"room": codigo},
            timeout=5
        )
        resp.raise_for_status()
    except Exception as exc:
        # Logue, mas continue – queremos garantir que a reunião “some” do front
        logger.error("DeleteRoom falhou para %s: %s", codigo, exc)

    # ---- remove do banco ---------------------------------------------
    reuniao.delete()
    logger.info("Reunião %s encerrada por %s", codigo, request.user.username)

    return JsonResponse({"ok": True})




@login_required
def obter_token(request, codigo):
    try:
        reuniao = get_object_or_404(Reuniao, codigo=codigo)
        token = gerar_token_reuniao(
            room=reuniao.codigo,
            user=request.user.username,
            can_publish=(request.user == reuniao.host)
        )
        logger.debug(f"Token gerado para {request.user.username} na reunião {codigo}")
        return JsonResponse({'token': token})
    except Exception as e:
        logger.error(f"Erro ao gerar token para {codigo}: {str(e)}")
        return JsonResponse({'error': f"Erro interno: {str(e)}"}, status=500)

def gerar_token(request, codigo_sala):
    try:
        usuario = request.user.username if request.user.is_authenticated else f"Anon_{uuid.uuid4().hex[:6]}"
        token = gerar_token_reuniao(room=codigo_sala, user=usuario)
        logger.debug(f"Token gerado para {usuario} na sala {codigo_sala}")
        return JsonResponse({'token': token})
    except Exception as e:
        logger.error(f"Erro ao gerar token para {codigo_sala}: {str(e)}")
        return JsonResponse({'error': f"Erro interno: {str(e)}"}, status=500)

# reunioes/views.py


@login_required
def sair(request):
    """
    • Limpa dados da sessão (inclui 'nome_convidado')
    • Desfaz autenticação Django
    """
    request.session.flush()      # remove tudo que for de sessão (incl. convidado)
    dj_logout(request)
    return redirect("login")     # ajuste para sua rota de login/página inicial




@csrf_exempt
@login_required
@require_POST
def expulsar_participante(request):
    try:
        data = json.loads(request.body)
        room = data.get("room")
        identity = data.get("identity")

        if not room or not identity:
            return JsonResponse({'error': 'Parâmetros ausentes'}, status=400)

        jwt_token = jwt.encode(
            {"iss": LIVEKIT_API_KEY, "aud": "livekit", "exp": int(time.time()) + 30},
            LIVEKIT_API_SECRET,
            algorithm="HS256"
        )

        response = requests.post(
            f"{LIVEKIT_URL.replace('wss://', 'https://')}/twirp/livekit.RoomService/RemoveParticipant",
            headers={"Authorization": f"Bearer {jwt_token}"},
            json={"room": room, "identity": identity},
            timeout=5
        )
        response.raise_for_status()

        logger.info(f"Participante {identity} removido da sala {room}")
        return JsonResponse({"ok": True})
    except Exception as e:
        logger.error(f"Erro ao remover participante {identity} da sala {room}: {e}")
        return JsonResponse({'error': str(e)}, status=500)
