"""GraphQL types, queries, and mutations for billing app."""

import strawberry
from strawberry import ID
from strawberry.types import Info

from accounts.models import WorkspaceMembership
from core.graphql.enums import SubscriptionStatus

from .models import Plan, Subscription


@strawberry.type
class PlanType:
    """GraphQL type for Plan model."""

    id: ID
    name: str
    price_cents: int
    currency: str
    is_active: bool
    description: str
    features: strawberry.scalars.JSON
    created_at: str
    updated_at: str

    @strawberry.field
    def price(self) -> float:
        """Get the price in major currency units."""
        return self.price_cents / 100

    @classmethod
    def from_model(cls, plan: Plan) -> "PlanType":
        return cls(
            id=ID(str(plan.pk)),
            name=plan.name,
            price_cents=plan.price_cents,
            currency=plan.currency,
            is_active=plan.is_active,
            description=plan.description or "",
            features=plan.features or [],
            created_at=plan.created_at.isoformat() if plan.created_at else "",
            updated_at=plan.updated_at.isoformat() if plan.updated_at else "",
        )


@strawberry.type
class SubscriptionType:
    """GraphQL type for Subscription model."""

    id: ID
    status: SubscriptionStatus
    current_period_end: str | None
    created_at: str
    updated_at: str
    workspace_id: ID
    plan_id: ID

    @strawberry.field
    def plan(self, info: Info) -> PlanType:
        """Get the plan for this subscription."""
        subscription = Subscription.objects.select_related("plan").get(pk=self.id)
        return PlanType.from_model(subscription.plan)

    @classmethod
    def from_model(cls, subscription: Subscription) -> "SubscriptionType":
        return cls(
            id=ID(str(subscription.pk)),
            status=SubscriptionStatus(subscription.status),
            current_period_end=subscription.current_period_end.isoformat() if subscription.current_period_end else None,
            created_at=subscription.created_at.isoformat() if subscription.created_at else "",
            updated_at=subscription.updated_at.isoformat() if subscription.updated_at else "",
            workspace_id=ID(str(subscription.workspace_id)),
            plan_id=ID(str(subscription.plan_id)),
        )


@strawberry.type
class BillingQuery:
    """Queries for billing app."""

    @strawberry.field
    def plans(self, info: Info, active_only: bool = True) -> list[PlanType]:
        """Get all available plans."""
        plans = Plan.objects.all()
        if active_only:
            plans = plans.filter(is_active=True)
        return [PlanType.from_model(p) for p in plans]

    @strawberry.field
    def plan(self, info: Info, id: ID) -> PlanType | None:
        """Get a specific plan by ID."""
        try:
            plan = Plan.objects.get(pk=id)
            return PlanType.from_model(plan)
        except Plan.DoesNotExist:
            return None

    @strawberry.field
    def subscriptions(self, info: Info, workspace_id: ID) -> list[SubscriptionType]:
        """Get all subscriptions for a workspace."""
        user = info.context.user
        if not user or not user.is_authenticated:
            return []

        has_access = WorkspaceMembership.objects.filter(user=user, workspace_id=workspace_id).exists()
        if not has_access:
            return []

        subscriptions = Subscription.objects.filter(workspace_id=workspace_id)
        return [SubscriptionType.from_model(s) for s in subscriptions]

    @strawberry.field
    def subscription(self, info: Info, id: ID) -> SubscriptionType | None:
        """Get a specific subscription by ID."""
        user = info.context.user
        if not user or not user.is_authenticated:
            return None

        try:
            subscription = Subscription.objects.get(pk=id)
        except Subscription.DoesNotExist:
            return None

        has_access = WorkspaceMembership.objects.filter(user=user, workspace=subscription.workspace).exists()
        if not has_access:
            return None

        return SubscriptionType.from_model(subscription)
