"""Manipulate Markov data via the Django site."""
import json
import logging
import time

from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.decorators import api_view, authentication_classes, permission_classes

import markov.lib as markovlib
from markov.models import MarkovContext

logger = logging.getLogger(__name__)


def index(request):
    """Display nothing, for the moment."""

    return HttpResponse()


def context_index(request, context_id):
    """Display the context index for the given context."""

    start_t = time.time()
    context = get_object_or_404(MarkovContext, pk=context_id)
    chain = " ".join(markovlib.generate_line(context))
    end_t = time.time()

    return render(request, 'markov/context.html', {'chain': chain, 'context': context, 'elapsed': end_t - start_t})


@api_view(['POST'])
@authentication_classes((BasicAuthentication, ))
@permission_classes((IsAuthenticated, ))
def rpc_generate_line_for_context(request, context):
    """Generate a line from a given context, with optional topics included."""
    if request.method != 'POST':
        return Response({'detail': "Supported method: POST."}, status=405)

    topics = None
    try:
        if request.body:
            markov_data = json.loads(request.body)
            topics = markov_data.get('topics', [])
    except (json.decoder.JSONDecodeError, KeyError):
        return Response({'detail': "Request body, if provided, must be JSON with an optional 'topics' parameter."},
                        status=400)

    context_id = markovlib.get_or_create_target_context(context)
    try:
        generated_words = markovlib.generate_line(context_id, topics)
    except ValueError as vex:
        return Response({'detail': f"Could not generate line: {vex}", 'context': context, 'topics': topics},
                        status=400)
    else:
        return Response({
            'context': context, 'topics': topics,
            'generated_line': ' '.join(generated_words), 'generated_words': generated_words
        })


@api_view(['POST'])
@authentication_classes((BasicAuthentication, ))
@permission_classes((IsAuthenticated, ))
def rpc_learn_line_for_context(request, context):
    """Learn a line for a given context."""
    if request.method != 'POST':
        return Response({'detail': "Supported method: POST."}, status=405)

    try:
        markov_data = json.loads(request.body)
        line = markov_data.get('line', [])
    except (json.decoder.JSONDecodeError, KeyError):
        return Response({'detail': "Request body must be JSON with a 'line' parameter."}, status=400)

    context_id = markovlib.get_or_create_target_context(context)
    markovlib.learn_line(line, context_id)
    return Response({'status': "OK", 'context': context, 'line': line})