"""
Analytics Service — Views.
"""
from decimal import Decimal

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 rest_framework.views import APIView
from django_filters.rest_framework import DjangoFilterBackend

from .models import (
    AggregationDefinition, AggregationSnapshot,
    KPIRollup,
    ReportTemplate, GeneratedReport,
)
from .serializers import (
    AggregationDefinitionListSerializer,
    AggregationDefinitionDetailSerializer,
    AggregationDefinitionCreateSerializer,
    AggregationSnapshotListSerializer,
    AggregationSnapshotDetailSerializer,
    KPIRollupListSerializer,
    KPIRollupDetailSerializer,
    ReportTemplateListSerializer,
    ReportTemplateDetailSerializer,
    ReportTemplateCreateSerializer,
    GeneratedReportListSerializer,
    GeneratedReportDetailSerializer,
    GeneratedReportCreateSerializer,
    ExecutiveSummarySerializer,
    PortfolioHealthSerializer,
    RiskHeatmapItemSerializer,
    StrategyAlignmentSerializer,
)


class TenantFilterMixin:
    """فیلتر خودکار بر اساس tenant."""
    def get_queryset(self):
        qs = super().get_queryset()
        if hasattr(self.request, "tenant"):
            qs = qs.filter(tenant=self.request.tenant)
        return qs


# ─── Aggregation Definition ──────────────────────

class AggregationDefinitionViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """تعریف‌های تجمیع داده."""
    queryset = AggregationDefinition.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["source_module", "aggregation_type", "is_active"]
    search_fields = ["name", "source_entity"]
    ordering_fields = ["created_at", "name"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return AggregationDefinitionListSerializer
        if self.action in ("create", "update", "partial_update"):
            return AggregationDefinitionCreateSerializer
        return AggregationDefinitionDetailSerializer

    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="take-snapshot")
    def take_snapshot(self, request, pk=None):
        """اجرای فوری اسنپ‌شات."""
        definition = self.get_object()
        from .services import SnapshotEngine
        engine = SnapshotEngine()
        snapshot = engine.take_snapshot(definition)
        return Response(
            AggregationSnapshotDetailSerializer(snapshot).data,
            status=status.HTTP_201_CREATED,
        )


# ─── Aggregation Snapshot ────────────────────────

class AggregationSnapshotViewSet(TenantFilterMixin, viewsets.ReadOnlyModelViewSet):
    """اسنپ‌شات‌های تجمیع (فقط‌خواندنی)."""
    queryset = AggregationSnapshot.objects.select_related("definition").all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["definition", "snapshot_date"]
    ordering_fields = ["snapshot_date", "created_at"]
    ordering = ["-snapshot_date"]

    def get_serializer_class(self):
        if self.action == "list":
            return AggregationSnapshotListSerializer
        return AggregationSnapshotDetailSerializer


# ─── KPI Rollup ─────────────────────────────────

class KPIRollupViewSet(TenantFilterMixin, viewsets.ReadOnlyModelViewSet):
    """تجمیع‌های KPI (فقط‌خواندنی)."""
    queryset = KPIRollup.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["kpi_code", "level", "period", "trend"]
    ordering_fields = ["period", "value", "created_at"]
    ordering = ["-period"]

    def get_serializer_class(self):
        if self.action == "list":
            return KPIRollupListSerializer
        return KPIRollupDetailSerializer


# ─── Report Template ────────────────────────────

class ReportTemplateViewSet(TenantFilterMixin, viewsets.ModelViewSet):
    """قالب‌های گزارش."""
    queryset = ReportTemplate.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["is_active", "default_format", "is_scheduled"]
    search_fields = ["name"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return ReportTemplateListSerializer
        if self.action in ("create", "update", "partial_update"):
            return ReportTemplateCreateSerializer
        return ReportTemplateDetailSerializer

    def perform_create(self, serializer):
        kwargs = {"owner": self.request.user}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)

    @action(detail=True, methods=["post"], url_path="generate")
    def generate_report(self, request, pk=None):
        """تولید فوری گزارش از قالب."""
        template = self.get_object()
        format_ = request.data.get("format", template.default_format)
        parameters = request.data.get("parameters", {})

        report = GeneratedReport.objects.create(
            tenant=template.tenant,
            template=template,
            title=f"{template.name} — {request.user}",
            parameters=parameters,
            format=format_,
            generated_by=request.user,
        )

        from .tasks import generate_report_task
        generate_report_task.delay(str(report.id))

        return Response(
            GeneratedReportDetailSerializer(report).data,
            status=status.HTTP_202_ACCEPTED,
        )


# ─── Generated Report ───────────────────────────

class GeneratedReportViewSet(TenantFilterMixin, viewsets.ReadOnlyModelViewSet):
    """گزارش‌های تولیدشده (فقط‌خواندنی)."""
    queryset = GeneratedReport.objects.select_related("template", "generated_by").all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["template", "format", "status"]
    ordering_fields = ["generated_at", "created_at"]
    ordering = ["-generated_at"]

    def get_serializer_class(self):
        if self.action == "list":
            return GeneratedReportListSerializer
        return GeneratedReportDetailSerializer


# ═══════════════════════════════════════════════════
# Feature 5.2: Executive Dashboard APIs
# ═══════════════════════════════════════════════════

class ExecutiveSummaryView(APIView):
    """خلاصه اجرایی — متریک‌های سطح بالا."""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # TODO: Aggregate real data from PM, PPM, Strategy modules
        data = {
            "total_portfolios": 0,
            "total_programs": 0,
            "total_projects": 0,
            "active_kpis": 0,
            "objectives_on_track": 0,
            "objectives_at_risk": 0,
            "budget_utilization": Decimal("0.00"),
            "resource_utilization": Decimal("0.00"),
        }
        serializer = ExecutiveSummarySerializer(data)
        return Response(serializer.data)


class PortfolioHealthView(APIView):
    """وضعیت سلامت پورتفولیوها — RAG status."""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # TODO: Aggregate from PPM portfolio data
        data = []
        serializer = PortfolioHealthSerializer(data, many=True)
        return Response(serializer.data)


class ResourceUtilizationView(APIView):
    """بهره‌وری منابع — نمای سازمانی."""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # TODO: Aggregate from HRM + PM resource data
        return Response({"data": [], "summary": {}})


class FinancialOverviewView(APIView):
    """نمای مالی — بودجه vs هزینه واقعی."""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # TODO: Aggregate from PM/PPM financial data
        return Response({"data": [], "summary": {}})


class RiskHeatmapView(APIView):
    """نقشه حرارتی ریسک — تجمیع ریسک‌ها."""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # TODO: Aggregate from PM risk registry
        data = []
        serializer = RiskHeatmapItemSerializer(data, many=True)
        return Response(serializer.data)


class StrategyAlignmentView(APIView):
    """همراستایی استراتژیک — امتیاز alignment."""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # TODO: Calculate from Strategy objectives + PPM portfolio links
        data = []
        serializer = StrategyAlignmentSerializer(data, many=True)
        return Response(serializer.data)


# ═══════════════════════════════════════════════════
# Enterprise Dependency Graph (F6.4)
# ═══════════════════════════════════════════════════

class EnterpriseDependencyGraphView(APIView):
    """
    گراف وابستگی‌های سازمانی.

    تجمیع سه منبع وابستگی:
    1. PM — وابستگی‌های بین فعالیت‌ها (TaskDependency)
    2. PPM — وابستگی‌های بین پروژه‌ای (CrossProjectDependency)
    3. Strategy — روابط علّی نقشه راهبرد (CausalLink)

    خروجی: گراف nodes + edges برای رندر frontend.
    """
    permission_classes = [IsAuthenticated]

    def get(self, request):
        tenant = getattr(request, "tenant", None)
        scope = request.query_params.get("scope", "all")  # all, pm, ppm, strategy
        project_id = request.query_params.get("project_id")

        nodes = []
        edges = []

        if scope in ("all", "pm"):
            pm_nodes, pm_edges = self._get_pm_dependencies(tenant, project_id)
            nodes.extend(pm_nodes)
            edges.extend(pm_edges)

        if scope in ("all", "ppm"):
            ppm_nodes, ppm_edges = self._get_ppm_dependencies(tenant)
            nodes.extend(ppm_nodes)
            edges.extend(ppm_edges)

        if scope in ("all", "strategy"):
            str_nodes, str_edges = self._get_strategy_causal_links(tenant)
            nodes.extend(str_nodes)
            edges.extend(str_edges)

        return Response({
            "data": {
                "nodes": nodes,
                "edges": edges,
                "summary": {
                    "total_nodes": len(nodes),
                    "total_edges": len(edges),
                    "modules": list({n["module"] for n in nodes}),
                },
            },
        })

    def _get_pm_dependencies(self, tenant, project_id=None):
        """استخراج وابستگی فعالیت‌ها از ماژول PM."""
        nodes, edges = [], []
        try:
            from modules.pm.backend.infrastructure.persistence.models import (
                TaskDependencyModel, TaskModel,
            )
            dep_qs = TaskDependencyModel.objects.all()
            if tenant:
                dep_qs = dep_qs.filter(tenant=tenant)
            if project_id:
                dep_qs = dep_qs.filter(
                    predecessor__project_id=project_id,
                )

            task_ids = set()
            for dep in dep_qs.select_related("predecessor", "successor"):
                for task in (dep.predecessor, dep.successor):
                    if task and str(task.id) not in task_ids:
                        task_ids.add(str(task.id))
                        nodes.append({
                            "id": str(task.id),
                            "label": task.title if hasattr(task, "title") else str(task),
                            "type": "task",
                            "module": "pm",
                            "metadata": {
                                "project_id": str(task.project_id) if hasattr(task, "project_id") else None,
                            },
                        })
                edges.append({
                    "source": str(dep.predecessor_id),
                    "target": str(dep.successor_id),
                    "type": dep.dependency_type if hasattr(dep, "dependency_type") else "FS",
                    "module": "pm",
                    "lag": dep.lag_days if hasattr(dep, "lag_days") else 0,
                })
        except Exception:
            pass
        return nodes, edges

    def _get_ppm_dependencies(self, tenant):
        """استخراج وابستگی‌های بین پروژه‌ای از ماژول PPM."""
        nodes, edges = [], []
        try:
            from modules.ppm.backend.infrastructure.persistence.models import (
                CrossProjectDependencyModel,
            )
            dep_qs = CrossProjectDependencyModel.objects.filter(status="active")
            if tenant:
                dep_qs = dep_qs.filter(tenant=tenant)

            project_ids = set()
            for dep in dep_qs:
                for pid in (str(dep.predecessor_project_id), str(dep.successor_project_id)):
                    if pid not in project_ids:
                        project_ids.add(pid)
                        nodes.append({
                            "id": pid,
                            "label": f"Project {pid[:8]}",
                            "type": "project",
                            "module": "ppm",
                            "metadata": {},
                        })
                edges.append({
                    "source": str(dep.predecessor_project_id),
                    "target": str(dep.successor_project_id),
                    "type": dep.dependency_type,
                    "module": "ppm",
                    "lag": dep.lag_days if hasattr(dep, "lag_days") else 0,
                })
        except Exception:
            pass
        return nodes, edges

    def _get_strategy_causal_links(self, tenant):
        """استخراج روابط علّی نقشه راهبرد از ماژول Strategy."""
        nodes, edges = [], []
        try:
            from modules.strategy.backend.infrastructure.persistence.models import (
                CausalLinkModel, StrategyMapObjectiveModel,
            )
            link_qs = CausalLinkModel.objects.all()
            if tenant:
                link_qs = link_qs.filter(tenant=tenant)

            obj_ids = set()
            for link in link_qs.select_related("source_objective", "target_objective"):
                for obj in (link.source_objective, link.target_objective):
                    if obj and str(obj.id) not in obj_ids:
                        obj_ids.add(str(obj.id))
                        nodes.append({
                            "id": str(obj.id),
                            "label": obj.label if hasattr(obj, "label") else str(obj),
                            "type": "strategy_objective",
                            "module": "strategy",
                            "metadata": {
                                "perspective_id": str(obj.perspective_id) if hasattr(obj, "perspective_id") else None,
                            },
                        })
                edges.append({
                    "source": str(link.source_objective_id),
                    "target": str(link.target_objective_id),
                    "type": link.link_type if hasattr(link, "link_type") else "causal",
                    "module": "strategy",
                    "strength": float(link.strength) if hasattr(link, "strength") else 1.0,
                })
        except Exception:
            pass
        return nodes, edges
