from django.shortcuts import get_object_or_404
from rest_framework import permissions, serializers
from rest_framework.response import Response
from rest_framework.views import APIView

from api_core.application import mutation

from .automation import can_configure, configure, readiness
from .exceptions import SeasonError
from .models import Season, SeasonAutomationPolicy


class AutomationSerializer(serializers.ModelSerializer):
    class Meta:
        model = SeasonAutomationPolicy
        fields = "__all__"


class CalendarInput(serializers.Serializer):
    registration_opens_at = serializers.DateTimeField()
    starts_at = serializers.DateTimeField()
    midseason_opens_at = serializers.DateTimeField()
    midseason_closes_at = serializers.DateTimeField()
    round_gap_days = serializers.IntegerField(min_value=3, max_value=30, default=6)
    kickoff_time = serializers.TimeField(default="18:00")
    enabled = serializers.BooleanField(default=True)
    auto_successor = serializers.BooleanField(default=True)
    continental_enabled = serializers.BooleanField(default=True)
    adopt_legacy_calendar = serializers.BooleanField(default=False)
    end_date = serializers.DateField(required=False)


class AutomationControlInput(serializers.Serializer):
    enabled = serializers.BooleanField()


class SeasonAutomationView(APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def get(self, request, season_id):
        season = get_object_or_404(Season, pk=season_id)
        policy = SeasonAutomationPolicy.objects.filter(season=season).first()
        data = AutomationSerializer(policy).data if policy else None
        return Response({"policy": data, "readiness": readiness(season)})

    def post(self, request, season_id):
        get_object_or_404(Season, pk=season_id)
        if not can_configure(request.user):
            return Response(
                {
                    "detail": "Mother federation governance or platform administration required."
                },
                status=403,
            )
        s = CalendarInput(data=request.data)
        s.is_valid(raise_exception=True)
        return mutation(
            request=request,
            scope=f"season.{season_id}.automation",
            operation=lambda: configure(
                season_id=season_id, actor=request.user, **s.validated_data
            ),
            serialize=lambda row: AutomationSerializer(row).data,
            domain_errors=(SeasonError,),
        )

    def patch(self, request, season_id):
        from django.db import transaction

        if not can_configure(request.user):
            return Response(
                {
                    "detail": "Mother federation governance or platform administration required."
                },
                status=403,
            )
        control = AutomationControlInput(data=request.data)
        control.is_valid(raise_exception=True)
        value = control.validated_data["enabled"]
        get_object_or_404(SeasonAutomationPolicy, season_id=season_id)

        def update():
            with transaction.atomic():
                row = SeasonAutomationPolicy.objects.select_for_update().get(
                    season_id=season_id
                )
                row.enabled = value
                row.operator = request.user
                row.save(update_fields=["enabled", "operator", "updated_at"])
                return row

        return mutation(
            request=request,
            scope=f"season.{season_id}.automation.control",
            operation=update,
            serialize=lambda row: AutomationSerializer(row).data,
            domain_errors=(SeasonError,),
        )
