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 .integration_serializers import (
    IstatAuditLogSerializer,
    IstatConnectionStatusSerializer,
    IstatCredentialWriteSerializer,
    IstatManualSyncRequestSerializer,
    IstatManualSyncResponseSerializer,
    IstatSyncHistorySerializer,
)
from .integration_services import (
    build_connection_payload,
    create_istat_audit_log,
    get_accessible_structure,
    trigger_manual_sync,
)
from .models import IstatAuditLog, IstatCredential, IstatSyncHistory


@extend_schema(
    tags=["ISTAT"],
    summary="Get, connect, update, or disconnect ISTAT credentials for a structure",
    request=IstatCredentialWriteSerializer,
    responses={
        200: IstatConnectionStatusSerializer,
        201: IstatConnectionStatusSerializer,
        400: OpenApiResponse(description="Validation error"),
        404: OpenApiResponse(description="Structure or credential not found"),
        409: OpenApiResponse(description="ISTAT credentials already exist"),
    },
)
class IstatCredentialAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )
        return Response(build_connection_payload(structure))

    def post(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )

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

        serializer = IstatCredentialWriteSerializer(
            data=request.data,
            context={"structure": structure, "user": request.user},
        )
        serializer.is_valid(raise_exception=True)
        credential = serializer.save()

        create_istat_audit_log(
            structure=structure,
            credential=credential,
            actor=request.user,
            action=IstatAuditLog.Action.CREDENTIAL_CREATED,
            message=f"User {request.user.username} created ISTAT credentials.",
            metadata={"structure_id": structure.id},
        )

        return Response(
            build_connection_payload(structure),
            status=status.HTTP_201_CREATED,
        )

    def patch(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )
        credential = get_object_or_404(IstatCredential, structure=structure)

        serializer = IstatCredentialWriteSerializer(
            credential,
            data=request.data,
            partial=True,
            context={"structure": structure, "user": request.user},
        )
        serializer.is_valid(raise_exception=True)
        credential = serializer.save()

        create_istat_audit_log(
            structure=structure,
            credential=credential,
            actor=request.user,
            action=IstatAuditLog.Action.CREDENTIAL_UPDATED,
            message=f"User {request.user.username} updated ISTAT credentials.",
            metadata={"structure_id": structure.id},
        )

        return Response(build_connection_payload(structure))

    def delete(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )
        credential = get_object_or_404(IstatCredential, structure=structure)
        credential_id = credential.id

        create_istat_audit_log(
            structure=structure,
            credential=credential,
            actor=request.user,
            action=IstatAuditLog.Action.CREDENTIAL_DELETED,
            message=f"User {request.user.username} deleted ISTAT credentials.",
            metadata={"structure_id": structure.id, "credential_id": credential_id},
        )

        credential.delete()
        return Response(build_connection_payload(structure))


@extend_schema(
    tags=["ISTAT"],
    summary="Trigger a manual ISTAT monthly sync (stub)",
    request=IstatManualSyncRequestSerializer,
    responses={
        200: IstatManualSyncResponseSerializer,
        400: OpenApiResponse(description="Validation error"),
        404: OpenApiResponse(description="Structure not found"),
    },
)
class IstatManualSyncAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )

        serializer = IstatManualSyncRequestSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        try:
            _, response_payload = trigger_manual_sync(
                structure=structure,
                actor=request.user,
                requested_period=serializer.validated_data,
                request_payload=dict(request.data or {}),
            )
        except ValueError as exc:
            return Response(
                {"detail": str(exc)},
                status=status.HTTP_400_BAD_REQUEST,
            )

        return Response(response_payload, status=status.HTTP_200_OK)


@extend_schema(
    tags=["ISTAT"],
    summary="List manual ISTAT sync history for a structure",
    responses={200: IstatSyncHistorySerializer(many=True)},
)
class IstatSyncHistoryAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )
        history = IstatSyncHistory.objects.filter(structure=structure)
        return Response(IstatSyncHistorySerializer(history, many=True).data)


@extend_schema(
    tags=["ISTAT"],
    summary="List ISTAT audit logs for a structure",
    responses={200: IstatAuditLogSerializer(many=True)},
)
class IstatAuditLogAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, structure_id):
        structure = get_accessible_structure(
            user=request.user,
            structure_id=structure_id,
        )
        logs = IstatAuditLog.objects.filter(structure=structure)
        return Response(IstatAuditLogSerializer(logs, many=True).data)
