from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.exceptions import ValidationError, NotFound
from django.contrib.auth import get_user_model
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_str

from apps.companies.models import CompanyUser, Company
from apps.apps_.models import App, APIKey
from .serializers import (
    CompanySignupSerializer,
    UserProfileSerializer,
    PasswordResetRequestSerializer,
    PasswordResetConfirmSerializer,
    ChangePasswordSerializer,
    AppSerializer,
    APIKeySerializer,
    CompanyDetailSerializer
)

User = get_user_model()


class CompanySignupView(generics.CreateAPIView):
    serializer_class = CompanySignupSerializer
    permission_classes = [AllowAny]


class UserProfileView(generics.RetrieveUpdateAPIView):
    """View for retrieving and updating user profile"""
    serializer_class = UserProfileSerializer
    permission_classes = [IsAuthenticated]

    def get_object(self):
        return self.request.user


class PasswordResetRequestView(generics.GenericAPIView):
    """View for requesting password reset"""
    serializer_class = PasswordResetRequestSerializer
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(
                {"message": "If an account with that email exists, a password reset link has been sent."},
                status=status.HTTP_200_OK
            )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class PasswordResetConfirmView(generics.GenericAPIView):
    """View for confirming password reset"""
    serializer_class = PasswordResetConfirmSerializer
    permission_classes = [AllowAny]

    def post(self, request, uidb64, token):
        try:
            # Decode user ID
            uid = force_str(urlsafe_base64_decode(uidb64))
            user = CompanyUser.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, CompanyUser.DoesNotExist):
            user = None

        if user is not None and default_token_generator.check_token(user, token):
            serializer = self.get_serializer(data=request.data)
            if serializer.is_valid():
                # Reset password
                user.set_password(serializer.validated_data['new_password'])
                user.save()
                return Response(
                    {"message": "Password has been reset successfully."},
                    status=status.HTTP_200_OK
                )
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(
                {"error": "Invalid or expired reset link."},
                status=status.HTTP_400_BAD_REQUEST
            )


class ChangePasswordView(generics.GenericAPIView):
    """View for changing password while logged in"""
    serializer_class = ChangePasswordSerializer
    permission_classes = [IsAuthenticated]

    def post(self, request):
        serializer = self.get_serializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return Response(
                {"message": "Password changed successfully."},
                status=status.HTTP_200_OK
            )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class CreateAppView(generics.CreateAPIView):
    serializer_class = AppSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        user = self.request.user
        company = getattr(user, "company", None)

        if not company:
            raise ValidationError("You must belong to a company to create an app.")

        if company.plan == "free" and App.objects.filter(company=company).exists():
            raise ValidationError("Free plan is limited to 1 app. Upgrade to create more.")

        serializer.save(company=company)


class CreateApiKeyView(generics.CreateAPIView):
    serializer_class = APIKeySerializer
    permission_classes = [IsAuthenticated]

    def create(self, request, *args, **kwargs):
        company = getattr(request.user, "company", None)
        if not company:
            return Response({"detail": "You must belong to a company"}, status=status.HTTP_400_BAD_REQUEST)

        app_id = request.data.get("app_id")
        if not app_id:
            return Response({"detail": "app_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            app = App.objects.get(id=app_id, company=company)
        except App.DoesNotExist:
            return Response({"detail": "App not found or not owned by your company"}, status=status.HTTP_404_NOT_FOUND)

        if company.plan == "free" and APIKey.objects.filter(app=app).exists():
            return Response(
                {"detail": "Free plan is limited to 1 API key per app. Upgrade to create more."},
                status=status.HTTP_403_FORBIDDEN
            )

        import secrets
        key = secrets.token_hex(20)
        api_key = APIKey.objects.create(app=app, key=key)

        serializer = self.get_serializer(api_key)
        return Response({"message": "API key created", "api_key": serializer.data}, status=status.HTTP_201_CREATED)


class CompanyDetailView(generics.RetrieveAPIView):
    serializer_class = CompanyDetailSerializer
    permission_classes = [IsAuthenticated]

    def get_object(self):
        company = getattr(self.request.user, "company", None)
        if not company:
            raise NotFound("Company not found for this user")
        return company


class AppDetailView(generics.RetrieveAPIView):
    serializer_class = AppSerializer
    permission_classes = [IsAuthenticated]

    def get_object(self):
        company = getattr(self.request.user, "company", None)
        if not company:
            raise NotFound("Company not found for this user")

        app_id = self.kwargs.get("app_id")
        try:
            return App.objects.get(id=app_id, company=company)
        except App.DoesNotExist:
            raise NotFound("App not found")