"""Manager dashboard summary. Every figure is included only when the caller holds the matching
permission at organization scope AND the module is enabled, so the page never leaks counts."""
from __future__ import annotations

import datetime

from django.contrib.auth import get_user_model
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.access.drf import TenantPermission
from apps.crm.models import Customer
from apps.modules.models import ModuleRequest
from apps.organizations.models import Organization, OrganizationMembership
from apps.tasks.models import Task
from infrastructure.models import Attendance, Holiday, LeaveRequest


def _allowed(ctx, module: str | None, permission: str) -> bool:
    return (module is None or module in ctx.enabled_modules) and ctx.has(permission, "organization")


class DashboardSummaryView(APIView):
    permission_classes = [TenantPermission]
    permission_map = {"GET": "members.view"}
    scope_map = {"GET": "organization"}

    def get(self, request):
        ctx, org = request.tenant, request.organization
        today = datetime.date.today()
        data: dict = {"date": today.isoformat()}

        if org.is_platform:  # the super admin's dashboard: the whole system, not one organization
            customers = Organization.objects.filter(kind=Organization.Kind.CUSTOMER)
            accounts = get_user_model().objects.all()
            data["platform"] = {
                "organizations": {"total": customers.count(), "active": customers.filter(is_active=True).count()},
                "users": {"total": accounts.count(), "active": accounts.filter(is_active=True).count()},
                "module_requests": {"pending": ModuleRequest.objects.filter(status=ModuleRequest.Status.PENDING).count()},
            }
            data["personnel"] = {"total": OrganizationMembership.objects.filter(organization=org, status="active").count()}
            return Response(data)

        members = OrganizationMembership.objects.filter(organization=org, status="active").select_related("user")
        data["personnel"] = {"total": members.count()}

        if _allowed(ctx, "crm", "crm.view"):
            customers = Customer.objects.filter(organization=org)
            data["customers"] = {"total": customers.count(), "active": customers.filter(status="active").count(),
                                 "leads": customers.filter(status="lead").count()}

        if _allowed(ctx, "tasks", "tasks.view"):
            tasks = Task.objects.filter(organization=org)
            data["tasks"] = {"in_progress": tasks.filter(status="in_progress").count(),
                             "todo": tasks.filter(status="todo").count(),
                             "review": tasks.filter(status="review").count(),
                             "overdue": tasks.exclude(status="done").filter(due_date__lt=today).count()}

        if _allowed(ctx, "attendance", "attendance.report"):
            user_ids = [m.user_id for m in members]
            records = {a.user_id: a for a in Attendance.objects.filter(organization=org, date=today, user_id__in=user_ids)}
            on_leave_ids = set(
                LeaveRequest.objects.filter(
                    organization=org, date=today, status="approved", type="daily", user_id__in=user_ids
                ).values_list("user_id", flat=True)
            )
            holiday = Holiday.objects.filter(organization=org, date=today).first()
            present = [uid for uid in user_ids if uid in records and records[uid].check_in]
            finished = [uid for uid in present if records[uid].check_out and not records[uid].is_default_checkout]
            absent = [m for m in members if m.user_id not in records and m.user_id not in on_leave_ids]
            data["attendance"] = {
                "is_holiday": holiday is not None,
                "holiday_title": holiday.title if holiday else None,
                "present": len(present),
                "finished": len(finished),
                "on_leave": len(on_leave_ids),
                "not_arrived": 0 if holiday else len(absent),
                "not_arrived_names": [] if holiday else [m.user.name or m.user.username or "" for m in absent][:30],
            }
        return Response(data)
