"""
Tests for Group Posts feature.
Verifies that posts inside groups are correctly excluded from feed/explore/profile.
"""
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 posts.models import Post
from usergroups.models import Group, GroupMember

User = get_user_model()


class GroupPostsFilteringTest(TestCase):
    """Test that group posts are excluded from regular feeds."""

    def setUp(self):
        """Set up test users, group, and posts."""
        self.client = APIClient()

        # Create users
        self.user1 = User.objects.create_user(
            username='user1',
            email='user1@test.com',
            password='testpass123',
            first_name='User',
            last_name='One'
        )
        self.user2 = User.objects.create_user(
            username='user2',
            email='user2@test.com',
            password='testpass123',
            first_name='User',
            last_name='Two'
        )

        # Create a group
        self.group = Group.objects.create(
            name='Test Group',
            description='A test group',
            created_by=self.user1
        )

        # Add user1 as admin
        GroupMember.objects.create(
            user=self.user1,
            group=self.group,
            role='ADMIN'
        )

        # Create a normal post (no group)
        self.normal_post = Post.objects.create(
            content='This is a normal post',
            created_by=self.user1,
            audience='PUBLIC'
        )

        # Create a group post
        self.group_post = Post.objects.create(
            content='This is a group post',
            created_by=self.user1,
            group=self.group,
            audience='PUBLIC'
        )

    def test_normal_post_appears_in_feed(self):
        """Normal posts (group=null) should appear in feed."""
        self.client.force_authenticate(user=self.user1)
        response = self.client.get('/api/v1/posts/feed/')

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Get post IDs from response
        post_ids = [p['id'] for p in response.data['results']]

        # Normal post should be in feed
        self.assertIn(self.normal_post.id, post_ids)

    def test_group_post_excluded_from_feed(self):
        """Group posts should NOT appear in regular feed."""
        self.client.force_authenticate(user=self.user1)
        response = self.client.get('/api/v1/posts/feed/')

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Get post IDs from response
        post_ids = [p['id'] for p in response.data['results']]

        # Group post should NOT be in feed
        self.assertNotIn(self.group_post.id, post_ids)

    def test_group_post_excluded_from_user_posts(self):
        """Group posts should NOT appear in user's profile posts."""
        self.client.force_authenticate(user=self.user2)
        response = self.client.get(f'/api/v1/posts/user/{self.user1.id}/')

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Get post IDs from response
        post_ids = [p['id'] for p in response.data['results']]

        # Normal post should be visible
        self.assertIn(self.normal_post.id, post_ids)

        # Group post should NOT be visible
        self.assertNotIn(self.group_post.id, post_ids)

    def test_group_post_appears_in_group_feed(self):
        """Group posts should appear in the group's post list."""
        # Add user2 as member
        GroupMember.objects.create(
            user=self.user2,
            group=self.group,
            role='MEMBER'
        )

        self.client.force_authenticate(user=self.user2)
        response = self.client.get(f'/api/v1/groups/{self.group.id}/posts/')

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Get post IDs from response
        post_ids = [p['id'] for p in response.data]

        # Group post should be in group feed
        self.assertIn(self.group_post.id, post_ids)

        # Normal post should NOT be in group feed
        self.assertNotIn(self.normal_post.id, post_ids)

    def test_non_member_cannot_see_group_posts(self):
        """Non-members should not be able to access group posts."""
        self.client.force_authenticate(user=self.user2)  # user2 is not a member
        response = self.client.get(f'/api/v1/groups/{self.group.id}/posts/')

        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_create_post_in_group(self):
        """Members can create posts in groups."""
        # Add user2 as member
        GroupMember.objects.create(
            user=self.user2,
            group=self.group,
            role='MEMBER'
        )

        self.client.force_authenticate(user=self.user2)
        response = self.client.post(
            f'/api/v1/groups/{self.group.id}/posts/create/',
            {'content': 'New group post by user2'},
            format='multipart'  # Use multipart for PostCreateSerializer
        )

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        # Verify post has group set
        new_post = Post.objects.get(id=response.data['id'])
        self.assertEqual(new_post.group, self.group)
        self.assertEqual(new_post.created_by, self.user2)

    def test_group_post_not_in_search(self):
        """Group posts should not appear in search results."""
        self.client.force_authenticate(user=self.user1)
        response = self.client.get('/api/v1/posts/search/', {'q': 'post'})

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Get post IDs from response
        post_ids = [p['id'] for p in response.data['results']]

        # Normal post should appear
        self.assertIn(self.normal_post.id, post_ids)

        # Group post should NOT appear
        self.assertNotIn(self.group_post.id, post_ids)


class GroupPostPermissionsTest(TestCase):
    """Test group post deletion permissions."""

    def setUp(self):
        """Set up test data."""
        self.client = APIClient()

        self.admin = User.objects.create_user(
            username='admin',
            email='admin@test.com',
            password='testpass123'
        )
        self.mod = User.objects.create_user(
            username='mod',
            email='mod@test.com',
            password='testpass123'
        )
        self.member = User.objects.create_user(
            username='member',
            email='member@test.com',
            password='testpass123'
        )

        self.group = Group.objects.create(
            name='Test Group',
            created_by=self.admin
        )

        GroupMember.objects.create(user=self.admin, group=self.group, role='ADMIN')
        GroupMember.objects.create(user=self.mod, group=self.group, role='MODERATOR')
        GroupMember.objects.create(user=self.member, group=self.group, role='MEMBER')

        self.member_post = Post.objects.create(
            content='Member post',
            created_by=self.member,
            group=self.group
        )

    def test_admin_can_delete_any_post(self):
        """Admin can delete any post in the group."""
        self.client.force_authenticate(user=self.admin)
        response = self.client.delete(
            f'/api/v1/groups/{self.group.id}/posts/{self.member_post.id}/delete/'
        )

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Verify post is soft deleted
        self.member_post.refresh_from_db()
        self.assertFalse(self.member_post.is_active)

    def test_mod_can_delete_member_post(self):
        """Moderator can delete member posts."""
        # Create a fresh post
        new_post = Post.objects.create(
            content='Another member post',
            created_by=self.member,
            group=self.group
        )

        self.client.force_authenticate(user=self.mod)
        response = self.client.delete(
            f'/api/v1/groups/{self.group.id}/posts/{new_post.id}/delete/'
        )

        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_member_can_only_delete_own_post(self):
        """Member can only delete their own posts."""
        # Create admin's post
        admin_post = Post.objects.create(
            content='Admin post',
            created_by=self.admin,
            group=self.group
        )

        self.client.force_authenticate(user=self.member)

        # Try to delete admin's post - should fail
        response = self.client.delete(
            f'/api/v1/groups/{self.group.id}/posts/{admin_post.id}/delete/'
        )
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

        # Create and delete own post - should succeed
        own_post = Post.objects.create(
            content='My own post',
            created_by=self.member,
            group=self.group
        )
        response = self.client.delete(
            f'/api/v1/groups/{self.group.id}/posts/{own_post.id}/delete/'
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
