"""Plan-driven quotas (e.g. max_projects) with internal/QA escape hatches."""
from __future__ import annotations

from typing import Optional
from uuid import UUID

from src.config import Settings, get_settings
from src.domain.admin.repository import SubscriptionPlanRepository
from src.domain.billing.constants import FREE_PLAN_SLUG, STAFF_PLAN_SLUG
from src.domain.billing.credit_policy import skips_ai_credit_limits
from src.domain.billing.repository import SubscriptionRepository
from src.domain.workspaces.repository import WorkspaceRepository


class PlanQuotaService:
    """Resolve subscription plan limits for a workspace; support quota-exempt workspaces."""

    def __init__(
        self,
        workspace_repo: WorkspaceRepository,
        subscription_repo: SubscriptionRepository,
        plan_repo: SubscriptionPlanRepository,
        settings: Optional[Settings] = None,
    ):
        self._workspace_repo = workspace_repo
        self._subscription_repo = subscription_repo
        self._plan_repo = plan_repo
        self._settings = settings or get_settings()

    async def workspace_skips_plan_quotas(self, workspace_id: UUID) -> bool:
        if str(workspace_id).lower() in self._settings.quota_exempt_workspace_id_set:
            return True
        ws = await self._workspace_repo.get_by_id(workspace_id)
        skip_flag = bool(ws and getattr(ws, "skip_plan_quota_limits", False))
        if skips_ai_credit_limits(skip_plan_quota_limits=skip_flag, plan_slug=None):
            return True
        return (await self.plan_slug(workspace_id)) == STAFF_PLAN_SLUG

    async def max_projects(self, workspace_id: UUID) -> Optional[int]:
        """None means no cap (unlimited)."""
        if await self.workspace_skips_plan_quotas(workspace_id):
            return None
        plan_slug = await self.plan_slug(workspace_id)
        plan = await self._plan_repo.get_by_slug(plan_slug)
        if not plan or not plan.limits:
            return 1 if plan_slug.lower() == FREE_PLAN_SLUG else None
        raw = plan.limits.get("max_projects")
        if raw is not None:
            return int(raw)
        return 1 if plan_slug.lower() == FREE_PLAN_SLUG else None

    async def email_included_monthly(self, workspace_id: UUID) -> int:
        """Included managed-email-domain sends per month for the workspace's plan.

        Free/no-plan workspaces get 0 — the managed email domain feature requires at least
        the basic plan's allowance; a workspace with no email_included_monthly key configured
        also gets 0 rather than unlimited, since silently uncapping a misconfigured plan is
        the wrong failure mode for a billed resource.
        """
        plan_slug = await self.plan_slug(workspace_id)
        plan = await self._plan_repo.get_by_slug(plan_slug)
        if not plan or not plan.limits:
            return 0
        return int(plan.limits.get("email_included_monthly") or 0)

    async def email_daily_cap(self, workspace_id: UUID) -> int:
        """Daily send ceiling for the workspace's plan (applies even within the monthly
        included amount — see EmailQuotaService.check_and_reserve)."""
        plan_slug = await self.plan_slug(workspace_id)
        plan = await self._plan_repo.get_by_slug(plan_slug)
        if not plan or not plan.limits:
            return 0
        return int(plan.limits.get("email_daily_cap") or 0)

    async def plan_slug(self, workspace_id: UUID) -> str:
        """Resolve the workspace plan slug for Core catalog policy."""
        plan_slug: Optional[str] = None
        ws = await self._workspace_repo.get_by_id(workspace_id)
        if ws and getattr(ws, "selected_plan_slug", None):
            plan_slug = ws.selected_plan_slug
        sub = await self._subscription_repo.get_by_workspace(workspace_id)
        if sub and getattr(sub, "plan_slug", None):
            plan_slug = sub.plan_slug
        elif sub and sub.plan_id:
            plan = await self._plan_repo.get_by_stripe_price_id(sub.plan_id)
            if plan:
                plan_slug = plan.slug
        return (plan_slug or FREE_PLAN_SLUG).lower()
