"""
Tenant Management Services — lifecycle, quota, security, monitoring.
"""
from typing import Optional, Dict, Any, List
from uuid import UUID

from django.db import transaction
from django.utils import timezone

from .models import (
    Tenant,
    Domain,
    TenantSettings,
    TenantQuotaUsage,
    TenantStatus,
    TenantType,
)


class TenantLifecycleService:
    """Handles the full tenant lifecycle: create → activate → suspend → archive."""

    @staticmethod
    @transaction.atomic
    def create_tenant(
        *,
        name: str,
        slug: str,
        schema_name: str,
        domain: str,
        legal_name: str = "",
        tenant_type: str = TenantType.COMPANY,
        subscription_plan: str = "",
        max_users: int = 10,
        max_storage_mb: int = 1024,
        country: str = "IR",
        default_language: str = "fa",
        tz: str = "Asia/Tehran",
        currency: str = "IRR",
        parent_tenant_id: Optional[UUID] = None,
    ) -> Tenant:
        """Create a new tenant with domain, settings, and quota records."""

        tenant = Tenant.objects.create(
            name=name,
            legal_name=legal_name,
            slug=slug,
            schema_name=schema_name,
            type=tenant_type,
            status=TenantStatus.PENDING,
            subscription_plan=subscription_plan,
            max_users=max_users,
            max_storage_mb=max_storage_mb,
            country=country,
            default_language=default_language,
            timezone=tz,
            currency=currency,
            parent_tenant_id=parent_tenant_id,
        )

        # Primary domain
        Domain.objects.create(
            domain=domain,
            tenant=tenant,
            is_primary=True,
        )

        # Default settings
        TenantSettings.objects.create(
            tenant=tenant,
            security_policy={
                "ip_whitelist": [],
                "enforce_2fa": False,
                "password_min_length": 8,
                "session_timeout_minutes": 30,
            },
            branding={
                "logo_url": "",
                "primary_color": "#4f46e5",
                "secondary_color": "#e000ad",
            },
        )

        # Quota tracker
        TenantQuotaUsage.objects.create(tenant=tenant)

        return tenant

    @staticmethod
    def activate_tenant(tenant_id: UUID) -> Tenant:
        tenant = Tenant.objects.get(pk=tenant_id)
        tenant.activate()
        return tenant

    @staticmethod
    def suspend_tenant(tenant_id: UUID, reason: str = "") -> Tenant:
        tenant = Tenant.objects.get(pk=tenant_id)
        tenant.suspend(reason=reason)
        return tenant

    @staticmethod
    def archive_tenant(tenant_id: UUID) -> Tenant:
        tenant = Tenant.objects.get(pk=tenant_id)
        tenant.archive()
        return tenant

    @staticmethod
    def change_plan(
        tenant_id: UUID,
        plan: str,
        max_users: Optional[int] = None,
        max_storage_mb: Optional[int] = None,
    ) -> Tenant:
        tenant = Tenant.objects.get(pk=tenant_id)
        tenant.subscription_plan = plan
        update_fields = ["subscription_plan", "updated_at"]
        if max_users is not None:
            tenant.max_users = max_users
            update_fields.append("max_users")
        if max_storage_mb is not None:
            tenant.max_storage_mb = max_storage_mb
            update_fields.append("max_storage_mb")
        tenant.save(update_fields=update_fields)
        return tenant


class TenantQuotaService:
    """Resource quota tracking and enforcement."""

    @staticmethod
    def refresh_quota(tenant_id: UUID) -> TenantQuotaUsage:
        """Recalculate resource usage for a tenant."""
        from apps.core.auth.models import User

        quota, _ = TenantQuotaUsage.objects.get_or_create(tenant_id=tenant_id)
        quota.users_count = User.objects.filter(tenant_id=tenant_id, is_active=True).count()
        quota.last_calculated_at = timezone.now()
        quota.save(
            update_fields=["users_count", "last_calculated_at", "updated_at"]
        )
        return quota

    @staticmethod
    def check_user_quota(tenant_id: UUID) -> Dict[str, Any]:
        """Return quota check result for users."""
        tenant = Tenant.objects.get(pk=tenant_id)
        quota, _ = TenantQuotaUsage.objects.get_or_create(tenant_id=tenant_id)
        return {
            "current": quota.users_count,
            "limit": tenant.max_users,
            "percent": quota.users_percent,
            "exceeded": quota.users_count >= tenant.max_users,
            "near_limit": quota.is_near_user_limit,
        }

    @staticmethod
    def check_storage_quota(tenant_id: UUID) -> Dict[str, Any]:
        tenant = Tenant.objects.get(pk=tenant_id)
        quota, _ = TenantQuotaUsage.objects.get_or_create(tenant_id=tenant_id)
        return {
            "current_mb": quota.storage_usage_mb,
            "limit_mb": tenant.max_storage_mb,
            "percent": quota.storage_percent,
            "exceeded": quota.storage_usage_mb >= tenant.max_storage_mb,
            "near_limit": quota.is_near_storage_limit,
        }


class TenantSecurityService:
    """Tenant-level security policy management."""

    @staticmethod
    def get_security_policy(tenant_id: UUID) -> Dict[str, Any]:
        settings, _ = TenantSettings.objects.get_or_create(tenant_id=tenant_id)
        return settings.security_policy or {}

    @staticmethod
    def update_security_policy(tenant_id: UUID, policy: Dict[str, Any]) -> TenantSettings:
        settings, _ = TenantSettings.objects.get_or_create(tenant_id=tenant_id)
        settings.security_policy.update(policy)
        settings.save(update_fields=["security_policy", "updated_at"])
        return settings

    @staticmethod
    def update_branding(tenant_id: UUID, branding: Dict[str, Any]) -> TenantSettings:
        settings, _ = TenantSettings.objects.get_or_create(tenant_id=tenant_id)
        settings.branding.update(branding)
        settings.save(update_fields=["branding", "updated_at"])
        return settings


class TenantMonitoringService:
    """Admin insights & health monitoring."""

    @staticmethod
    def get_tenant_health(tenant_id: UUID) -> Dict[str, Any]:
        """Quick health overview for a single tenant."""
        from apps.core.auth.models import User

        tenant = Tenant.objects.get(pk=tenant_id)
        quota, _ = TenantQuotaUsage.objects.get_or_create(tenant_id=tenant_id)

        # Last login across tenant users
        last_login = (
            User.objects.filter(tenant_id=tenant_id, last_login__isnull=False)
            .order_by("-last_login")
            .values_list("last_login", flat=True)
            .first()
        )

        active_users = User.objects.filter(tenant_id=tenant_id, is_active=True).count()

        return {
            "tenant": tenant.name,
            "status": tenant.status,
            "is_active": tenant.is_active,
            "active_users": active_users,
            "max_users": tenant.max_users,
            "last_login": last_login,
            "storage_usage_mb": quota.storage_usage_mb,
            "max_storage_mb": tenant.max_storage_mb,
            "api_calls": quota.api_calls,
            "quota_last_calculated": quota.last_calculated_at,
        }

    @staticmethod
    def get_all_tenants_overview() -> List[Dict[str, Any]]:
        """Summary for all tenants (super admin dashboard)."""
        tenants = Tenant.objects.all().order_by("-created_at")
        result = []
        for t in tenants:
            quota = getattr(t, "quota_usage", None)
            result.append(
                {
                    "id": str(t.pk),
                    "name": t.name,
                    "slug": t.slug,
                    "type": t.type,
                    "status": t.status,
                    "plan": t.subscription_plan,
                    "users": quota.users_count if quota else 0,
                    "max_users": t.max_users,
                    "created_at": t.created_at,
                }
            )
        return result
