from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework.test import APIClient
from rest_framework import status
from django.urls import reverse
from posts.models import Post

User = get_user_model()

class PrivateAccountVisibilityTest(TestCase):
    def setUp(self):
        self.client = APIClient()
        # Public user
        self.public_user = User.objects.create_user(
            username='public_user',
            email='public@example.com',
            password='password123',
            is_private=False
        )
        # Private user
        self.private_user = User.objects.create_user(
            username='private_user',
            email='private@example.com',
            password='password123',
            is_private=True
        )
        # Random user (non-follower)
        self.random_user = User.objects.create_user(
            username='random_user',
            email='random@example.com',
            password='password123'
        )

        # Follower user
        self.follower_user = User.objects.create_user(
            username='follower_user',
            email='follower@example.com',
            password='password123'
        )
        from follows.models import FollowUser
        FollowUser.objects.create(follower=self.follower_user, followed=self.private_user)

    def test_private_account_posts_visibility_to_non_follower(self):
        """Posts from private accounts should NOT be visible to non-followers"""
        Post.objects.create(content="Private message", created_by=self.private_user, audience='FOLLOWERS')

        self.client.force_authenticate(user=self.random_user)
        response = self.client.get(reverse('list_posts'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        # Assuming list_posts uses PageNumberPagination
        post_contents = [p['content'] for p in response.data['results']]
        self.assertNotIn("Private message", post_contents)

    def test_private_account_posts_visibility_to_follower(self):
        """Posts from private accounts SHOULD be visible to followers"""
        Post.objects.create(content="Private message", created_by=self.private_user, audience='FOLLOWERS')

        self.client.force_authenticate(user=self.follower_user)
        response = self.client.get(reverse('list_posts'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        post_contents = [p['content'] for p in response.data['results']]
        self.assertIn("Private message", post_contents)

    def test_private_account_public_audience_violation(self):
        """Private accounts cannot create public posts"""
        self.client.force_authenticate(user=self.private_user)
        data = {
            'content': 'Attempting public post',
            'audience': 'PUBLIC'
        }
        response = self.client.post(reverse('create_post'), data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn('audience', response.data)

    def test_private_account_auto_restricted_visibility(self):
        """Even if a private user somehow has a PUBLIC post, it shouldn't be visible to strangers"""
        # Manually create a PUBLIC post for a private user (simulating bypass or prior state)
        Post.objects.create(content="Sneaky public post", created_by=self.private_user, audience='PUBLIC')

        self.client.force_authenticate(user=self.random_user)
        response = self.client.get(reverse('list_posts'))
        post_contents = [p['content'] for p in response.data['results']]
        self.assertNotIn("Sneaky public post", post_contents)

    def test_public_account_public_post_visibility(self):
        """Public accounts PUBLIC posts should be visible to everyone"""
        Post.objects.create(content="Hello world", created_by=self.public_user, audience='PUBLIC')

        self.client.force_authenticate(user=self.random_user)
        response = self.client.get(reverse('list_posts'))
        post_contents = [p['content'] for p in response.data['results']]
        self.assertIn("Hello world", post_contents)
