from django.test import TestCase, override_settings
from unittest.mock import patch, MagicMock
from datetime import date
from django.contrib.auth import get_user_model
from .models import Hotel, RoomType, HotelBooking
from .pms_integration import PMSService

User = get_user_model()

class PMSServiceTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='pms_test_user', 
            email='test@example.com',
            first_name='Test',
            last_name='User',
            phone='9876543210'
        )
        self.hotel = Hotel.objects.create(owner=self.user, name='PMS Hotel', city='City', address='Addr')
        self.room_type = RoomType.objects.create(hotel=self.hotel, name='Standard', price=500, total_rooms=5)
        self.booking = HotelBooking.objects.create(
            user=self.user,
            hotel=self.hotel,
            branch='Main',
            room_type=self.room_type,
            check_in=date(2024, 1, 1),
            check_out=date(2024, 1, 5),
            rooms_booked=1,
            status='confirmed'
        )

    @patch('requests.Session.post')
    @override_settings(PMS_API_URL='http://test.com', PMS_API_TOKEN='test_token', PMS_VERIFY_SSL=False)
    def test_send_booking_success(self, mock_post):
        # Configure mock
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.text = '{"success": true}'
        mock_post.return_value = mock_response
        
        # Call service
        result = PMSService.send_booking(self.booking)
        
        # Verify result
        self.assertTrue(result)
        
        # Verify payload
        expected_payload = {
            "id": self.booking.id,
            "hotel_id": None,
            "branch_id": None,
            "room_type": self.room_type.id,
            "check_in": "2024-01-01",
            "check_out": "2024-01-05",
            "rooms_booked": 1,
            "guest_name": "Test User",
            "guest_phone": "9876543210",
            "guest_email": "test@example.com",
            "total_amount": 2000.0,
            "status": "confirmed",
            "payment_status": "UNPAID",
        }
        
        mock_post.assert_called_once()
        args, kwargs = mock_post.call_args
        self.assertEqual(args[0], 'http://test.com')
        self.assertEqual(kwargs['json'], expected_payload)
        self.assertEqual(kwargs['verify'], False) # We set verify=False in implementation

    def test_get_booking_endpoint_from_aatithya_hotel_detail_url(self):
        self.hotel.pms_sync_url = 'http://localhost:8000/channel-manager/api/v1/hotelfinder/hotels/1/'
        self.hotel.save(update_fields=['pms_sync_url'])

        self.assertEqual(
            PMSService.get_booking_endpoint(self.booking),
            'http://localhost:8000/channel-manager/api/v1/hotelfinder/bookings/create/'
        )

    def test_get_booking_endpoint_from_aatithya_base_url(self):
        self.hotel.pms_sync_url = 'http://localhost:8000'
        self.hotel.save(update_fields=['pms_sync_url'])

        self.assertEqual(
            PMSService.get_booking_endpoint(self.booking),
            'http://localhost:8000/channel-manager/api/v1/hotelfinder/bookings/create/'
        )

    @patch('requests.Session.post')
    @override_settings(PMS_API_URL='http://test.com', PMS_API_TOKEN='test_token')
    def test_send_booking_failure(self, mock_post):
        mock_response = MagicMock()
        mock_response.status_code = 500
        mock_response.text = 'Server Error'
        
        import requests
        # Mock raise_for_status to actually raise an exception for 500 status
        mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError('500 Server Error')
        mock_post.return_value = mock_response
        
        result = PMSService.send_booking(self.booking)
        
        self.assertFalse(result)


from rest_framework.test import APITestCase
from django.urls import reverse

class SyncPMSHotelViewTest(APITestCase):
    def setUp(self):
        self.user = User.objects.create_superuser(
            username='admin_user', 
            email='admin@example.com'
        )
        self.user.role = 'ADMIN'
        self.user.save()
        self.client.force_authenticate(user=self.user)

    @patch('hotel.pms_sync.sync_one_hotel')
    @patch('requests.post')
    def test_sync_pms_hotel_aatithya_success(self, mock_post, mock_sync_one_hotel):
        # Configure mocks
        mock_sync_one_hotel.return_value = (True, "Synced successfully")
        
        mock_post_resp = MagicMock()
        mock_post_resp.status_code = 200
        mock_post.return_value = mock_post_resp
        
        # Call API
        url = reverse('sync-pms-hotel')
        payload = {
            "is_aatithya": True,
            "pms_sync_url": "http://localhost:8000",
            "pms_branch_id": 1
        }
        response = self.client.post(url, payload, format='json')
        
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.json()['created'], True)
        
        # Verify sync_one_hotel was called with correctly mapped sync_url
        expected_sync_url = "http://localhost:8000/channel-manager/api/v1/hotelfinder/hotels/1/"
        mock_sync_one_hotel.assert_called_once()
        args, kwargs = mock_sync_one_hotel.call_args
        self.assertEqual(args[1], expected_sync_url)
        
        # Verify connection mapping POST was called on success
        mock_post.assert_called_once()
        args, kwargs = mock_post.call_args
        self.assertEqual(args[0], "http://localhost:8000/channel-manager/api/v1/hotelfinder/connection-mapping/")

    def test_next_id_api(self):
        url = reverse('hotel-next-id')
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertIn('next_id', response.json())
        self.assertEqual(response.json()['next_id'], 1)
        
        # Create a hotel and check next_id increases
        hotel = Hotel.objects.create(owner=self.user, name='Another Hotel', city='City', address='Addr')
        response = self.client.get(url)
        self.assertEqual(response.json()['next_id'], hotel.id + 1)
