from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth.models import User
from django.utils import timezone
from django.core.files.uploadedfile import SimpleUploadedFile
from events.models import CallForProposal, Proposal, Event
from datetime import timedelta

class ProposalTests(TestCase):
    def setUp(self):
        # Create test user
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass123'
        )
        self.client = Client()
        self.client.login(username='testuser', password='testpass123')

        # Create test event
        self.event = Event.objects.create(
            title='Test Event',
            description='Test Description',
            date_time=timezone.now() + timedelta(days=30),
            venue='Test Location'
        )

        # Create test CFP
        self.cfp = CallForProposal.objects.create(
            title='Test CFP',
            description='Test Description',
            event=self.event,
            submission_deadline=timezone.now() + timedelta(days=7)
        )

    def test_multiple_proposal_submissions(self):
        """Test that multiple proposals can be submitted to the same CFP"""
        # Submit first proposal
        response1 = self.client.post(
            reverse('events:submit_proposal', args=[self.cfp.id]),
            {
                'title': 'Proposal 1',
                'abstract': 'Abstract 1',
                'presentation_type': 'talk'
            }
        )
        self.assertEqual(Proposal.objects.count(), 1)

        # Submit second proposal
        response2 = self.client.post(
            reverse('events:submit_proposal', args=[self.cfp.id]),
            {
                'title': 'Proposal 2',
                'abstract': 'Abstract 2',
                'presentation_type': 'workshop'
            }
        )
        self.assertEqual(Proposal.objects.count(), 2)

        # Verify proposals are different
        proposals = Proposal.objects.all()
        self.assertNotEqual(proposals[0].title, proposals[1].title)

    def test_proposal_edit(self):
        """Test that editing a proposal updates the correct one"""
        # Create initial proposal
        proposal = Proposal.objects.create(
            title='Original Title',
            abstract='Original Abstract',
            presentation_type='talk',
            cfp=self.cfp,
            submitter=self.user
        )

        # Edit the proposal
        edit_url = f"{reverse('events:submit_proposal', args=[self.cfp.id])}?edit={proposal.id}"
        response = self.client.post(edit_url, {
            'title': 'Updated Title',
            'abstract': 'Updated Abstract',
            'presentation_type': 'workshop'
        })

        # Verify only one proposal exists and it's updated
        self.assertEqual(Proposal.objects.count(), 1)
        updated_proposal = Proposal.objects.first()
        self.assertEqual(updated_proposal.title, 'Updated Title')
        self.assertEqual(updated_proposal.abstract, 'Updated Abstract')

from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from django.test import TestCase, Client
from django.contrib.auth.models import User
from django.utils import timezone
from datetime import timedelta
from events.models import Event, CallForProposal, Proposal

class ProposalTests(TestCase):
    def setUp(self):
        # Create test user
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass123'
        )
        self.reviewer = User.objects.create_user(
            username='reviewer',
            password='testpass123'
        )
        self.client = Client()
        self.client.login(username='testuser', password='testpass123')

        # Create test event and CFP
        self.event = Event.objects.create(
            title='Test Event',
            description='Test Description',
            date_time=timezone.now() + timedelta(days=30),
            venue='Test Location'
        )
        self.cfp = CallForProposal.objects.create(
            title='Test CFP',
            description='Test Description',
            event=self.event,
            submission_deadline=timezone.now() + timedelta(days=7)
        )

    def test_proposal_creation(self):
        """Test proposal creation with all fields"""
        # Create a test file
        test_slides = SimpleUploadedFile(
            "test_slides.pdf",
            b"file_content",
            content_type="application/pdf"
        )
        test_doc = SimpleUploadedFile(
            "test_doc.pdf",
            b"file_content",
            content_type="application/pdf"
        )

        proposal = Proposal.objects.create(
            title='Test Proposal',
            abstract='Test Abstract',
            presentation_type='talk',
            cfp=self.cfp,
            submitter=self.user,
            status='submitted',
            presentation_slides=test_slides,
            supporting_document=test_doc,
            additional_notes='Test notes'
        )

        self.assertEqual(proposal.title, 'Test Proposal')
        self.assertEqual(proposal.status, 'submitted')
        self.assertTrue(proposal.presentation_slides)
        self.assertTrue(proposal.supporting_document)

    def test_proposal_review_process(self):
        """Test the proposal review workflow"""
        proposal = Proposal.objects.create(
            title='Test Proposal',
            abstract='Test Abstract',
            presentation_type='talk',
            cfp=self.cfp,
            submitter=self.user,
            status='submitted'
        )

        # Test initial state
        self.assertEqual(proposal.status, 'submitted')
        self.assertIsNone(proposal.reviewed_by)
        self.assertIsNone(proposal.reviewed_at)
        self.assertEqual(proposal.reviewer_notes, '')

        # Test review process
        proposal.review(
            reviewer=self.reviewer,
            status='accepted',
            notes='Great proposal!'
        )

        # Verify review details
        self.assertEqual(proposal.status, 'accepted')
        self.assertEqual(proposal.reviewed_by, self.reviewer)
        self.assertIsNotNone(proposal.reviewed_at)
        self.assertEqual(proposal.reviewer_notes, 'Great proposal!')

    def test_proposal_list_view(self):
        """Test the proposal list view"""
        # Create multiple proposals
        proposals = [
            Proposal.objects.create(
                title=f'Test Proposal {i}',
                abstract='Test Abstract',
                presentation_type='talk',
                cfp=self.cfp,
                submitter=self.user,
                status='submitted'
            ) for i in range(3)
        ]

        # Test list view
        response = self.client.get(reverse('events:cfp_list'))
        self.assertEqual(response.status_code, 200)
        
        # Verify all proposals are displayed
        for proposal in proposals:
            self.assertContains(response, proposal.title)
            self.assertContains(response, proposal.get_status_display())

    def test_proposal_unique_constraint(self):
        """Test that a user cannot submit duplicate proposals to the same CFP"""
        Proposal.objects.create(
            title='Test Proposal',
            abstract='Test Abstract',
            presentation_type='talk',
            cfp=self.cfp,
            submitter=self.user,
            status='submitted'
        )

        # Attempt to create a duplicate proposal
        with self.assertRaises(Exception):
            Proposal.objects.create(
                title='Test Proposal',  # Same title
                abstract='Different Abstract',
                presentation_type='talk',
                cfp=self.cfp,
                submitter=self.user,  # Same submitter
                status='submitted'
            )
