"""
Aahar Integration Service
Handles all outgoing HTTP calls to the Aahar restaurant management system.
"""

import logging
import requests
from django.conf import settings

logger = logging.getLogger(__name__)

AAHAR_BASE_URL = getattr(settings, 'AAHAR_API_URL', 'https://aaharqr.vaiditech.com/')
AAHAR_API_KEY = getattr(settings, 'AAHAR_API_KEY', '')
AAHAR_API_USER = getattr(settings, 'AAHAR_API_USER', 'vaiditech')
AAHAR_API_PASSWORD = getattr(settings, 'AAHAR_API_PASSWORD', '12345678')
REQUEST_TIMEOUT = 15  # seconds


class AaharServiceError(Exception):
    """Custom exception for Aahar API errors"""
    def __init__(self, message, status_code=None, response_data=None):
        super().__init__(message)
        self.status_code = status_code
        self.response_data = response_data


def _get_headers():
    """Get common headers for Aahar API requests"""
    headers = {
        'Content-Type': 'application/json',
    }
    if AAHAR_API_KEY:
        headers['Authorization'] = f'Bearer {AAHAR_API_KEY}'
        headers['Access-Token'] = AAHAR_API_KEY
    return headers


def _make_request(method, endpoint, data=None, base_url=None, auth=None, headers=None):
    """
    Generic request handler for Aahar APIs.
    Returns the JSON response or raises AaharServiceError.
    """
    if base_url:
        if not base_url.startswith("http://") and not base_url.startswith("https://"):
            import re
            is_ip_or_local = re.match(r'^(localhost|127\.0\.0\.1|192\.168\.|[0-9]{1,3}\.[0-9]{1,3})', base_url)
            if is_ip_or_local:
                base_url = f"http://{base_url}"
            else:
                base_url = f"https://{base_url}"
        base_url = base_url.rstrip('/')
        if 'apis/backend/web' not in base_url:
            base_url = f"{base_url}/apis/backend/web"
    url = f"{base_url or AAHAR_BASE_URL.rstrip('/')}/{endpoint}"
    req_headers = _get_headers()
    if headers:
        req_headers.update(headers)

    try:
        response = requests.request(
            method=method,
            url=url,
            json=data,
            headers=req_headers,
            timeout=REQUEST_TIMEOUT,
            auth=auth,
            verify=False,
        )

        response_data = None
        try:
            response_data = response.json()
        except ValueError:
            response_data = {'raw': response.text}

        if response.status_code >= 400:
            raise AaharServiceError(
                message=f"Aahar API error: {response.status_code}",
                status_code=response.status_code,
                response_data=response_data,
            )

        return response_data

    except requests.ConnectionError:
        raise AaharServiceError("Cannot connect to Aahar server. Please check the URL and network.")
    except requests.Timeout:
        raise AaharServiceError("Aahar server request timed out. Please try again.")
    except requests.RequestException as e:
        raise AaharServiceError(f"Aahar request failed: {str(e)}")


# =================================================================
# API #1: restaurant_service_mapping (Restaurant → Hotel/Aahar)
# =================================================================
def register_restaurant_mapping(aahar_service_id, domain):
    """
    Register/link a restaurant with a hotel in Aahar.
    Endpoint: PUT /api/restaurant_service_mapping
    Payload: {"restaurant_service_id": "2", "domain": "aatithya.vaiditech.in"}
    """
    logger.info(f"Registering restaurant mapping: service_id={aahar_service_id}, domain={domain}")

    data = {
        "restaurant_service_id": str(aahar_service_id),
        "domain": domain,
    }

    # This API is called on the hotel/Aahar domain
    if not domain.startswith("http"):
        import re
        is_ip = re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d+)?$', domain.split('/')[0])
        if is_ip or 'localhost' in domain or '127.0.0.1' in domain:
            base_url = f"http://{domain}/api"
        else:
            base_url = f"https://{domain}/api"
    else:
        base_url = domain
    return _make_request('PUT', 'restaurant_service_mapping', data=data, base_url=base_url)


# =================================================================
# API #2: room_booking_mapping (Hotel → Restaurant/Aahar)
# =================================================================
def send_room_booking_mapping(aahar_service_id, room_number, booking_id='', guest_name='', booking_number='', is_checkout_initiated=0):
    """
    Map a hotel room booking to the restaurant in Aahar.
    Endpoint: POST /store-room-booking-data
    """
    logger.info(f"Sending room booking mapping: service_id={aahar_service_id}, room={room_number}")

    data = {
        "restaurant_service_id": str(aahar_service_id),
        "room_number": str(room_number),
        "booking_id": str(booking_id),
        "guest_name": str(guest_name),
        "booking_number": str(booking_number),
        "ischeckoutinitiated": is_checkout_initiated
    }

    return _make_request('POST', 'store-room-booking-data', data=data)


# =================================================================
# API #3: get-hotel-order (Fetch orders from Aahar)
# =================================================================
def fetch_hotel_orders(aahar_service_id, room_number='', booking_id='', base_url=None):
    """
    Fetch hotel room orders from Aahar.
    Endpoint: POST /get-hotel-order
    Payload: {"restaurant_service_id": "2", "room_number": "101", "booking_id": ""}
    Returns: List of orders with items, totals, and invoice details.
    """
    logger.info(f"Fetching hotel orders: service_id={aahar_service_id}, room={room_number}")

    data = {
        "restaurant_service_id": str(aahar_service_id),
        "room_number": str(room_number),
        "booking_id": str(booking_id),
    }

    response = _make_request('POST', 'get-hotel-order', data=data, base_url=base_url)

    # Aahar returns {"code": 200, "data": [...]}
    if isinstance(response, dict) and 'data' in response:
        return response['data']
    return response


# =================================================================
# API #4: restaurant_order_payment_status (Hotel → Restaurant/Aahar)
# =================================================================
def send_payment_status(aahar_service_id, invoice, payment, mode='cash', payment_status='paid', base_url=None):
    """
    Notify Aahar that an order has been paid.
    Endpoint: POST /restaurant_order_payment_status
    """
    logger.info(f"Sending payment status: invoice={invoice}, amount={payment}, status={payment_status}")

    # Fetch order_sync from local DB to get order_billing_id and payment_id
    order_billing_id = None
    payment_id = None
    try:
        from restaurant.models import AaharOrderSync
        order_sync = AaharOrderSync.objects.filter(invoice=invoice).first()
        if order_sync:
            order_data = order_sync.order_data or {}
            
            # Extract order_billing_id from order_data if available, otherwise fallback to aahar_order_id
            if 'order_billing_id' in order_data and order_data['order_billing_id']:
                order_billing_id = order_data['order_billing_id']
            elif 'orders' in order_data and isinstance(order_data['orders'], list) and len(order_data['orders']) > 0:
                order_billing_id = order_data['orders'][0].get('order_billing_id')
            
            if not order_billing_id:
                order_billing_id = order_sync.aahar_order_id

            # Extract payment_id from order_data if nested, or check defaults
            if 'payment_id' in order_data and order_data['payment_id']:
                payment_id = order_data['payment_id']
            elif 'orders' in order_data and isinstance(order_data['orders'], list) and len(order_data['orders']) > 0:
                payment_id = order_data['orders'][0].get('payment_id')
    except Exception as e:
        logger.warning(f"Could not retrieve local order sync info: {e}")

    # Fallbacks for testing/direct calls
    if not order_billing_id:
        import re
        m = re.search(r'\d+', invoice)
        order_billing_id = int(m.group()) if m else 1
    if not payment_id:
        payment_id = 1

    data = {
        "restaurant_service_id": str(aahar_service_id),
        "orders": [
            {
                "order_billing_id": int(order_billing_id),
                "payment_id": int(payment_id),
                "payment_mode": str(mode),
                "amount": float(payment),
                "txn_id": "TXN-" + str(order_billing_id),
                "status": str(payment_status)
            }
        ]
    }

    return _make_request('POST', 'restaurant_order_payment_status', data=data, base_url=base_url)


# =================================================================
# Online Orders API #1: List Active Hotels
# =================================================================
def fetch_active_hotels(base_url=None, api_token=None):
    """
    Retrieves a list of all active restaurants/hotels participating in the online orders platform.
    Endpoint: GET /get-all-restaurants
    """
    logger.info("Fetching active hotels from Aahar online orders API")
    headers = {}
    if api_token:
        headers['Access-Token'] = api_token
        headers['Authorization'] = f'Bearer {api_token}'
    auth = (AAHAR_API_USER, AAHAR_API_PASSWORD) if AAHAR_API_USER else None
    response = _make_request('GET', 'get-all-restaurants', base_url=base_url, auth=auth, headers=headers)
    if isinstance(response, dict) and 'data' in response:
        return response['data']
    return response


# =================================================================
# Online Orders API #2: Get Hotel Menu
# =================================================================
def fetch_hotel_menu(restaurant_id, base_url=None):
    """
    Fetches the full active menu for a specific restaurant.
    Endpoint: POST /menu-sync
    """
    logger.info(f"Fetching menu for Aahar restaurant_id={restaurant_id} using base_url={base_url}")
    data = {
        "service_category_id": int(restaurant_id),
        "service_id": int(restaurant_id)
    }
    return _make_request('POST', 'menu-sync', data=data, base_url=base_url)


# =================================================================
# Online Orders API #3: Place an Order
# =================================================================
def submit_online_order(restaurant_id, order_data, base_url=None):
    """
    Submits a new order for a specific restaurant from an online portal.
    Endpoint: POST receive-external-order
    Payload: OrderCreate schema
    """
    logger.info(f"Submitting online order to Aahar restaurant_id={restaurant_id} base_url={base_url}")
    auth = ('vaiditech', '12345678')
    return _make_request('POST', 'receive-external-order', data=order_data, base_url=base_url, auth=auth)


def fetch_restaurant_details_from_domain(aahar_service_id, domain):
    """
    Fetches the details of a specific restaurant from the Aahar domain.
    """
    import re
    if not domain.startswith("http"):
        is_ip = re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d+)?$', domain.split('/')[0])
        if is_ip or 'localhost' in domain or '127.0.0.1' in domain:
            url_prefix = f"http://{domain}"
        else:
            url_prefix = f"https://{domain}"
    else:
        url_prefix = domain.rstrip('/')
    
    try:
        response = _make_request(
            'POST',
            'menu-sync',
            data={'service_category_id': str(aahar_service_id)},
            base_url=url_prefix,
        )
        if isinstance(response, dict) and response.get('code') == 200 and isinstance(response.get('data'), dict):
            details = response['data']
            details['service_category_id'] = str(aahar_service_id)
            return details
    except AaharServiceError as exc:
        logger.info("Aahar menu-sync detail lookup failed for service category %s: %s", aahar_service_id, exc)

    try:
        response = _make_request('GET', 'get-all-restaurants', base_url=url_prefix)
        hotels_data = response.get('data') if isinstance(response, dict) and 'data' in response else response
    except AaharServiceError as exc:
        raise AaharServiceError(f"Unable to fetch restaurant details from Aahar domain: {exc}")


    def candidate_ids(hotel):
        candidates = [
            hotel.get('id'),
            hotel.get('restaurant_id'),
            hotel.get('restaurant_service_id'),
            hotel.get('service_category_id'),
            hotel.get('service_id'),
            hotel.get('category_id'),
        ]
        service_category = hotel.get('service_category')
        if isinstance(service_category, dict):
            candidates.extend([
                service_category.get('id'),
                service_category.get('service_category_id'),
                service_category.get('restaurant_service_id'),
            ])
        service_categories = hotel.get('service_categories')
        if isinstance(service_categories, list):
            for category in service_categories:
                if isinstance(category, dict):
                    candidates.extend([
                        category.get('id'),
                        category.get('service_category_id'),
                        category.get('restaurant_service_id'),
                    ])
                else:
                    candidates.append(category)
        return [str(candidate) for candidate in candidates if candidate not in (None, '')]

    if isinstance(hotels_data, list):
        for hotel in hotels_data:
            if str(aahar_service_id) in candidate_ids(hotel):
                return hotel
    raise AaharServiceError(f"Restaurant with ID {aahar_service_id} not found on Aahar domain.")
