"""
alloggiati/views.py
===================
API views for the Alloggiati Web integration.

Endpoints:
  POST   /api/alloggiati/sync
  GET    /api/alloggiati/sync/logs/<structure_id>
  GET    /api/alloggiati/credentials/<structure_id>
  POST   /api/alloggiati/credentials/<structure_id>
  PATCH  /api/alloggiati/credentials/<structure_id>
  DELETE /api/alloggiati/credentials/<structure_id>
"""

from __future__ import annotations

from django.db.models import Q
from django.shortcuts import get_object_or_404
from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from alloggiati.models import AlloggiatiCredential, AlloggiatiSyncLog
from alloggiati.serializers import (
    AlloggiatiCredentialStatusSerializer,
    AlloggiatiCredentialWriteSerializer,
    AlloggiatiSyncLogSerializer,
    AlloggiatiSyncRequestSerializer,
    AlloggiatiSyncResponseSerializer,
)
from alloggiati.service import AlloggiatiService
from structures.models import Structure


def _get_accessible_structure(user, structure_id: int) -> Structure:
    qs = Structure.objects.filter(
        Q(user=user) | Q(structure_users__user=user)
    ).distinct()
    return get_object_or_404(qs, id=structure_id)


# ---------------------------------------------------------------------------
# Sync trigger
# ---------------------------------------------------------------------------

class AlloggiatiSyncAPIView(APIView):
    """POST /api/alloggiati/sync — trigger a manual Alloggiati Web sync."""

    permission_classes = [IsAuthenticated]

    @extend_schema(
        tags=["Alloggiati"],
        summary="Trigger Alloggiati Web guest sync",
        request=AlloggiatiSyncRequestSerializer,
        responses={
            200: AlloggiatiSyncResponseSerializer,
            400: OpenApiResponse(description="Validation error"),
            502: OpenApiResponse(description="Alloggiati Web error"),
        },
    )
    def post(self, request):
        serializer = AlloggiatiSyncRequestSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        _get_accessible_structure(request.user, data["structureId"])

        result = AlloggiatiService.sync(
            structure_id=data["structureId"],
            date_from=data["dateFrom"].isoformat(),
            date_to=data["dateTo"].isoformat(),
        )

        http_status = (
            status.HTTP_200_OK
            if result["status"] in ("CONNECTED", "PARTIAL")
            else status.HTTP_502_BAD_GATEWAY
        )
        return Response(result, status=http_status)


# ---------------------------------------------------------------------------
# Sync log history
# ---------------------------------------------------------------------------

class AlloggiatiSyncLogListAPIView(APIView):
    """GET /api/alloggiati/sync/logs/<structure_id> — list sync history."""

    permission_classes = [IsAuthenticated]

    @extend_schema(
        tags=["Alloggiati"],
        summary="List Alloggiati sync logs for a structure",
        responses={200: AlloggiatiSyncLogSerializer(many=True)},
    )
    def get(self, request, structure_id: int):
        structure = _get_accessible_structure(request.user, structure_id)
        logs = AlloggiatiSyncLog.objects.filter(structure=structure)[:50]
        return Response(AlloggiatiSyncLogSerializer(logs, many=True).data)


# ---------------------------------------------------------------------------
# Credential management
# ---------------------------------------------------------------------------

class AlloggiatiCredentialAPIView(APIView):
    """CRUD for AlloggiatiCredential per structure."""

    permission_classes = [IsAuthenticated]

    def _status_payload(self, structure: Structure) -> dict:
        cred = AlloggiatiCredential.objects.filter(structure=structure).first()
        return {
            "structure_id": structure.id,
            "connected": cred is not None,
            "mode": cred.mode if cred else None,
            "created_at": cred.created_at if cred else None,
            "updated_at": cred.updated_at if cred else None,
        }

    @extend_schema(
        tags=["Alloggiati"],
        summary="Get Alloggiati credential status",
        responses={200: AlloggiatiCredentialStatusSerializer},
    )
    def get(self, request, structure_id: int):
        structure = _get_accessible_structure(request.user, structure_id)
        return Response(self._status_payload(structure))

    @extend_schema(
        tags=["Alloggiati"],
        summary="Create Alloggiati credentials",
        request=AlloggiatiCredentialWriteSerializer,
        responses={
            201: AlloggiatiCredentialStatusSerializer,
            409: OpenApiResponse(description="Credential already exists"),
        },
    )
    def post(self, request, structure_id: int):
        structure = _get_accessible_structure(request.user, structure_id)

        if AlloggiatiCredential.objects.filter(structure=structure).exists():
            return Response(
                {"detail": "Alloggiati credentials already exist for this structure."},
                status=status.HTTP_409_CONFLICT,
            )

        serializer = AlloggiatiCredentialWriteSerializer(
            data=request.data,
            context={"structure": structure},
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(self._status_payload(structure), status=status.HTTP_201_CREATED)

    @extend_schema(
        tags=["Alloggiati"],
        summary="Update Alloggiati credentials",
        request=AlloggiatiCredentialWriteSerializer,
        responses={200: AlloggiatiCredentialStatusSerializer},
    )
    def patch(self, request, structure_id: int):
        structure = _get_accessible_structure(request.user, structure_id)
        credential = get_object_or_404(AlloggiatiCredential, structure=structure)

        serializer = AlloggiatiCredentialWriteSerializer(
            credential,
            data=request.data,
            partial=True,
            context={"structure": structure},
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(self._status_payload(structure))

    @extend_schema(
        tags=["Alloggiati"],
        summary="Delete Alloggiati credentials",
        responses={200: AlloggiatiCredentialStatusSerializer},
    )
    def delete(self, request, structure_id: int):
        structure = _get_accessible_structure(request.user, structure_id)
        credential = get_object_or_404(AlloggiatiCredential, structure=structure)
        credential.delete()
        return Response(self._status_payload(structure))
