from django.shortcuts import render

from .models import liuyao

from rest_framework.views import APIView, status
from rest_framework.response import Response

import iching.utils as iutils

from django.shortcuts import render
from .models import liuyao
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from datetime import datetime
from django.conf import settings

def liuyao_entry(request):
    """Main liuyao page with entry form."""
    context = {
        'current_datetime': datetime.now(iutils.bz.gMYTimezone).strftime('%Y-%m-%d %H:%M'),
    }
    return render(request, 'liuyao/liuyao-entry.html', context)

@login_required
def LiuyaoList(request):
    """Display list of existing liuyao charts."""
    items = liuyao.objects.filter(user_id=request.user.id).order_by('-id')
    
    # Get items per page from session, URL param, or settings
    items_per_page = request.session.get('liuyao_items_per_page')
    
    if not items_per_page:
        url_value = request.GET.get('per_page')
        if url_value and url_value.isdigit() and 5 <= int(url_value) <= 100:
            items_per_page = int(url_value)
        else:
            items_per_page = settings.PAGINATE_BY.get('liuyao', settings.PAGINATE_BY['default'])
    
    paginator = Paginator(items, items_per_page)
    page_number = request.GET.get('page')
    current_page = paginator.get_page(page_number)

    # Generate a list of page numbers to display
    page_range = range(
        max(current_page.number - 3, 1),
        min(current_page.number + 3, current_page.paginator.num_pages) + 1
    )

    context = {
        'items': current_page,
        'page_range': page_range,
        'items_per_page': items_per_page  # Pass to template for display
    }
    return render(request, 'liuyao/liuyao-list.html', context)

import json
from django.forms.models import model_to_dict
from django.core.exceptions import ObjectDoesNotExist

@login_required
def LiuyaoDetail(request, pk):
    # Create a custom JSON encoder that handles datetime objects
    def convert_datetime_to_iso(obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, dict):
            return {key: convert_datetime_to_iso(value) for key, value in obj.items()}
        elif isinstance(obj, list):
            return [convert_datetime_to_iso(item) for item in obj]
        return obj

    try:
        item = liuyao.objects.get(pk=pk, user_id=request.user.id)
        item_dict = model_to_dict(item)
        # Use the recalculate_liuyao_data function from iutils.liuyao
        # Pass qdate as datetime object before converting to ISO string
        item_dict = iutils.liuyao.recalculate_liuyao_data(item_dict, date=item.qdate)
        item_dict = convert_datetime_to_iso(item_dict)
        item_json = json.dumps(item_dict)
    except ObjectDoesNotExist:
        return render(request, 'errors/404.html', status=404)

    # Get configurable message limit
    from ai.models import ConversationConfig
    max_messages = ConversationConfig.get_max_messages()

    return render(request, 'liuyao/liuyao-detail.html', {
        'item': item,
        'item_json': item_json,
        'max_messages': max_messages,
    })

from api.serializers import LiuyaoCalculatorSerializer
from drf_spectacular.utils import extend_schema, extend_schema_view
from datetime import datetime
from django.http import QueryDict
class LiuyaoCalculator(APIView):
    serializer_class = LiuyaoCalculatorSerializer

    @extend_schema(
        summary="Calculate Liuyao result",
        description="This endpoint calculates the Liuyao result based on the provided input data.",
        request=LiuyaoCalculatorSerializer,  # Specify the request serializer
        parameters=[
            LiuyaoCalculatorSerializer,  # Use the serializer for query parameters
        ],
        responses={
            200: LiuyaoCalculatorSerializer,  # Specify the response serializer
            400: "Invalid input data",  # Example of a plain string for error responses
        },
    )
    def get(self, request, *args, **kwargs):
        # Validate query parameters using the extended serializer
        serializer = LiuyaoCalculatorSerializer(data=request.query_params)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        # Extract necessary data for calculations
        usecur = validated_data.get('usecur', False)
        date = (
            datetime.now(iutils.bz.gMYTimezone)
            if usecur
            else datetime(
                validated_data['year'],
                validated_data['month'],
                validated_data['day'],
                *map(int, validated_data.get('time', "00:00").split(':'))
            )
        )

        # Create a data structure for recalculation
        item_data = {
            'y1': validated_data['y1'],
            'y2': validated_data['y2'],
            'y3': validated_data['y3'],
            'y4': validated_data['y4'],
            'y5': validated_data['y5'],
            'y6': validated_data['y6'],
            'data': {}
        }
        
        # Use the shared recalculate_liuyao_data function
        item_data = iutils.liuyao.recalculate_liuyao_data(item_data, date)

        result = {
            'gua': {
                'question': validated_data['question'],
                'bz': item_data['data']['bz'],
                'god6': item_data['data']['god6'],
                'ly': item_data['data']['ly'],
                'rel': item_data['data']['rel'],
            },
            'question': validated_data['question'],
            'yao': f"{validated_data['y1']}|{validated_data['y2']}|{validated_data['y3']}|{validated_data['y4']}|{validated_data['y5']}|{validated_data['y6']}",
        }

        return Response(result)

from rest_framework import viewsets
from main.visitor import utils
from api.serializers import LiuyaoSerializer
from rest_framework.permissions import IsAuthenticated
from django.contrib.auth.mixins import LoginRequiredMixin
from rest_framework.authentication import SessionAuthentication

@extend_schema_view(
    list=extend_schema(
        summary="List all Liuyao objects",
        description="Retrieve a list of all Liuyao objects in the system."
    ),
    retrieve=extend_schema(
        summary="Retrieve a Liuyao object",
        description="Get details of a specific Liuyao object by its ID."
    ),
    create=extend_schema(
        summary="Create a Liuyao object",
        description="Add a new Liuyao object to the system."
    ),
    update=extend_schema(
        summary="Update a Liuyao object",
        description="Update an existing Liuyao object by its ID."
    ),
    partial_update=extend_schema(
        summary="Partially update a Liuyao object",
        description="Partially update an existing Liuyao object by its ID."
    ),
    destroy=extend_schema(
        summary="Delete a Liuyao object",
        description="Delete a specific Liuyao object by its ID."
    ),
)
class liuyaoViewSet(viewsets.ModelViewSet):
    queryset = liuyao.objects.all()
    serializer_class = LiuyaoSerializer
    authentication_classes = [SessionAuthentication]
    # Make the viewset accessible to both authenticated and unauthenticated users
    permission_classes = []

    def perform_create(self, serializer):
        # Always generate a UUID
        uuid_value = utils.getUUID(self.request)
        
        # Get user if authenticated
        user = self.request.user
        user_id = user.id if user.is_authenticated else None
        
        # Save with both UUID and user_id (if authenticated)
        serializer.save(uuid=uuid_value, user_id=user_id)
    
    def get_queryset(self):
        user = self.request.user
        if user.is_authenticated:
            # Return user's records if authenticated
            return liuyao.objects.filter(user_id=user.id)
        
        # Return an empty queryset or handle the case as needed
        return liuyao.objects.none()
