import logging
from django.urls import reverse
from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from django.shortcuts import get_object_or_404
from hub.services.models import Lead
from hub.services.odoo import OdooAPI
from .models import ServiceInstance, ServiceBrokerUser
from .serializers import (
    ServiceInstanceProvisioningSerializer,
    CatalogSerializer,
    ServiceInstanceUpdateSerializer,
)
from .authentication import ServiceBrokerAuthentication

logger = logging.getLogger(__name__)


class ServiceBrokerViewSet(viewsets.ViewSet):
    authentication_classes = [ServiceBrokerAuthentication]

    @action(detail=False, methods=["get"], url_path="catalog")
    def get_catalog(self, request):
        """
        Return the catalog of services available to the authenticated user.
        """
        # Get broker user and their allowed offerings
        broker_user = get_object_or_404(ServiceBrokerUser, user=request.user)
        offerings = broker_user.allowed_offerings.prefetch_related(
            "plans",
            "service",
            "cloud_provider",
        ).all()

        # Serialize the catalog
        serializer = CatalogSerializer({"services": offerings})
        return Response(serializer.data)

    def _create_lead_from_provision_data(self, offering, plan, parameters, context):
        """Create a lead in Odoo from provisioning data"""
        # Get the first user from parameters as the main contact
        user_data = parameters["users"][0]

        lead = Lead(
            service=offering.service,
            offering=offering,
            plan=plan,
            name=user_data["full_name"],
            company=context["organization_display_name"],
            email=user_data["email"],
            phone="",  # Not provided in broker API
        )

        try:
            odoo = OdooAPI()
            lead.odoo_lead_id = odoo.create_lead(lead, source="osbapi")
            lead.save()
            return lead
        except Exception as e:
            logger.error(f"Failed to create lead in Odoo: {str(e)}")
            raise

    @action(
        detail=False,
        methods=["put"],
        url_path="service_instances/(?P<instance_id>[^/.]+)",
    )
    def provision_instance(self, request, instance_id):
        # Validate request data
        serializer = ServiceInstanceProvisioningSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        # Get broker user and check offering access
        broker_user = get_object_or_404(ServiceBrokerUser, user=request.user)
        offering = serializer.validated_data["service_id"]  # This is now the offering

        if not broker_user.allowed_offerings.filter(id=offering.id).exists():
            return Response(
                {"error": "Service offering not available for this user"},
                status=status.HTTP_403_FORBIDDEN,
            )

        # Check if instance already exists
        if ServiceInstance.objects.filter(instance_id=instance_id).exists():
            return Response(status=status.HTTP_200_OK)

        try:
            # Create lead in Odoo
            lead = self._create_lead_from_provision_data(
                offering=offering,
                plan=serializer.validated_data["plan_id"],
                parameters=serializer.validated_data["parameters"],
                context=serializer.validated_data["context"],
            )

            # Create service instance
            instance = ServiceInstance.objects.create(
                instance_id=instance_id,
                offering=offering,
                plan=serializer.validated_data["plan_id"],
                organization_guid=serializer.validated_data["organization_guid"],
                space_guid=serializer.validated_data["space_guid"],
                organization_name=serializer.validated_data["context"][
                    "organization_name"
                ],
                parameters=serializer.validated_data["parameters"],
                context=serializer.validated_data["context"],
                lead=lead,
            )

            return Response(
                {
                    "dashboard_url": settings.WEBSITE_URL
                    + reverse(
                        "services:offering_detail",
                        kwargs={
                            "provider_slug": offering.cloud_provider.slug,
                            "service_slug": offering.service.slug,
                        },
                    ),
                    "operation": "provision",
                },
                status=status.HTTP_201_CREATED,
            )

        except Exception as e:
            logger.error(f"Error provisioning instance: {str(e)}")
            return Response(
                {"error": "Failed to provision service instance"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

    @action(
        detail=False,
        methods=["delete"],
        url_path="service_instances/(?P<instance_id>[^/.]+)",
    )
    def deprovision_instance(self, request, instance_id):
        instance = get_object_or_404(ServiceInstance, instance_id=instance_id)
        instance.delete()
        return Response(status=status.HTTP_200_OK)

    @action(
        detail=False,
        methods=["get"],
        url_path="service_instances/(?P<instance_id>[^/.]+)",
    )
    def get_instance(self, request, instance_id):
        instance = get_object_or_404(ServiceInstance, instance_id=instance_id)
        return Response(
            {
                "service_id": str(instance.offering.id),
                "plan_id": str(instance.plan.id),
                "dashboard_url": settings.WEBSITE_URL
                + reverse(
                    "services:offering_detail",
                    kwargs={
                        "provider_slug": instance.offering.cloud_provider.slug,
                        "service_slug": instance.offering.service.slug,
                    },
                ),
            }
        )

    @action(
        detail=False,
        methods=["patch"],
        url_path="service_instances/(?P<instance_id>[^/.]+)",
    )
    def update_instance(self, request, instance_id):
        instance = get_object_or_404(ServiceInstance, instance_id=instance_id)
        serializer = ServiceInstanceUpdateSerializer(
            data=request.data, context={"instance": instance}
        )

        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        instance.plan = serializer.validated_data["plan_id"]
        instance.save()

        return Response(
            {
                "operation": "update",
                "dashboard_url": settings.WEBSITE_URL
                + reverse(
                    "services:offering_detail",
                    kwargs={
                        "provider_slug": instance.offering.cloud_provider.slug,
                        "service_slug": instance.offering.service.slug,
                    },
                ),
            }
        )
