import graphene
from graphene_django import DjangoObjectType
from django.contrib.auth import get_user_model
from ..models import Team as TeamModel, TeamMember as TeamMemberModel, TeamInvitation as TeamInvitationModel, UserProfile
from .team_schema import SelectedLocation

UserModel = get_user_model()


def _get_or_create_user_with_profile(logto_id: str):
    user, _ = UserModel.objects.get_or_create(
        username=logto_id,
        defaults={'email': ''}
    )
    profile, _ = UserProfile.objects.get_or_create(
        logto_id=logto_id,
        defaults={'user': user}
    )
    if profile.user_id != user.id:
        profile.user = user
        profile.save(update_fields=['user'])
    # Attach profile to user for resolvers
    user.profile = profile
    return user

class Team(DjangoObjectType):
    id = graphene.String()
    logtoOrgId = graphene.String()
    teamType = graphene.String()
    selectedLocation = graphene.Field(SelectedLocation)

    class Meta:
        model = TeamModel
        fields = ('uuid', 'name', 'logto_org_id', 'team_type', 'created_at')

    def resolve_id(self, info):
        return self.uuid

    def resolve_logtoOrgId(self, info):
        return self.logto_org_id

    def resolve_teamType(self, info):
        return self.team_type

    def resolve_selectedLocation(self, info):
        loc_type = getattr(self, 'selected_location_type', None)
        loc_uuid = getattr(self, 'selected_location_uuid', None)
        if loc_type and loc_uuid:
            return SelectedLocation(
                type=loc_type,
                uuid=loc_uuid,
                name=getattr(self, 'selected_location_name', None),
                latitude=getattr(self, 'selected_location_latitude', None),
                longitude=getattr(self, 'selected_location_longitude', None)
            )
        return None

class User(DjangoObjectType):
    id = graphene.String()
    firstName = graphene.String()
    lastName = graphene.String()
    phone = graphene.String()
    avatarId = graphene.String()
    activeTeamId = graphene.String()
    activeTeam = graphene.Field(Team)
    teams = graphene.List(Team)
    
    class Meta:
        model = UserModel
        fields = ('username', 'first_name', 'last_name', 'email')
    
    def resolve_id(self, info):
        if hasattr(self, 'profile') and self.profile:
            return self.profile.logto_id
        return self.username
    
    def resolve_firstName(self, info):
        return self.first_name
        
    def resolve_lastName(self, info):
        return self.last_name
        
    def resolve_phone(self, info):
        return getattr(self.profile, 'phone', None)
        
    def resolve_avatarId(self, info):
        return getattr(self.profile, 'avatar_id', None)
    
    def resolve_activeTeamId(self, info):
        return self.profile.active_team.uuid if getattr(self, 'profile', None) and self.profile.active_team else None
        
    def resolve_activeTeam(self, info):
        return self.profile.active_team if getattr(self, 'profile', None) else None
    
    def resolve_teams(self, info):
        # Возвращаем Team объекты через TeamMember отношения  
        from ..models import TeamMember as TeamMemberModel
        team_members = TeamMemberModel.objects.filter(user=self)
        return [member.team for member in team_members]

class TeamMember(DjangoObjectType):
    user = graphene.Field(User)
    role = graphene.String()
    joinedAt = graphene.String()

    class Meta:
        from ..models import TeamMember as TeamMemberModel
        model = TeamMemberModel
        fields = ('uuid', 'role')

    def resolve_joinedAt(self, info):
        return self.joined_at.isoformat() if self.joined_at else None


class TeamInvitation(DjangoObjectType):
    email = graphene.String()
    role = graphene.String()
    status = graphene.String()
    invitedBy = graphene.String()
    expiresAt = graphene.String()
    createdAt = graphene.String()

    class Meta:
        model = TeamInvitationModel
        fields = ('uuid', 'email', 'role', 'status')

    def resolve_invitedBy(self, info):
        return self.invited_by

    def resolve_expiresAt(self, info):
        return self.expires_at.isoformat() if self.expires_at else None

    def resolve_createdAt(self, info):
        return self.created_at.isoformat() if self.created_at else None


class TeamWithMembers(DjangoObjectType):
    id = graphene.String()
    members = graphene.List(TeamMember)
    invitations = graphene.List(TeamInvitation)

    class Meta:
        model = TeamModel
        fields = ('uuid', 'name', 'created_at')

    def resolve_id(self, info):
        return self.uuid

    def resolve_members(self, info):
        return self.members.all()

    def resolve_invitations(self, info):
        return self.invitations.filter(status='PENDING')


class UserQuery(graphene.ObjectType):
    me = graphene.Field(User)
    get_team = graphene.Field(TeamWithMembers, team_id=graphene.String(required=True))

    def resolve_me(self, info):
        # Получаем user_id из ID Token
        user_id = getattr(info.context, 'user_id', None)
        if not user_id:
            return None

        try:
            return _get_or_create_user_with_profile(user_id)
        except Exception:
            return None

    def resolve_get_team(self, info, team_id):
        try:
            return TeamModel.objects.get(uuid=team_id)
        except TeamModel.DoesNotExist:
            return None

class CreateTeamInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    teamType = graphene.String()  # BUYER или SELLER


class UpdateUserInput(graphene.InputObjectType):
    firstName = graphene.String()
    lastName = graphene.String()
    phone = graphene.String()
    avatarId = graphene.String()

class CreateTeamMutation(graphene.Mutation):
    class Arguments:
        input = CreateTeamInput(required=True)

    team = graphene.Field(Team)

    def mutate(self, info, input):
        # Получаем user_id из контекста (ID Token)
        user_id = getattr(info.context, 'user_id', None)
        if not user_id:
            raise Exception("User not authenticated")

        try:
            owner = _get_or_create_user_with_profile(user_id)

            team = TeamModel.objects.create(
                name=input.name,
                owner=owner,
                team_type=input.teamType or 'BUYER'
            )

            # Добавляем owner как участника команды с ролью OWNER
            TeamMemberModel.objects.create(
                team=team,
                user=owner,
                role='OWNER'
            )

            # Устанавливаем как активную команду, если у пользователя её нет
            if hasattr(owner, 'profile') and not owner.profile.active_team:
                owner.profile.active_team = team
                owner.profile.save(update_fields=['active_team'])

            return CreateTeamMutation(team=team)

        except Exception as e:
            raise Exception(f"Failed to create team: {str(e)}")


class UpdateUserMutation(graphene.Mutation):
    class Arguments:
        userId = graphene.String(required=True)
        input = UpdateUserInput(required=True)

    user = graphene.Field(User)

    def mutate(self, info, userId, input):
        # Проверяем права - пользователь может редактировать только себя
        context_user_id = getattr(info.context, 'user_id', None)
        if context_user_id != userId:
            return UpdateUserMutation(user=None)

        try:
            user = _get_or_create_user_with_profile(userId)

            if input.firstName is not None:
                user.first_name = input.firstName
            if input.lastName is not None:
                user.last_name = input.lastName
            user.save()
            if hasattr(user, 'profile'):
                if input.phone is not None:
                    user.profile.phone = input.phone
                if input.avatarId is not None:
                    user.profile.avatar_id = input.avatarId
                user.profile.save()
            return UpdateUserMutation(user=user)

        except Exception:
            return UpdateUserMutation(user=None)


class SwitchTeamMutation(graphene.Mutation):
    class Arguments:
        teamId = graphene.String(required=True)

    user = graphene.Field(User)

    def mutate(self, info, teamId):
        user_id = getattr(info.context, 'user_id', None)
        if not user_id:
            raise Exception("User not authenticated")

        try:
            team = TeamModel.objects.get(uuid=teamId)
            user = _get_or_create_user_with_profile(user_id)
            if hasattr(user, 'profile'):
                user.profile.active_team = team
                user.profile.save(update_fields=['active_team'])
            return SwitchTeamMutation(user=user)
        except TeamModel.DoesNotExist:
            raise Exception("Team not found")


class UserMutation(graphene.ObjectType):
    create_team = CreateTeamMutation.Field()
    update_user = UpdateUserMutation.Field()
    switch_team = SwitchTeamMutation.Field()

user_schema = graphene.Schema(query=UserQuery, mutation=UserMutation)
