import logging
import json
import requests
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
from django.conf import settings
from urllib.parse import urlparse

logger = logging.getLogger(__name__)

class PMSService:
    """
    Service to handle integration with the Property Management System.
    """
    
    @classmethod
    def get_session(cls):
        """
        Creates a requests Session with retry logic.
        """
        session = requests.Session()
        retries = Retry(
            total=getattr(settings, 'PMS_MAX_RETRIES', 3),
            backoff_factor=getattr(settings, 'PMS_RETRY_BACKOFF_FACTOR', 0.5),
            status_forcelist=[429, 500, 502, 503, 504],
            allowed_methods=["POST"]
        )
        adapter = HTTPAdapter(max_retries=retries)
        session.mount("https://", adapter)
        session.mount("http://", adapter)
        return session

    @classmethod
    def get_booking_endpoint(cls, booking):
        """
        Resolve the booking push URL.

        AAthitya hotel sync stores either the PMS base URL or a hotel-detail URL
        on the Hotel row. Booking pushes must go to the booking create endpoint.
        """
        hotel_url = getattr(booking.hotel, 'pms_sync_url', None)
        configured_url = hotel_url or getattr(settings, 'PMS_API_URL', None)

        if not configured_url:
            return None

        configured_url = configured_url.rstrip('/')
        if '/channel-manager/api/v1/hotelfinder/' in configured_url:
            parsed = urlparse(configured_url)
            base_url = f"{parsed.scheme}://{parsed.netloc}"
            return f"{base_url}/channel-manager/api/v1/hotelfinder/bookings/create/"

        if hotel_url:
            return f"{configured_url}/channel-manager/api/v1/hotelfinder/bookings/create/"

        return configured_url

    @classmethod
    def get_auth_token(cls, booking):
        return (
            getattr(booking.hotel, 'pms_sync_token', None)
            or getattr(settings, 'PMS_API_TOKEN', None)
            or ''
        )

    @classmethod
    def send_booking(cls, booking):
        """
        Sends booking details to the PMS.
        
        Args:
            booking (HotelBooking): The booking instance to sync.
            
        Returns:
            bool: True if successful, False otherwise.
        """
        pms_url = cls.get_booking_endpoint(booking)
        pms_token = cls.get_auth_token(booking)
        
        if not pms_url:
            logger.error("[PMS Integration] No PMS booking URL configured for hotel %s.", booking.hotel_id)
            return False

        try:
            # Custom payload for Aatithya PMS
            pms_room_id = booking.room_type.pms_id
            if not pms_room_id:
                logger.warning(f"[PMS Integration] RoomType {booking.room_type.id} ({booking.room_type.name}) has no pms_id. Sending local ID.")
                pms_room_id = booking.room_type.id

            guest_name = booking.guest_name or booking.user.get_full_name() or booking.user.username
            guest_phone = booking.mobile or getattr(booking.user, 'phone', '') or ""
            guest_email = booking.email or booking.user.email or ""

            # Check if booking is paid
            from payments.models import Payment
            from django.contrib.contenttypes.models import ContentType
            try:
                ct = ContentType.objects.get_for_model(booking)
                has_paid = Payment.objects.filter(
                    content_type=ct,
                    object_id=booking.id,
                    status='completed'
                ).exists()
                payment_status = 'PAID' if has_paid else 'UNPAID'
            except Exception as e:
                logger.warning(f"[PMS Integration] Error checking payment status: {str(e)}")
                payment_status = 'UNPAID'

            payload = {
                "id": booking.id,
                "hotel_id": booking.hotel.pms_hotel_id or booking.hotel.pms_id,
                "branch_id": booking.hotel.pms_branch_id,
                "room_type": pms_room_id,
                "check_in": str(booking.check_in),
                "check_out": str(booking.check_out),
                "rooms_booked": booking.rooms_booked,
                "guest_name": guest_name,
                "guest_phone": guest_phone,
                "guest_email": guest_email,
                "total_amount": float(booking.total_amount) if booking.total_amount else 0.0,
                "status": booking.status,
                "payment_status": payment_status,
            }
            
            headers = {
                "Authorization": pms_token,
                "X-API-Key": pms_token,
                "Content-Type": "application/json"
            }
            
            timeout = getattr(settings, 'PMS_REQUEST_TIMEOUT', 10)
            verify_ssl = getattr(settings, 'PMS_VERIFY_SSL', True)

            logger.info(f"[PMS Integration] Sending booking {booking.id} to PMS at {pms_url}")
            logger.debug(f"[PMS Payload] {json.dumps(payload, indent=2, default=str)}")
            
            session = cls.get_session()
            response = session.post(
                pms_url, 
                json=payload, 
                headers=headers,
                timeout=timeout,
                verify=verify_ssl
            )
            
            response.raise_for_status()
            
            logger.info(f"[PMS Integration] Successfully sent booking {booking.id}. Response: {response.text}")
            return True
            
        except requests.exceptions.RequestException as e:
            logger.error(f"[PMS Integration] Failed to send booking {booking.id} to PMS: {str(e)}")
            if hasattr(e, 'response') and e.response is not None:
                logger.error(f"[PMS Integration] Response content: {e.response.text}")
            return False
            
        except Exception as e:
            logger.error(f"[PMS Integration] Unexpected error sending booking {booking.id}: {str(e)}")
            return False
