from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.parsers import JSONParser, MultiPartParser, FormParser
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema, OpenApiParameter

from .models import Company, OrgProfile, Department, Director
from .serializers import CompanySerializer, OrgProfileSerializer, DepartmentSerializer, DirectorSerializer


class CompanyViewSet(viewsets.ModelViewSet):
    """ViewSet for Company management."""
    rbac_domain = "phonebook"
    queryset = Company.objects.select_related("created_by")
    serializer_class = CompanySerializer
    parser_classes = [JSONParser, MultiPartParser, FormParser]

    def get_queryset(self):
        qs = super().get_queryset()
        company_type = self.request.query_params.get("company_type")
        if company_type:
            qs = qs.filter(company_type=company_type)
        donor_category = self.request.query_params.get("donor_category")
        if donor_category:
            qs = qs.filter(donor_category=donor_category)
        return qs

    @extend_schema(
        parameters=[
            OpenApiParameter(name="industry", type=str, description="Filter by industry"),
            OpenApiParameter(name="company_type", type=str, description="Filter by company_type (organization|donor)"),
        ]
    )
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

    @action(detail=True, methods=["post", "delete"], url_path="logo",
            parser_classes=[MultiPartParser, FormParser, JSONParser])
    def logo(self, request, pk=None):
        company = self.get_object()
        if request.method == "DELETE":
            if company.logo:
                company.logo.delete(save=False)
            company.logo = None
            company.save(update_fields=["logo", "updated_at"])
            return Response(self.get_serializer(company).data)

        file = request.FILES.get("logo")
        if not file:
            return Response({"detail": "Missing 'logo' file."},
                            status=status.HTTP_400_BAD_REQUEST)
        from apps.core.uploads import validate_upload
        validate_upload(file)
        if company.logo:
            company.logo.delete(save=False)
        company.logo = file
        company.save(update_fields=["logo", "updated_at"])
        return Response(self.get_serializer(company).data)


class OrgProfileViewSet(viewsets.ViewSet):
    """Singleton org profile. GET /org-profile/ returns the row, PATCH updates it."""
    rbac_domain = "phonebook"
    parser_classes = [JSONParser, MultiPartParser, FormParser]

    def _get_singleton(self):
        obj = OrgProfile.objects.first()
        if obj is None:
            obj = OrgProfile.objects.create(name="My Organization")
        return obj

    def list(self, request):
        obj = self._get_singleton()
        return Response(OrgProfileSerializer(obj, context={"request": request}).data)

    @action(detail=False, methods=["get", "patch", "put"], url_path="current")
    def current(self, request):
        obj = self._get_singleton()
        if request.method in ("PATCH", "PUT"):
            partial = request.method == "PATCH"
            serializer = OrgProfileSerializer(obj, data=request.data, partial=partial, context={"request": request})
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
        return Response(OrgProfileSerializer(obj, context={"request": request}).data)


class DepartmentViewSet(viewsets.ModelViewSet):
    """ViewSet for internal Department records."""
    rbac_domain = "phonebook"
    queryset = Department.objects.all().select_related("parent", "head__user")
    serializer_class = DepartmentSerializer

    def get_serializer_context(self):
        ctx = super().get_serializer_context()
        # Employee GROUP BY runs for every action otherwise (incl. writes);
        # 60s staleness on a headcount badge is fine.
        from django.core.cache import cache
        counts = cache.get("dept_counts")
        if counts is None:
            from apps.hr.models import Employee
            from django.db.models import Count
            counts = dict(
                Employee.objects.values_list("department").annotate(c=Count("id"))
            )
            cache.set("dept_counts", counts, 60)
        ctx["dept_counts"] = counts
        return ctx


class DirectorViewSet(viewsets.ModelViewSet):
    """ViewSet for board / executive Director records."""
    rbac_domain = "phonebook"
    queryset = Director.objects.all().select_related("employee__user__contact_profile")
    serializer_class = DirectorSerializer
    parser_classes = [JSONParser, MultiPartParser, FormParser]
