from rest_framework import views, viewsets, permissions, status
from rest_framework.response import Response
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate, get_user_model
from django.shortcuts import get_object_or_404
from django.core.mail import get_connection, EmailMultiAlternatives
from .models import RegistrationDomainRule, RegistrationRestrictionSetting, GuestClaimToken, EmailVerificationToken, SMTPSetting
from .serializers import (
    UserSerializer, AdminUserSerializer, RegisterSerializer,
    RegistrationDomainRuleSerializer, RegistrationRestrictionSettingSerializer, SMTPSettingSerializer
)
from apps.events.models import ShiftSignup

User = get_user_model()

def send_verification_email_to_user(user, v_token_str, request_host=None):
    smtp = SMTPSetting.get_solo()
    host_str = request_host or 'localhost:3000'
    verify_url = f"http://{host_str}/?verify_email={v_token_str}"

    subject = "E-Mail-Adresse bestätigen — Veranstaltungsschichtplaner"
    text_content = f"Hallo {user.get_display_name()},\n\nbitte bestätige deine E-Mail-Adresse durch Aufruf des folgenden Links:\n{verify_url}\n\nVielen Dank!"
    html_content = f"""
    <div style="font-family: sans-serif; padding: 20px; line-height: 1.6; color: #1f2937;">
        <h2 style="color: #4f46e5;">Willkommen beim Schichtplaner!</h2>
        <p>Hallo <strong>{user.get_display_name()}</strong>,</p>
        <p>vielen Dank für deine Registrierung. Bitte bestätige deine E-Mail-Adresse durch Klick auf den folgenden Button:</p>
        <p style="margin: 25px 0;">
            <a href="{verify_url}" style="background: #4f46e5; color: #ffffff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold; display: inline-block;">
                E-Mail-Adresse Bestätigen
            </a>
        </p>
        <p style="color: #6b7280; font-size: 12px;">Oder kopiere diesen Link in deinen Browser:<br><a href="{verify_url}">{verify_url}</a></p>
    </div>
    """

    print("==================================================")
    print(f"[E-MAIL BESTÄTIGUNG]: {verify_url}")
    print("==================================================")

    if smtp.is_active and smtp.host:
        try:
            connection = get_connection(
                host=smtp.host,
                port=smtp.port,
                username=smtp.username,
                password=smtp.password,
                use_tls=smtp.use_tls,
                use_ssl=smtp.use_ssl,
                fail_silently=False,
            )
            msg = EmailMultiAlternatives(
                subject=subject,
                body=text_content,
                from_email=smtp.from_email or 'noreply@schichtplaner.local',
                to=[user.email],
                connection=connection
            )
            msg.attach_alternative(html_content, "text/html")
            msg.send()
            return True, "E-Mail erfolgreich versendet."
        except Exception as e:
            return False, f"SMTP-Fehler: {str(e)}"

    return True, "Bestätigungslink in Konsole ausgegeben."

class AdminUserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = AdminUserSerializer
    permission_classes = [permissions.IsAdminUser]

    def destroy(self, request, *args, **kwargs):
        user_to_delete = self.get_object()
        if user_to_delete.id == request.user.id:
            return Response(
                {'error': 'Du kannst dein eigenes Admin-Konto nicht selbst löschen.'},
                status=status.HTTP_400_BAD_REQUEST
            )
        name = user_to_delete.get_display_name()
        user_to_delete.delete()
        return Response({'message': f'Benutzer "{name}" wurde erfolgreich gelöscht.'})

class RegisterView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            user = serializer.save()
            user.is_approved = False
            user.is_email_verified = False
            user.is_active = True
            user.save()

            setting = RegistrationRestrictionSetting.get_solo()

            claim_token_str = request.data.get('claim_token')
            claimed_target_name = None

            if claim_token_str:
                try:
                    claim_obj = GuestClaimToken.objects.get(token=claim_token_str, is_claimed=False)
                    claim_obj.is_claimed = True
                    claim_obj.save()

                    # Assign target signup
                    target_signup = claim_obj.signup
                    if target_signup and not target_signup.user:
                        target_signup.user = user
                        target_signup.guest_name = None
                        target_signup.guest_session_key = None
                        target_signup.save()

                    claimed_target_name = claim_obj.guest_name
                except Exception:
                    pass

            # Reassign any guest shift signups to this newly created user!
            session_key = request.session.session_key
            display_name = user.get_display_name()

            guest_signups = ShiftSignup.objects.filter(user=None)
            assigned_count = 0
            for signup in guest_signups:
                matches_session = session_key and signup.guest_session_key == session_key
                matches_display = signup.guest_name and signup.guest_name.strip().lower() == display_name.strip().lower()
                matches_claimed_name = claimed_target_name and signup.guest_name and signup.guest_name.strip().lower() == claimed_target_name.strip().lower()

                if matches_session or matches_display or matches_claimed_name:
                    signup.user = user
                    signup.guest_name = None
                    signup.guest_session_key = None
                    signup.save()
                    assigned_count += 1

            if setting.require_email_verification:
                user.is_approved = False
                user.is_email_verified = False
                user.is_active = True
                user.save()

                v_token = EmailVerificationToken.objects.create(user=user)
                req_host = request.get_host()
                send_verification_email_to_user(user, str(v_token.token), request_host=req_host)

                return Response({
                    'requires_verification': True,
                    'verification_token': str(v_token.token),
                    'claimed_shifts_count': assigned_count,
                    'message': 'Konto erfolgreich erstellt! Bitte bestätige deine E-Mail-Adresse über den Link in der Bestätigungs-E-Mail oder warte auf die Admin-Freischaltung.'
                }, status=status.HTTP_201_CREATED)

            # Opt-Out: Email verification not required!
            user.is_email_verified = True

            if setting.require_admin_approval:
                user.is_approved = False
                user.is_active = False
                user.save()
                return Response({
                    'requires_approval': True,
                    'claimed_shifts_count': assigned_count,
                    'message': 'Konto erfolgreich registriert! Ein Administrator muss dein Konto vor der ersten Anmeldung freischalten.'
                }, status=status.HTTP_201_CREATED)

            user.is_approved = True
            user.is_active = True
            user.save()

            token, _ = Token.objects.get_or_create(user=user)
            user_data = UserSerializer(user).data
            return Response({
                'token': token.key,
                'user': user_data,
                'claimed_shifts_count': assigned_count,
                'message': f'Konto erfolgreich erstellt! {assigned_count} Gast-Schichten wurden deinem Konto zugewiesen.' if assigned_count > 0 else 'Konto erfolgreich erstellt!'
            }, status=status.HTTP_201_CREATED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class VerifyEmailView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        token_str = request.data.get('token')
        if not token_str:
            return Response({'error': 'Token erforderlich.'}, status=status.HTTP_400_BAD_REQUEST)

        v_token = EmailVerificationToken.objects.filter(token=token_str, is_used=False).first()
        if not v_token:
            return Response({'error': 'Ungültiger oder bereits verwendeter Bestätigungslink.'}, status=status.HTTP_400_BAD_REQUEST)

        v_token.is_used = True
        v_token.save()

        user = v_token.user
        user.is_email_verified = True
        user.is_approved = True
        user.is_active = True
        user.save()

        token, _ = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user': UserSerializer(user).data,
            'message': f'E-Mail-Adresse für {user.get_display_name()} wurde erfolgreich bestätigt! Du bist jetzt angemeldet.'
        }, status=status.HTTP_200_OK)

class GenerateClaimLinkView(views.APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, signup_id):
        signup = get_object_or_404(ShiftSignup, pk=signup_id)
        if signup.user:
            return Response({'error': 'Diese Schicht ist bereits mit einem festen Benutzerkonto verknüpft.'}, status=status.HTTP_400_BAD_REQUEST)

        guest_name = signup.guest_name or "Gast"

        claim_obj, _ = GuestClaimToken.objects.get_or_create(
            signup=signup,
            created_by=request.user,
            defaults={'guest_name': guest_name}
        )

        return Response({
            'token': str(claim_obj.token),
            'guest_name': guest_name,
            'event_title': signup.shift.task_area.event.title,
            'shift_title': signup.shift.title,
            'created_by': request.user.get_display_name()
        })

class ClaimInfoView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def get(self, request, token_uuid):
        claim_obj = get_object_or_404(GuestClaimToken, token=token_uuid)
        return Response({
            'token': str(claim_obj.token),
            'guest_name': claim_obj.guest_name,
            'is_claimed': claim_obj.is_claimed,
            'event_title': claim_obj.signup.shift.task_area.event.title if claim_obj.signup else 'Veranstaltung',
            'shift_title': claim_obj.signup.shift.title if claim_obj.signup else 'Schicht',
            'created_by': claim_obj.created_by.get_display_name()
        })

class LoginView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        if not username or not password:
            return Response({'error': 'Benutzername und Passwort erforderlich.'}, status=status.HTTP_400_BAD_REQUEST)

        user_obj = None
        if '@' in username:
            try:
                user_obj = User.objects.get(email__iexact=username)
                username = user_obj.username
            except User.DoesNotExist:
                pass
        else:
            try:
                user_obj = User.objects.get(username__iexact=username)
            except User.DoesNotExist:
                pass

        if user_obj:
            if not (user_obj.is_approved or user_obj.is_email_verified or user_obj.is_superuser or user_obj.is_admin_user):
                return Response({
                    'error': 'Anmeldung nicht möglich: Deine E-Mail-Adresse wurde noch nicht bestätigt und dein Konto wurde noch nicht vom Admin freigeschaltet.'
                }, status=status.HTTP_403_FORBIDDEN)

        user = authenticate(username=username, password=password)
        if not user:
            return Response({'error': 'Ungültige Anmeldedaten.'}, status=status.HTTP_401_UNAUTHORIZED)

        token, _ = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user': UserSerializer(user).data
        })

class MeView(views.APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        return Response(UserSerializer(request.user).data)

    def patch(self, request):
        serializer = UserSerializer(request.user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class RegistrationDomainRuleViewSet(viewsets.ModelViewSet):
    queryset = RegistrationDomainRule.objects.all()
    serializer_class = RegistrationDomainRuleSerializer
    permission_classes = [permissions.IsAdminUser]

class RegistrationRestrictionSettingView(views.APIView):
    def get_permissions(self):
        if self.request.method == 'GET':
            return [permissions.AllowAny()]
        return [permissions.IsAdminUser()]

    def get(self, request):
        setting = RegistrationRestrictionSetting.get_solo()
        active_domains = list(RegistrationDomainRule.objects.filter(is_active=True).values_list('domain', flat=True))
        return Response({
            'is_restriction_enabled': setting.is_restriction_enabled,
            'require_admin_approval': setting.require_admin_approval,
            'require_email_verification': setting.require_email_verification,
            'active_domains': active_domains
        })

    def post(self, request):
        setting = RegistrationRestrictionSetting.get_solo()
        if 'is_restriction_enabled' in request.data:
            setting.is_restriction_enabled = request.data['is_restriction_enabled']
        if 'require_admin_approval' in request.data:
            setting.require_admin_approval = request.data['require_admin_approval']
        if 'require_email_verification' in request.data:
            setting.require_email_verification = request.data['require_email_verification']
        setting.save()
        return Response({
            'is_restriction_enabled': setting.is_restriction_enabled,
            'require_admin_approval': setting.require_admin_approval,
            'require_email_verification': setting.require_email_verification
        })

class SMTPSettingView(views.APIView):
    permission_classes = [permissions.IsAdminUser]

    def get(self, request):
        setting = SMTPSetting.get_solo()
        return Response(SMTPSettingSerializer(setting).data)

    def post(self, request):
        setting = SMTPSetting.get_solo()
        serializer = SMTPSettingSerializer(setting, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class TestSMTPEmailView(views.APIView):
    permission_classes = [permissions.IsAdminUser]

    def post(self, request):
        smtp = SMTPSetting.get_solo()
        target_email = request.data.get('email') or request.user.email
        if not target_email:
            return Response({'error': 'E-Mail-Adresse erforderlich.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            connection = get_connection(
                host=smtp.host,
                port=smtp.port,
                username=smtp.username,
                password=smtp.password,
                use_tls=smtp.use_tls,
                use_ssl=smtp.use_ssl,
                fail_silently=False,
            )
            msg = EmailMultiAlternatives(
                subject="Test E-Mail — SMTP Konfiguration",
                body=f"Hallo,\n\ndies ist eine Test-E-Mail zur Überprüfung der SMTP-Einstellungen für {request.user.get_display_name()}.",
                from_email=smtp.from_email or 'noreply@schichtplaner.local',
                to=[target_email],
                connection=connection
            )
            msg.send()
            return Response({'message': f'Test E-Mail erfolgreich an {target_email} gesendet!'})
        except Exception as e:
            return Response({'error': f'SMTP-Verbindungsfehler: {str(e)}'}, status=status.HTTP_400_BAD_REQUEST)

class PendingUsersView(views.APIView):
    permission_classes = [permissions.IsAdminUser]

    def get(self, request):
        pending_users = User.objects.filter(is_approved=False, is_email_verified=False, is_superuser=False).order_by('-date_joined')
        return Response(UserSerializer(pending_users, many=True).data)

class ApproveUserView(views.APIView):
    permission_classes = [permissions.IsAdminUser]

    def post(self, request, user_id):
        user = get_object_or_404(User, pk=user_id)
        user.is_approved = True
        user.is_active = True
        user.save()
        return Response({'message': f'Nutzer {user.get_display_name()} wurde erfolgreich freigeschaltet.'})

    def delete(self, request, user_id):
        user = get_object_or_404(User, pk=user_id)
        name = user.get_display_name()
        user.delete()
        return Response({'message': f'Registrierung von {name} wurde abgelehnt und gelöscht.'})

class UserListView(views.APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        users = User.objects.filter(is_active=True).order_by('username')
        return Response(UserSerializer(users, many=True).data)
