"""
Team-level GraphQL schema for Billing service.
Requires teams:member scope (verified by middleware).
Provides teamBalance and teamTransactions for the authenticated team.
"""
import graphene
import uuid
import logging
from django.db.models import Q
from graphene_django import DjangoObjectType
from graphql import GraphQLError

from ..tigerbeetle_client import tigerbeetle_client
from ..models import Account as AccountModel, Operation as OperationModel, TransactionReason as TransactionReasonModel
from ..permissions import require_scopes

logger = logging.getLogger(__name__)


class TeamBalance(graphene.ObjectType):
    """Balance information for a team's account."""
    balance = graphene.Float(required=True, description="Current balance (credits_posted - debits_posted)")
    creditsPosted = graphene.Float(required=True, description="Total credits posted to account")
    debitsPosted = graphene.Float(required=True, description="Total debits posted from account")
    exists = graphene.Boolean(required=True, description="Whether the account exists in TigerBeetle")


class TransactionReasonType(DjangoObjectType):
    class Meta:
        model = TransactionReasonModel
        fields = ('id', 'name', 'description')


class TeamTransaction(DjangoObjectType):
    """Transaction/operation involving the team's account."""
    reasonName = graphene.String()
    direction = graphene.String(description="'credit' or 'debit' relative to team account")

    class Meta:
        model = OperationModel
        fields = ('uuid', 'amount', 'state', 'created_at', 'updated_at')

    def resolve_reasonName(self, info):
        return self.reason.name if self.reason else None


class TeamQuery(graphene.ObjectType):
    teamBalance = graphene.Field(TeamBalance, description="Get balance for the authenticated team")
    teamTransactions = graphene.List(
        TeamTransaction,
        limit=graphene.Int(default_value=50),
        offset=graphene.Int(default_value=0),
        description="Get transactions for the authenticated team"
    )

    @require_scopes("teams:member")
    def resolve_teamBalance(self, info):
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            raise GraphQLError("Team UUID not found in context")

        try:
            # Convert team UUID to int for TigerBeetle lookup
            team_uuid_obj = uuid.UUID(team_uuid)
            tb_account_id = team_uuid_obj.int

            # Look up account in TigerBeetle
            accounts = tigerbeetle_client.lookup_accounts([tb_account_id])

            if not accounts:
                # Account doesn't exist yet - return zero balance
                return TeamBalance(
                    balance=0.0,
                    creditsPosted=0.0,
                    debitsPosted=0.0,
                    exists=False
                )

            account = accounts[0]
            credits_posted = float(account.credits_posted)
            debits_posted = float(account.debits_posted)
            balance = credits_posted - debits_posted

            return TeamBalance(
                balance=balance,
                creditsPosted=credits_posted,
                debitsPosted=debits_posted,
                exists=True
            )

        except ValueError as e:
            logger.error(f"Invalid team UUID format: {team_uuid} - {e}")
            raise GraphQLError("Invalid team UUID format")
        except Exception as e:
            logger.error(f"Error fetching team balance: {e}")
            raise GraphQLError("Failed to fetch team balance")

    @require_scopes("teams:member")
    def resolve_teamTransactions(self, info, limit=50, offset=0):
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            raise GraphQLError("Team UUID not found in context")

        try:
            team_uuid_obj = uuid.UUID(team_uuid)

            # Find the local account record for this team
            try:
                account = AccountModel.objects.get(uuid=team_uuid_obj)
            except AccountModel.DoesNotExist:
                # No account yet - return empty list
                return []

            # Get all operations where this account is source or destination
            operations = OperationModel.objects.filter(
                Q(source_account=account) | Q(destination_account=account)
            ).select_related('reason', 'source_account', 'destination_account').order_by('-created_at')[offset:offset + limit]

            # Add direction to each operation
            result = []
            for op in operations:
                op.direction = 'debit' if op.source_account == account else 'credit'
                result.append(op)

            return result

        except ValueError as e:
            logger.error(f"Invalid team UUID format: {team_uuid} - {e}")
            raise GraphQLError("Invalid team UUID format")
        except Exception as e:
            logger.error(f"Error fetching team transactions: {e}")
            raise GraphQLError("Failed to fetch team transactions")


team_schema = graphene.Schema(query=TeamQuery)
