from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse, StreamingHttpResponse, HttpResponseRedirect
from django.core.management import call_command
from django.core.files.storage import default_storage
from django.urls import reverse
from django.conf import settings
from django.views.decorators.clickjacking import xframe_options_exempt
from .models import Chatbot, File, RAGMetadata
from .forms import FileUploadForm, ChatbotForm
from .utils import retrieve_ai_response
from io import StringIO
import logging

# Set up logging
logger = logging.getLogger(__name__)

def home(request):
    return render(request, 'home.html')

@login_required
def dashboard(request):
    chatbots = Chatbot.objects.filter(user=request.user)
    return render(request, 'dashboard.html', {'chatbots': chatbots})

@login_required
def chatbot_detail(request, chatbot_id):
    chatbot = get_object_or_404(Chatbot, id=chatbot_id, user=request.user)
    if request.method == 'POST':
        form = FileUploadForm(request.POST, request.FILES)
        if form.is_valid():
            file_instance = form.save(commit=False)
            file_instance.chatbot = chatbot
            file_instance.save()
            messages.success(request, 'File uploaded successfully!')
            return redirect('chatbot_detail', chatbot_id=chatbot.id)
    else:
        form = FileUploadForm()
    return render(request, 'chatbot_detail.html', {'chatbot': chatbot, 'form': form})

@login_required
def chatbot_create(request):
    if request.method == 'POST':
        form = ChatbotForm(request.POST)
        if form.is_valid():
            chatbot = form.save(commit=False)
            chatbot.user = request.user
            chatbot.save()
            messages.success(request, 'Chatbot created successfully!')
            return redirect('chatbot_detail', chatbot_id=chatbot.id)
    else:
        form = ChatbotForm()
    return render(request, 'chatbot_create.html', {'form': form})

@login_required
def process_rag_data(request, chatbot_id):
    logger.debug(f"Received request: method={request.method}, headers={dict(request.headers)}, chatbot_id={chatbot_id}")
    
    # Check authentication and chatbot ownership
    try:
        chatbot = get_object_or_404(Chatbot, id=chatbot_id, user=request.user)
    except Exception as e:
        logger.error(f"Chatbot access failed: {str(e)}")
        if request.method == 'POST':
            return StreamingHttpResponse(
                f"data: ERROR: Invalid chatbot or access denied: {str(e)}\n\n",
                content_type='text/event-stream',
                status=403
            )
        return render(request, 'process_rag_data.html', {'error': str(e)}, status=403)

    if request.method == 'POST':
        def stream_command_output():
            output = StringIO()
            try:
                call_command('process_rag_data', chatbot_id, stdout=output)
                output.seek(0)
                for line in output:
                    logger.debug(f"Streaming line: {line.strip()}")
                    yield f"data: {line.strip()}\n\n"
                yield "data: [DONE]\n\n"
            except Exception as e:
                logger.exception(f"RAG data processing failed: {str(e)}")
                yield f"data: ERROR: RAG data processing failed: {str(e)}\n\n"
            finally:
                output.close()
        
        try:
            response = StreamingHttpResponse(
                stream_command_output(),
                content_type='text/event-stream'
            )
            response['Cache-Control'] = 'no-cache'
            response['X-Accel-Buffering'] = 'no'
            return response
        except Exception as e:
            logger.exception(f"SSE streaming failed: {str(e)}")
            return StreamingHttpResponse(
                f"data: ERROR: Server error: {str(e)}\n\n",
                content_type='text/event-stream',
                status=500
            )
    
    return render(request, 'process_rag_data.html', {'chatbot': chatbot})

@login_required
def delete_file(request, chatbot_id, file_id):
    if request.method != 'POST':
        messages.error(request, 'Invalid request method.')
        return HttpResponseRedirect(reverse('chatbot_detail', args=[chatbot_id]))
    
    chatbot = get_object_or_404(Chatbot, id=chatbot_id, user=request.user)
    try:
        file_obj = File.objects.get(id=file_id, chatbot=chatbot)
        file_path = default_storage.path(file_obj.file.name)
        if default_storage.exists(file_path):
            default_storage.delete(file_path)
        file_obj.delete()
        messages.success(request, 'File deleted successfully!')
    except File.DoesNotExist:
        messages.error(request, 'File not found or you do not have permission to delete it.')
    
    return HttpResponseRedirect(reverse('chatbot_detail', args=[chatbot_id]))

@login_required
def search_rag(request, chatbot_id):
    logger.debug(f"Received request: method={request.method}, headers={dict(request.headers)}, chatbot_id={chatbot_id}")
    
    if request.method != 'POST':
        logger.error("Invalid method: Expected POST")
        return JsonResponse({'error': 'Method must be POST'}, status=400)
    
    if request.headers.get('X-Requested-With') != 'XMLHttpRequest':
        logger.error("Not an AJAX request: Missing X-Requested-With header")
        return JsonResponse({'error': 'Request must be AJAX'}, status=400)
    
    query = request.POST.get('query', '').strip()
    logger.debug(f"Query received: {query}")
    
    if not query:
        logger.error("Query is empty")
        return JsonResponse({'error': 'Query cannot be empty'}, status=400)

    # Use utility function with no AI response
    result = retrieve_ai_response(
        chatbot_id=chatbot_id,
        user=request.user,
        message=query,
        n_results=8,
        include_ai=False
    )

    if 'error' in result:
        return JsonResponse({'error': result['error']}, status=400 if "No RAG data" in result['error'] else 500)
    
    return JsonResponse({
        'results': result['results'],
        'warnings': result['warnings']
    })

@login_required
def chatbot_preview(request, chatbot_id):
    chatbot = get_object_or_404(Chatbot, id=chatbot_id, user=request.user)
    
    if request.method == 'POST':
        if request.headers.get('X-Requested-With') != 'XMLHttpRequest':
            logger.error("Not an AJAX request: Missing X-Requested-With header")
            return JsonResponse({'error': 'Request must be AJAX'}, status=400)
        
        message = request.POST.get('message', '').strip()
        logger.debug(f"Received chat message: {message}")
        
        if not message:
            logger.error("Message is empty")
            return JsonResponse({'error': 'Message cannot be empty'}, status=400)

        # Use utility function
        result = retrieve_ai_response(
            chatbot_id=chatbot_id,
            user=request.user,
            message=message,
            n_results=8,
            include_ai=True
        )

        if 'error' in result:
            return JsonResponse({'error': result['error']}, status=400 if "No RAG data" in result['error'] else 500)
        
        return JsonResponse({
            'response': result['response'],
            'rag_context': result['results'],
            'warnings': result['warnings']
        })
    
    return render(request, 'chatbot_preview.html', {'chatbot': chatbot})

@login_required
def chatbot_test(request, chatbot_id):
    chatbot = get_object_or_404(Chatbot, id=chatbot_id, user=request.user)
    return render(request, 'chatbot_test.html', {'chatbot': chatbot})

@login_required
@xframe_options_exempt
def chatbot_embed(request, chatbot_id):
    chatbot = get_object_or_404(Chatbot, id=chatbot_id, user=request.user)
    
    if request.method == 'POST':
        if request.headers.get('X-Requested-With') != 'XMLHttpRequest':
            logger.error("Not an AJAX request: Missing X-Requested-With header")
            return JsonResponse({'error': 'Request must be AJAX'}, status=400)
        
        message = request.POST.get('message', '').strip()
        logger.debug(f"Received chat message: {message}")
        
        if not message:
            logger.error("Message is empty")
            return JsonResponse({'error': 'Message cannot be empty'}, status=400)

        # Use utility function
        result = retrieve_ai_response(
            chatbot_id=chatbot_id,
            user=request.user,
            message=message,
            n_results=8,
            include_ai=True
        )

        if 'error' in result:
            return JsonResponse({'error': result['error']}, status=400 if "No RAG data" in result['error'] else 500)
        
        return JsonResponse({
            'response': result['response'],
            'rag_context': result['results'],
            'warnings': result['warnings']
        })
    
    return render(request, 'chatbot_embed.html', {'chatbot': chatbot})