import graphene
from django.utils import timezone
from datetime import timedelta
from graphene_django import DjangoObjectType
from django.contrib.auth import get_user_model
from ..models import Team as TeamModel, TeamMember as TeamMemberModel, TeamAddress as TeamAddressModel
from ..permissions import require_scopes

UserModel = get_user_model()

class User(DjangoObjectType):
    id = graphene.String()
    firstName = graphene.String()
    lastName = graphene.String()
    phone = graphene.String()
    avatarId = graphene.String()
    createdAt = graphene.String()
    
    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_createdAt(self, info):
        return self.date_joined.isoformat() if self.date_joined else None

class TeamMember(DjangoObjectType):
    user = graphene.Field(User)
    joinedAt = graphene.String()
    
    class Meta:
        model = TeamMemberModel
        fields = ('role', 'joined_at')
    
    def resolve_user(self, info):
        return self.user
    
    def resolve_joinedAt(self, info):
        return self.joined_at.isoformat() if self.joined_at else None

class TeamAddress(DjangoObjectType):
    isDefault = graphene.Boolean()
    createdAt = graphene.String()
    graphNodeId = graphene.String()
    processedAt = graphene.String()
    countryCode = graphene.String()

    class Meta:
        model = TeamAddressModel
        fields = ('uuid', 'name', 'address', 'latitude', 'longitude', 'is_default', 'created_at', 'country_code')

    def resolve_isDefault(self, info):
        return self.is_default

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

    def resolve_graphNodeId(self, info):
        return self.graph_node_id

    def resolve_processedAt(self, info):
        return self.processed_at.isoformat() if self.processed_at else None

    def resolve_countryCode(self, info):
        return self.country_code


class SelectedLocation(graphene.ObjectType):
    type = graphene.String()
    uuid = graphene.String()
    name = graphene.String()
    latitude = graphene.Float()
    longitude = graphene.Float()


class Team(DjangoObjectType):
    id = graphene.String()
    ownerId = graphene.String()
    members = graphene.List(TeamMember)
    addresses = graphene.List(lambda: TeamAddress)
    selectedLocation = graphene.Field(SelectedLocation)

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

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

    def resolve_ownerId(self, info):
        if self.owner and hasattr(self.owner, 'profile'):
            return self.owner.profile.logto_id
        return self.owner.username if self.owner else None

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

    def resolve_addresses(self, info):
        return self.addresses.all()

    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 TeamQuery(graphene.ObjectType):
    team = graphene.Field(Team)
    getTeam = graphene.Field(Team, teamId=graphene.String(required=True))
    team_members = graphene.List(TeamMember)
    team_addresses = graphene.List(TeamAddress)
    
    @require_scopes("teams:member")
    def resolve_team(self, info):
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            return None

        try:
            return TeamModel.objects.get(uuid=team_uuid)
        except TeamModel.DoesNotExist:
            return None

    @require_scopes("teams:member")
    def resolve_getTeam(self, info, teamId):
        # Получаем конкретную команду по ID
        try:
            return TeamModel.objects.get(uuid=teamId)
        except TeamModel.DoesNotExist:
            return None

    @require_scopes("teams:member")
    def resolve_team_members(self, info):
        # Получаем участников команды
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            return []

        try:
            team = TeamModel.objects.get(uuid=team_uuid)
            return team.members.all()
        except TeamModel.DoesNotExist:
            return []

    @require_scopes("teams:member")
    def resolve_team_addresses(self, info):
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            return []

        try:
            team = TeamModel.objects.get(uuid=team_uuid)
            return team.addresses.all()
        except TeamModel.DoesNotExist:
            return []


class InviteMemberInput(graphene.InputObjectType):
    email = graphene.String(required=True)
    role = graphene.String()

class InviteMemberMutation(graphene.Mutation):
    class Arguments:
        input = InviteMemberInput(required=True)

    success = graphene.Boolean()
    message = graphene.String()

    @require_scopes("teams:member")
    def mutate(self, info, input):
        from ..temporal_client import start_invite_workflow

        # Проверяем права - только owner может приглашать
        team_uuid = getattr(info.context, 'team_uuid', None)
        user_id = getattr(info.context, 'user_id', None)
        
        if not team_uuid or not user_id:
            return InviteMemberMutation(success=False, message="Недостаточно прав")
        
        try:
            team = TeamModel.objects.get(uuid=team_uuid)
            
            # Проверяем что пользователь - owner команды
            if not team.owner:
                return InviteMemberMutation(success=False, message="Только owner может приглашать")
            owner_identifier = team.owner.profile.logto_id if hasattr(team.owner, 'profile') and team.owner.profile else team.owner.username
            if owner_identifier != user_id:
                return InviteMemberMutation(success=False, message="Только owner может приглашать")
            
            expires_at = timezone.now() + timedelta(days=7)
            start_invite_workflow(
                team_uuid=str(team.uuid),
                email=input.email,
                role=input.role or 'MEMBER',
                invited_by=owner_identifier,
                expires_at=expires_at.isoformat(),
            )

            return InviteMemberMutation(success=True, message="Приглашение отправлено")
            
        except TeamModel.DoesNotExist:
            return InviteMemberMutation(success=False, message="Команда не найдена")

class CreateTeamAddressInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    address = graphene.String(required=True)
    latitude = graphene.Float()
    longitude = graphene.Float()
    countryCode = graphene.String()
    isDefault = graphene.Boolean()


class CreateTeamAddressMutation(graphene.Mutation):
    class Arguments:
        input = CreateTeamAddressInput(required=True)

    success = graphene.Boolean()
    message = graphene.String()
    workflowId = graphene.String()

    @require_scopes("teams:member")
    def mutate(self, info, input):
        from ..temporal_client import start_address_workflow

        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            return CreateTeamAddressMutation(success=False, message="Не авторизован")

        try:
            team = TeamModel.objects.get(uuid=team_uuid)

            # Запускаем workflow - он сам создаст адрес через M2M мутацию
            workflow_id, _ = start_address_workflow(
                team_uuid=str(team.uuid),
                name=input.name,
                address=input.address,
                latitude=input.get('latitude'),
                longitude=input.get('longitude'),
                country_code=input.get('countryCode'),
                is_default=input.get('isDefault', False),
            )

            return CreateTeamAddressMutation(
                success=True,
                message="Адрес создается",
                workflowId=workflow_id,
            )

        except TeamModel.DoesNotExist:
            return CreateTeamAddressMutation(success=False, message="Команда не найдена")
        except Exception as e:
            return CreateTeamAddressMutation(success=False, message=str(e))


class DeleteTeamAddressMutation(graphene.Mutation):
    class Arguments:
        uuid = graphene.String(required=True)

    success = graphene.Boolean()
    message = graphene.String()

    @require_scopes("teams:member")
    def mutate(self, info, uuid):
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            return DeleteTeamAddressMutation(success=False, message="Не авторизован")

        try:
            team = TeamModel.objects.get(uuid=team_uuid)
            address = team.addresses.get(uuid=uuid)
            address.delete()
            return DeleteTeamAddressMutation(success=True, message="Адрес удален")

        except TeamModel.DoesNotExist:
            return DeleteTeamAddressMutation(success=False, message="Команда не найдена")
        except TeamAddressModel.DoesNotExist:
            return DeleteTeamAddressMutation(success=False, message="Адрес не найден")


class SetSelectedLocationInput(graphene.InputObjectType):
    type = graphene.String(required=True)  # 'address' или 'hub'
    uuid = graphene.String(required=True)
    name = graphene.String(required=True)
    latitude = graphene.Float(required=True)
    longitude = graphene.Float(required=True)


class SetSelectedLocationMutation(graphene.Mutation):
    class Arguments:
        input = SetSelectedLocationInput(required=True)

    success = graphene.Boolean()
    message = graphene.String()
    selectedLocation = graphene.Field(SelectedLocation)

    @require_scopes("teams:member")
    def mutate(self, info, input):
        team_uuid = getattr(info.context, 'team_uuid', None)
        if not team_uuid:
            return SetSelectedLocationMutation(success=False, message="Не авторизован")

        location_type = input.type
        if location_type not in ('address', 'hub'):
            return SetSelectedLocationMutation(success=False, message="Неверный тип локации")

        try:
            team = TeamModel.objects.get(uuid=team_uuid)
            team.selected_location_type = location_type
            team.selected_location_uuid = input.uuid
            team.selected_location_name = input.name
            team.selected_location_latitude = input.latitude
            team.selected_location_longitude = input.longitude
            team.save(update_fields=[
                'selected_location_type',
                'selected_location_uuid',
                'selected_location_name',
                'selected_location_latitude',
                'selected_location_longitude'
            ])

            return SetSelectedLocationMutation(
                success=True,
                message="Локация выбрана",
                selectedLocation=SelectedLocation(
                    type=location_type,
                    uuid=input.uuid,
                    name=input.name,
                    latitude=input.latitude,
                    longitude=input.longitude
                )
            )

        except TeamModel.DoesNotExist:
            return SetSelectedLocationMutation(success=False, message="Команда не найдена")


class TeamMutation(graphene.ObjectType):
    invite_member = InviteMemberMutation.Field()
    create_team_address = CreateTeamAddressMutation.Field()
    delete_team_address = DeleteTeamAddressMutation.Field()
    set_selected_location = SetSelectedLocationMutation.Field()

team_schema = graphene.Schema(query=TeamQuery, mutation=TeamMutation)
