"""
Strategy API v1 — Views.
"""
from rest_framework import viewsets, status, filters
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend

from ...infrastructure.persistence.models import (
    VisionModel, StrategicThemeModel,
    ObjectiveModel, KeyResultModel, KeyResultCheckInModel,
    KPIDefinitionModel, KPITargetModel, KPIActualModel, KPIAssignmentModel,
    StrategyMapModel, StrategyMapPerspectiveModel,
    StrategyMapObjectiveModel, CausalLinkModel,
    ScorecardModel, ScorecardPerspectiveModel, ScorecardMeasureModel,
    GateProcessModel, GateModel, GateReviewModel,
    GateReviewerModel, GateDeliverableModel,
    PolicyModel, PolicyAcknowledgmentModel,
    ObjectivePortfolioAlignmentModel,
)
from .serializers import (
    VisionListSerializer,
    VisionDetailSerializer,
    VisionCreateSerializer,
    VisionStatusSerializer,
    StrategicThemeListSerializer,
    StrategicThemeDetailSerializer,
    StrategicThemeCreateSerializer,
    ThemeStatusSerializer,
    ObjectiveListSerializer,
    ObjectiveDetailSerializer,
    ObjectiveCreateSerializer,
    ObjectiveStatusSerializer,
    KeyResultListSerializer,
    KeyResultDetailSerializer,
    KeyResultCreateSerializer,
    CheckInListSerializer,
    CheckInCreateSerializer,
    ObjectiveProgressSerializer,
    CascadeProgressSerializer,
    KPIDefinitionListSerializer,
    KPIDefinitionDetailSerializer,
    KPIDefinitionCreateSerializer,
    KPIStatusSerializer,
    KPITargetListSerializer,
    KPITargetDetailSerializer,
    KPITargetCreateSerializer,
    KPIActualListSerializer,
    KPIActualDetailSerializer,
    KPIActualCreateSerializer,
    KPIAssignmentListSerializer,
    KPIAssignmentDetailSerializer,
    KPIAssignmentCreateSerializer,
    KPIScoreSerializer,
    KPITrendSerializer,
    StrategyMapListSerializer,
    StrategyMapDetailSerializer,
    StrategyMapCreateSerializer,
    StrategyMapStatusSerializer,
    PerspectiveListSerializer,
    PerspectiveDetailSerializer,
    PerspectiveCreateSerializer,
    MapObjectiveListSerializer,
    MapObjectiveDetailSerializer,
    MapObjectiveCreateSerializer,
    CausalLinkListSerializer,
    CausalLinkDetailSerializer,
    CausalLinkCreateSerializer,
    ScorecardListSerializer,
    ScorecardDetailSerializer,
    ScorecardCreateSerializer,
    ScorecardStatusSerializer,
    ScPerspectiveListSerializer,
    ScPerspectiveDetailSerializer,
    ScPerspectiveCreateSerializer,
    ScMeasureListSerializer,
    ScMeasureDetailSerializer,
    ScMeasureCreateSerializer,
    ScorecardReportSerializer,
    GateProcessListSerializer,
    GateProcessDetailSerializer,
    GateProcessCreateSerializer,
    GateListSerializer,
    GateDetailSerializer,
    GateCreateSerializer,
    GateReviewListSerializer,
    GateReviewDetailSerializer,
    GateReviewCreateSerializer,
    GateReviewStatusSerializer,
    GateReviewerListSerializer,
    GateReviewerDetailSerializer,
    GateReviewerCreateSerializer,
    GateDeliverableListSerializer,
    GateDeliverableDetailSerializer,
    GateDeliverableCreateSerializer,
    PolicyListSerializer,
    PolicyDetailSerializer,
    PolicyCreateSerializer,
    PolicyStatusSerializer,
    PolicyAckListSerializer,
    PolicyAckDetailSerializer,
    PolicyAckCreateSerializer,
    AlignmentListSerializer,
    AlignmentDetailSerializer,
    AlignmentCreateSerializer,
    StrategicFitScoreSerializer,
)
from .permissions import (
    VisionPermission, StrategicThemePermission,
    ObjectivePermission, KeyResultPermission, CheckInPermission,
    KPIDefinitionPermission, KPITargetPermission,
    KPIActualPermission, KPIAssignmentPermission,
    StrategyMapPermission, MapPerspectivePermission,
    MapObjectivePermission, CausalLinkPermission,
    ScorecardPermission, ScPerspectivePermission, ScMeasurePermission,
    GateProcessPermission, GatePermission, GateReviewPermission,
    GateReviewerPermission, GateDeliverablePermission,
    PolicyPermission, PolicyAcknowledgmentPermission,
    AlignmentPermission,
)
from ...application.services.vision_service import VisionService
from ...application.services.strategic_theme_service import StrategicThemeService
from ...application.services.okr_service import OKRService
from ...application.services.kpi_service import KPIService
from ...application.services.strategy_map_service import StrategyMapService
from ...application.services.scorecard_service import ScorecardService
from ...application.services.stage_gate_service import StageGateService


class TenantFilterMixin:
    """Mixin — فیلتر خودکار queryset بر اساس tenant."""

    def get_queryset(self):
        qs = super().get_queryset()
        if hasattr(self.request, "tenant"):
            return qs.filter(tenant=self.request.tenant)
        return qs

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Vision ViewSet
# ═══════════════════════════════════════════════════

class VisionViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """CRUD + activate/archive برای چشم‌انداز."""
    queryset = VisionModel.objects.all()
    permission_classes = [IsAuthenticated, VisionPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["title", "description"]
    filterset_fields = ["status"]
    ordering_fields = ["title", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return VisionListSerializer
        if self.action in ("create", "update", "partial_update"):
            return VisionCreateSerializer
        if self.action == "change_status":
            return VisionStatusSerializer
        return VisionDetailSerializer

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        serializer = VisionStatusSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        svc = VisionService()
        action_name = serializer.validated_data["action"]

        if action_name == "activate":
            result = svc.activate(pk)
        elif action_name == "archive":
            result = svc.archive(pk)
        else:
            return Response(
                {"error": {"code": "invalid_action", "message": "عملیات نامعتبر"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        if not result:
            return Response(
                {"error": {"code": "not_found", "message": "چشم‌انداز یافت نشد"}},
                status=status.HTTP_404_NOT_FOUND,
            )

        return Response({"data": VisionDetailSerializer(
            VisionModel.objects.get(id=pk)
        ).data})

    @action(detail=True, methods=["get"], url_path="themes")
    def themes(self, request, pk=None):
        """لیست تم‌های راهبردی مرتبط با یک چشم‌انداز."""
        themes = StrategicThemeModel.objects.filter(vision_id=pk)
        serializer = StrategicThemeListSerializer(themes, many=True)
        return Response({"data": serializer.data})


# ═══════════════════════════════════════════════════
# StrategicTheme ViewSet
# ═══════════════════════════════════════════════════

class StrategicThemeViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """CRUD + activate/complete/archive برای تم راهبردی."""
    queryset = StrategicThemeModel.objects.select_related("vision").all()
    permission_classes = [IsAuthenticated, StrategicThemePermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["name", "description"]
    filterset_fields = ["status", "priority", "vision"]
    ordering_fields = ["name", "sort_order", "created_at"]
    ordering = ["sort_order", "-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return StrategicThemeListSerializer
        if self.action in ("create", "update", "partial_update"):
            return StrategicThemeCreateSerializer
        if self.action == "change_status":
            return ThemeStatusSerializer
        return StrategicThemeDetailSerializer

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        serializer = ThemeStatusSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        svc = StrategicThemeService()
        action_name = serializer.validated_data["action"]

        if action_name == "activate":
            result = svc.activate(pk)
        elif action_name == "complete":
            result = svc.complete(pk)
        elif action_name == "archive":
            result = svc.archive(pk)
        else:
            return Response(
                {"error": {"code": "invalid_action", "message": "عملیات نامعتبر"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        if not result:
            return Response(
                {"error": {"code": "not_found", "message": "تم راهبردی یافت نشد"}},
                status=status.HTTP_404_NOT_FOUND,
            )

        return Response({"data": StrategicThemeDetailSerializer(
            StrategicThemeModel.objects.select_related("vision").get(id=pk)
        ).data})


# ═══════════════════════════════════════════════════
# Objective ViewSet
# ═══════════════════════════════════════════════════

class ObjectiveViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """CRUD + status transitions + progress analysis برای اهداف."""
    queryset = ObjectiveModel.objects.select_related("theme", "parent").all()
    permission_classes = [IsAuthenticated, ObjectivePermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["title", "description"]
    filterset_fields = ["status", "level", "time_frame", "theme", "parent"]
    ordering_fields = ["title", "progress", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return ObjectiveListSerializer
        if self.action in ("create", "update", "partial_update"):
            return ObjectiveCreateSerializer
        if self.action == "change_status":
            return ObjectiveStatusSerializer
        return ObjectiveDetailSerializer

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        serializer = ObjectiveStatusSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        svc = OKRService()
        action_name = serializer.validated_data["action"]

        action_map = {
            "activate": svc.activate_objective,
            "achieve": svc.achieve_objective,
            "miss": svc.miss_objective,
            "at_risk": lambda pk: svc.objective_repo.find_by_id(pk) and self._mark_at_risk(svc, pk),
        }

        handler = action_map.get(action_name)
        if not handler:
            return Response(
                {"error": {"code": "invalid_action", "message": "عملیات نامعتبر"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        if action_name == "at_risk":
            result = self._mark_at_risk(svc, pk)
        else:
            result = handler(pk)

        if not result:
            return Response(
                {"error": {"code": "not_found", "message": "هدف یافت نشد"}},
                status=status.HTTP_404_NOT_FOUND,
            )

        return Response({"data": ObjectiveDetailSerializer(
            ObjectiveModel.objects.select_related("theme", "parent").get(id=pk)
        ).data})

    @staticmethod
    def _mark_at_risk(svc, objective_id):
        entity = svc.objective_repo.find_by_id(objective_id)
        if not entity:
            return None
        entity.mark_at_risk()
        saved = svc.objective_repo.save(entity)
        return saved

    @action(detail=True, methods=["get"], url_path="key-results")
    def key_results(self, request, pk=None):
        """List key results for an objective."""
        krs = KeyResultModel.objects.filter(objective_id=pk).select_related("objective")
        serializer = KeyResultListSerializer(krs, many=True)
        return Response({"data": serializer.data})

    @action(detail=True, methods=["get"], url_path="children")
    def children(self, request, pk=None):
        """List child objectives."""
        children = ObjectiveModel.objects.filter(parent_id=pk).select_related("theme")
        serializer = ObjectiveListSerializer(children, many=True)
        return Response({"data": serializer.data})

    @action(detail=True, methods=["get"], url_path="progress")
    def progress(self, request, pk=None):
        """محاسبه پیشرفت هدف."""
        svc = OKRService()
        result = svc.calculate_progress(pk)
        if not result:
            return Response(
                {"error": {"code": "not_found", "message": "هدف یافت نشد"}},
                status=status.HTTP_404_NOT_FOUND,
            )
        serializer = ObjectiveProgressSerializer(result)
        return Response({"data": serializer.data})

    @action(detail=True, methods=["get"], url_path="cascade")
    def cascade(self, request, pk=None):
        """محاسبه پیشرفت آبشاری."""
        svc = OKRService()
        result = svc.calculate_cascade(pk)
        if not result:
            return Response(
                {"error": {"code": "not_found", "message": "هدف یافت نشد"}},
                status=status.HTTP_404_NOT_FOUND,
            )
        serializer = CascadeProgressSerializer(result)
        return Response({"data": serializer.data})


# ═══════════════════════════════════════════════════
# KeyResult ViewSet
# ═══════════════════════════════════════════════════

class KeyResultViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """CRUD برای نتایج کلیدی."""
    queryset = KeyResultModel.objects.select_related("objective").all()
    permission_classes = [IsAuthenticated, KeyResultPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["title"]
    filterset_fields = ["status", "metric_type", "objective"]
    ordering_fields = ["title", "current_value", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return KeyResultListSerializer
        if self.action in ("create", "update", "partial_update"):
            return KeyResultCreateSerializer
        return KeyResultDetailSerializer

    @action(detail=True, methods=["get"], url_path="check-ins")
    def check_ins(self, request, pk=None):
        """لیست ثبت‌های پیشرفت یک نتیجه کلیدی."""
        checkins = KeyResultCheckInModel.objects.filter(key_result_id=pk)
        serializer = CheckInListSerializer(checkins, many=True)
        return Response({"data": serializer.data})

    @action(detail=True, methods=["post"], url_path="record-check-in")
    def record_check_in(self, request, pk=None):
        """ثبت پیشرفت جدید."""
        data = request.data.copy()
        data["key_result"] = pk
        serializer = CheckInCreateSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save(
            checked_by=request.user,
            **({
                "tenant": request.tenant
            } if hasattr(request, "tenant") else {}),
        )

        # Trigger progress recalculation
        from ...application.services.okr_service import OKRService
        svc = OKRService()
        kr = svc.kr_repo.find_by_id(pk)
        if kr:
            kr.update_value(serializer.validated_data["value"])
            svc.kr_repo.save(kr)
            svc._recalculate_objective_progress(kr.objective_id)

        return Response(
            {"data": CheckInListSerializer(serializer.instance).data},
            status=status.HTTP_201_CREATED,
        )


# ═══════════════════════════════════════════════════
# CheckIn ViewSet
# ═══════════════════════════════════════════════════

class CheckInViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """ثبت‌های پیشرفت."""
    queryset = KeyResultCheckInModel.objects.select_related("key_result").all()
    permission_classes = [IsAuthenticated, CheckInPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["key_result", "confidence"]
    ordering_fields = ["check_date", "created_at"]
    ordering = ["-check_date"]

    def get_serializer_class(self):
        if self.action in ("create",):
            return CheckInCreateSerializer
        return CheckInListSerializer

    def perform_create(self, serializer):
        kwargs = {"checked_by": self.request.user}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# KPI Definition ViewSet
# ═══════════════════════════════════════════════════

class KPIDefinitionViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """شاخص‌های کلیدی عملکرد."""
    queryset = KPIDefinitionModel.objects.select_related("owner").all()
    permission_classes = [IsAuthenticated, KPIDefinitionPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["status", "direction", "frequency", "data_source", "category"]
    search_fields = ["name", "code", "description"]
    ordering_fields = ["name", "code", "created_at"]
    ordering = ["name"]

    def get_serializer_class(self):
        if self.action == "list":
            return KPIDefinitionListSerializer
        if self.action in ("create", "update", "partial_update"):
            return KPIDefinitionCreateSerializer
        return KPIDefinitionDetailSerializer

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        ser = KPIStatusSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        svc = KPIService()
        new_status = ser.validated_data["status"]
        if new_status == "active":
            result = svc.activate_kpi(pk)
        elif new_status == "archived":
            result = svc.archive_kpi(pk)
        else:
            return Response({"error": {"message": "وضعیت نامعتبر"}}, status=status.HTTP_400_BAD_REQUEST)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        return Response({"data": {"status": new_status}})

    @action(detail=True, methods=["get"], url_path="targets")
    def targets(self, request, pk=None):
        qs = KPITargetModel.objects.filter(kpi_id=pk)
        ser = KPITargetListSerializer(qs, many=True)
        return Response({"data": ser.data})

    @action(detail=True, methods=["get"], url_path="actuals")
    def actuals(self, request, pk=None):
        qs = KPIActualModel.objects.filter(kpi_id=pk)
        ser = KPIActualListSerializer(qs, many=True)
        return Response({"data": ser.data})

    @action(detail=True, methods=["get"], url_path="assignments")
    def assignments(self, request, pk=None):
        qs = KPIAssignmentModel.objects.filter(kpi_id=pk)
        ser = KPIAssignmentListSerializer(qs, many=True)
        return Response({"data": ser.data})

    @action(detail=True, methods=["get"], url_path="score")
    def score(self, request, pk=None):
        svc = KPIService()
        result = svc.calculate_score(pk)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        ser = KPIScoreSerializer(result.__dict__)
        return Response({"data": ser.data})

    @action(detail=True, methods=["get"], url_path="trend")
    def trend(self, request, pk=None):
        svc = KPIService()
        result = svc.calculate_trend(pk)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        ser = KPITrendSerializer(result.__dict__)
        return Response({"data": ser.data})


# ═══════════════════════════════════════════════════
# KPI Target ViewSet
# ═══════════════════════════════════════════════════

class KPITargetViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """هدف‌گذاری KPI."""
    queryset = KPITargetModel.objects.select_related("kpi").all()
    permission_classes = [IsAuthenticated, KPITargetPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["kpi"]
    ordering_fields = ["period_start", "created_at"]
    ordering = ["-period_start"]

    def get_serializer_class(self):
        if self.action == "list":
            return KPITargetListSerializer
        if self.action in ("create", "update", "partial_update"):
            return KPITargetCreateSerializer
        return KPITargetDetailSerializer


# ═══════════════════════════════════════════════════
# KPI Actual ViewSet
# ═══════════════════════════════════════════════════

class KPIActualViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """مقادیر واقعی KPI."""
    queryset = KPIActualModel.objects.select_related("kpi", "recorded_by").all()
    permission_classes = [IsAuthenticated, KPIActualPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["kpi", "source"]
    ordering_fields = ["period_start", "created_at"]
    ordering = ["-period_start"]

    def get_serializer_class(self):
        if self.action == "list":
            return KPIActualListSerializer
        if self.action in ("create", "update", "partial_update"):
            return KPIActualCreateSerializer
        return KPIActualDetailSerializer

    def perform_create(self, serializer):
        kwargs = {"recorded_by": self.request.user}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# KPI Assignment ViewSet
# ═══════════════════════════════════════════════════

class KPIAssignmentViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """تخصیص KPI."""
    queryset = KPIAssignmentModel.objects.select_related("kpi").all()
    permission_classes = [IsAuthenticated, KPIAssignmentPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["kpi", "level", "status"]
    ordering_fields = ["level", "created_at"]
    ordering = ["level"]

    def get_serializer_class(self):
        if self.action == "list":
            return KPIAssignmentListSerializer
        if self.action in ("create", "update", "partial_update"):
            return KPIAssignmentCreateSerializer
        return KPIAssignmentDetailSerializer

    @action(detail=True, methods=["post"], url_path="deactivate")
    def deactivate(self, request, pk=None):
        svc = KPIService()
        result = svc.deactivate_assignment(pk)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        return Response({"data": {"status": "inactive"}})


# ═══════════════════════════════════════════════════
# Strategy Map ViewSet
# ═══════════════════════════════════════════════════

class StrategyMapViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """نقشه راهبردی."""
    queryset = StrategyMapModel.objects.all()
    permission_classes = [IsAuthenticated, StrategyMapPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["name"]
    filterset_fields = ["status"]
    ordering_fields = ["name", "version", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return StrategyMapListSerializer
        if self.action in ("create", "update", "partial_update"):
            return StrategyMapCreateSerializer
        if self.action == "change_status":
            return StrategyMapStatusSerializer
        return StrategyMapDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        ser = StrategyMapStatusSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        new_status = ser.validated_data["status"]
        svc = StrategyMapService()
        if new_status == "published":
            result = svc.publish_map(pk)
        elif new_status == "archived":
            result = svc.archive_map(pk)
        else:
            obj = self.get_object()
            obj.status = new_status
            obj.save()
            return Response({"data": StrategyMapDetailSerializer(obj).data})
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        return Response({"data": {"status": new_status}})

    @action(detail=True, methods=["post"], url_path="new-version")
    def new_version(self, request, pk=None):
        svc = StrategyMapService()
        result = svc.new_version(pk)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        return Response({"data": {"version": result.version}})


# ═══════════════════════════════════════════════════
# Map Perspective ViewSet
# ═══════════════════════════════════════════════════

class MapPerspectiveViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """دیدگاه‌های نقشه راهبردی."""
    queryset = StrategyMapPerspectiveModel.objects.select_related("strategy_map").all()
    permission_classes = [IsAuthenticated, MapPerspectivePermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["strategy_map"]
    ordering_fields = ["sort_order", "name", "created_at"]
    ordering = ["sort_order"]

    def get_serializer_class(self):
        if self.action == "list":
            return PerspectiveListSerializer
        if self.action in ("create", "update", "partial_update"):
            return PerspectiveCreateSerializer
        return PerspectiveDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Map Objective ViewSet
# ═══════════════════════════════════════════════════

class MapObjectiveViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """اهداف روی نقشه راهبردی."""
    queryset = StrategyMapObjectiveModel.objects.select_related(
        "strategy_map", "perspective", "objective",
    ).all()
    permission_classes = [IsAuthenticated, MapObjectivePermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["strategy_map", "perspective"]
    ordering_fields = ["created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return MapObjectiveListSerializer
        if self.action in ("create", "update", "partial_update"):
            return MapObjectiveCreateSerializer
        return MapObjectiveDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Causal Link ViewSet
# ═══════════════════════════════════════════════════

class CausalLinkViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """ارتباطات علّی نقشه راهبردی."""
    queryset = CausalLinkModel.objects.select_related(
        "strategy_map", "from_objective", "to_objective",
    ).all()
    permission_classes = [IsAuthenticated, CausalLinkPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["strategy_map", "strength"]
    ordering_fields = ["created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return CausalLinkListSerializer
        if self.action in ("create", "update", "partial_update"):
            return CausalLinkCreateSerializer
        return CausalLinkDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Scorecard ViewSet
# ═══════════════════════════════════════════════════

class ScorecardViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """کارت امتیازی متوازن."""
    queryset = ScorecardModel.objects.select_related("owner").all()
    permission_classes = [IsAuthenticated, ScorecardPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["name"]
    filterset_fields = ["status"]
    ordering_fields = ["name", "period_start", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return ScorecardListSerializer
        if self.action in ("create", "update", "partial_update"):
            return ScorecardCreateSerializer
        if self.action == "change_status":
            return ScorecardStatusSerializer
        if self.action == "report":
            return ScorecardReportSerializer
        return ScorecardDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        ser = ScorecardStatusSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        new_status = ser.validated_data["status"]
        svc = ScorecardService()
        action_map = {
            "active": svc.activate_scorecard,
            "closed": svc.close_scorecard,
            "archived": svc.archive_scorecard,
        }
        fn = action_map.get(new_status)
        if fn:
            result = fn(pk)
        else:
            obj = self.get_object()
            obj.status = new_status
            obj.save()
            return Response({"data": ScorecardDetailSerializer(obj).data})
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        return Response({"data": {"status": new_status}})

    @action(detail=True, methods=["get"], url_path="report")
    def report(self, request, pk=None):
        svc = ScorecardService()
        result = svc.generate_report(pk)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        from ..v1.serializers import ScorecardReportSerializer as ReportSer
        return Response({"data": ReportSer(result).data})


# ═══════════════════════════════════════════════════
# Scorecard Perspective ViewSet
# ═══════════════════════════════════════════════════

class ScPerspectiveViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """دیدگاه‌های کارت امتیازی."""
    queryset = ScorecardPerspectiveModel.objects.select_related("scorecard").all()
    permission_classes = [IsAuthenticated, ScPerspectivePermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["scorecard"]
    ordering_fields = ["sort_order", "name", "created_at"]
    ordering = ["sort_order"]

    def get_serializer_class(self):
        if self.action == "list":
            return ScPerspectiveListSerializer
        if self.action in ("create", "update", "partial_update"):
            return ScPerspectiveCreateSerializer
        return ScPerspectiveDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Scorecard Measure ViewSet
# ═══════════════════════════════════════════════════

class ScMeasureViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """سنجه‌های کارت امتیازی."""
    queryset = ScorecardMeasureModel.objects.select_related(
        "perspective", "kpi_assignment",
    ).all()
    permission_classes = [IsAuthenticated, ScMeasurePermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["perspective", "status"]
    ordering_fields = ["created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return ScMeasureListSerializer
        if self.action in ("create", "update", "partial_update"):
            return ScMeasureCreateSerializer
        return ScMeasureDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Stage-Gate Governance ViewSets
# ═══════════════════════════════════════════════════

class GateProcessViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """فرآیندهای Stage-Gate."""
    queryset = GateProcessModel.objects.all()
    permission_classes = [IsAuthenticated, GateProcessPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["name"]
    filterset_fields = ["applicable_to", "is_active"]
    ordering_fields = ["name", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return GateProcessListSerializer
        if self.action in ("create", "update", "partial_update"):
            return GateProcessCreateSerializer
        return GateProcessDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


class GateViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """دروازه‌های Stage-Gate."""
    queryset = GateModel.objects.select_related("process").all()
    permission_classes = [IsAuthenticated, GatePermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["process"]
    ordering_fields = ["sequence", "name", "created_at"]
    ordering = ["sequence"]

    def get_serializer_class(self):
        if self.action == "list":
            return GateListSerializer
        if self.action in ("create", "update", "partial_update"):
            return GateCreateSerializer
        return GateDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


class GateReviewViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """بازبینی‌های دروازه."""
    queryset = GateReviewModel.objects.select_related("gate").all()
    permission_classes = [IsAuthenticated, GateReviewPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["gate", "status", "entity_type"]
    ordering_fields = ["review_date", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return GateReviewListSerializer
        if self.action in ("create", "update", "partial_update"):
            return GateReviewCreateSerializer
        if self.action == "change_status":
            return GateReviewStatusSerializer
        return GateReviewDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        ser = GateReviewStatusSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        act = ser.validated_data["action"]
        svc = StageGateService()
        action_map = {
            "start": svc.start_review,
            "approve": svc.approve_review,
            "conditional": svc.approve_conditional,
            "reject": svc.reject_review,
        }
        fn = action_map.get(act)
        if not fn:
            return Response({"error": {"message": "عملیات نامعتبر"}}, status=status.HTTP_400_BAD_REQUEST)
        result = fn(pk)
        if not result:
            return Response({"error": {"message": "یافت نشد"}}, status=status.HTTP_404_NOT_FOUND)
        return Response({"data": {"status": result.status}})


class GateReviewerViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """بازبینان دروازه."""
    queryset = GateReviewerModel.objects.select_related("review", "user").all()
    permission_classes = [IsAuthenticated, GateReviewerPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["review", "decision"]
    ordering_fields = ["created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return GateReviewerListSerializer
        if self.action in ("create", "update", "partial_update"):
            return GateReviewerCreateSerializer
        return GateReviewerDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


class GateDeliverableViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """تحویل‌دادنی‌های دروازه."""
    queryset = GateDeliverableModel.objects.select_related("review").all()
    permission_classes = [IsAuthenticated, GateDeliverablePermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["review", "status"]
    ordering_fields = ["created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return GateDeliverableListSerializer
        if self.action in ("create", "update", "partial_update"):
            return GateDeliverableCreateSerializer
        return GateDeliverableDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Corporate Policy Management ViewSets
# ═══════════════════════════════════════════════════

class PolicyViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """سیاست‌های سازمانی."""
    queryset = PolicyModel.objects.select_related("owner", "approver").all()
    permission_classes = [IsAuthenticated, PolicyPermission]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["status", "category"]
    search_fields = ["title", "code"]
    ordering_fields = ["created_at", "effective_date"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return PolicyListSerializer
        if self.action in ("create", "update", "partial_update"):
            return PolicyCreateSerializer
        if self.action == "change_status":
            return PolicyStatusSerializer
        return PolicyDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)

    @action(detail=True, methods=["post"], url_path="change-status")
    def change_status(self, request, pk=None):
        """تغییر وضعیت سیاست (active / under_review / retired)."""
        serializer = PolicyStatusSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        new_status = serializer.validated_data["status"]
        from ...application.services.policy_service import PolicyService
        svc = PolicyService()
        if new_status == "active":
            result = svc.activate_policy(pk)
        elif new_status == "under_review":
            result = svc.submit_for_review(pk)
        elif new_status == "retired":
            result = svc.retire_policy(pk)
        else:
            return Response({"error": "Invalid status"}, status=status.HTTP_400_BAD_REQUEST)
        if result is None:
            return Response({"error": "Policy not found"}, status=status.HTTP_404_NOT_FOUND)
        return Response(PolicyDetailSerializer(PolicyModel.objects.get(id=pk)).data)


class PolicyAcknowledgmentViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """تأیید آشنایی با سیاست."""
    queryset = PolicyAcknowledgmentModel.objects.select_related("policy", "user").all()
    permission_classes = [IsAuthenticated, PolicyAcknowledgmentPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["policy", "user"]
    ordering_fields = ["acknowledged_at", "created_at"]
    ordering = ["-acknowledged_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return PolicyAckListSerializer
        if self.action in ("create", "update", "partial_update"):
            return PolicyAckCreateSerializer
        return PolicyAckDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# Alignment ViewSet
# ═══════════════════════════════════════════════════

class ObjectiveAlignmentViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """همراستایی Objective ↔ Portfolio."""
    queryset = ObjectivePortfolioAlignmentModel.objects.select_related("objective").all()
    permission_classes = [IsAuthenticated, AlignmentPermission]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["objective", "portfolio_id", "alignment_level", "is_active"]
    ordering_fields = ["strategic_fit_score", "created_at"]
    ordering = ["-strategic_fit_score"]

    def get_serializer_class(self):
        if self.action == "list":
            return AlignmentListSerializer
        if self.action in ("create", "update", "partial_update"):
            return AlignmentCreateSerializer
        return AlignmentDetailSerializer

    def perform_create(self, serializer):
        kwargs = {}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)

    @action(detail=False, methods=["get"], url_path="strategic-fit")
    def strategic_fit(self, request):
        """محاسبه امتیاز تناسب استراتژیک یک پورتفولیو."""
        portfolio_id = request.query_params.get("portfolio_id")
        if not portfolio_id:
            return Response(
                {"error": {"message": "پارامتر portfolio_id الزامی است."}},
                status=status.HTTP_400_BAD_REQUEST,
            )
        alignments = self.get_queryset().filter(
            portfolio_id=portfolio_id, is_active=True,
        )
        details = []
        total_weighted_score = 0
        total_weight = 0
        for a in alignments:
            total_weighted_score += float(a.strategic_fit_score) * float(a.weight)
            total_weight += float(a.weight)
            details.append({
                "objective_id": str(a.objective_id),
                "objective_title": a.objective.title if a.objective else "",
                "alignment_level": a.alignment_level,
                "score": float(a.strategic_fit_score),
                "weight": float(a.weight),
            })
        total_score = total_weighted_score / total_weight if total_weight else 0
        return Response({"data": {
            "portfolio_id": portfolio_id,
            "total_score": round(total_score, 2),
            "aligned_objectives_count": len(details),
            "alignment_details": details,
        }})

    @action(detail=False, methods=["get"], url_path="heatmap")
    def alignment_heatmap(self, request):
        """هیتمپ همراستایی استراتژیک (Objectives × Portfolios)."""
        from django.db.models import Avg, Count

        qs = self.get_queryset().filter(is_active=True)
        summary = qs.values("portfolio_id").annotate(
            avg_score=Avg("strategic_fit_score"),
            obj_count=Count("id"),
        ).order_by("-avg_score")
        return Response({"data": list(summary)})
