import re
import httpx
from copy import deepcopy
import httpx
from app.core.config import settings

def process_sources(sources_document: list[str], use_source_ids: list[str]) -> list[str]:
     sources = []
     for source_document in sources_document:
          source_document = source_document.model_dump()
          metadata = source_document.get("metadata")
          source_id = metadata.get("source_id")
          metadata = {
               "title": metadata.get("title"),
               "start_timestamp": metadata.get("start_timestamp"),
               "page_content": source_document.get("page_content")
          }
          if source_id in use_source_ids:
               sources.append(metadata)
     return sources

# Internal fields that provide no value to an AI assistant
REMOVE_KEYS = {
    "room_stay_id",
    "reserv_id",
    "customer_id",
    "customerId",
    "travellerId",
    "customer_traveller_id",
    "current_billing",
    "product_id",
    "type_id",
    "policy_id",
    "sub_hotel_id",
    "tax_id",
    "res_tax_id",
    "created_by_user",
    "products_added_while_create",
    "room_number_locked_indicator",
    "source_of_creation",
    "auto_added",
    "collect_which",
    "siteminder_id",
    "selectedRatePlanId",
}
 
# Sensitive fields
SENSITIVE_KEYS = {
    "card_number",
    "credit_card",
    "card",
    "cc_number",
    "cvv",
    "cvc",
    "expiry",
    "expiration",
    "token",
    "payment_token",
    "auth_token",
    "access_token",
    "refresh_token",
    "password",
    "secret",
    "pin",
    "ssn",
}
 
# Keys that are almost always duplicated / internal
REMOVE_DUPLICATE_SECTIONS = {
    "reservation_data",  # same data exists in reservation
}
 
 
def _looks_sensitive(value):
    if not isinstance(value, str):
        return False
 
    # Possible raw credit card number
    digits = re.sub(r"\D", "", value)
    if 13 <= len(digits) <= 19:
        return True
 
    return False
 
 
def _clean(obj):
    if isinstance(obj, dict):
        cleaned = {}
 
        for k, v in obj.items():
 
            # remove duplicate top-level sections
            if k in REMOVE_DUPLICATE_SECTIONS:
                continue
 
            if k in REMOVE_KEYS:
                continue
 
            if k.lower() in SENSITIVE_KEYS:
                continue
 
            if _looks_sensitive(v):
                continue
 
            value = _clean(v)
 
            # remove empty values
            if value in (
                None,
                "",
                [],
                {},
            ):
                continue
 
            cleaned[k] = value
 
        return cleaned
 
    elif isinstance(obj, list):
        result = []
 
        seen = set()
 
        for item in obj:
            item = _clean(item)
 
            if item in (None, "", {}, []):
                continue
 
            # remove duplicate objects
            marker = repr(item)
            if marker in seen:
                continue
 
            seen.add(marker)
            result.append(item)
 
        return result
 
    return obj
 
 
def clean_reservation_payload(payload: dict) -> dict:

    payload = deepcopy(payload)
 
    cleaned = _clean(payload)
 
    # reservation_data duplicates reservation
    if (
        "reservation" in cleaned
        and "reservation_data" in cleaned
    ):
        cleaned.pop("reservation_data", None)
 
    # reservation.overalltotals duplicates overall_totals
    reservation = cleaned.get("reservation")
    if isinstance(reservation, dict):
        reservation.pop("overalltotals", None)
 
        # resortFeePos already exists inside pos[]
        reservation.pop("resortFeePos", None)
 
    return cleaned
 
async def get_reservation(confirmation_number: str, email: str, hotel_id: str, sub_hotel_id: str):
    try:
        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.post(
                settings.LS_API_URL + "frontend/Reservations/loadOrderInfo",
                json={
                    "confirmation": confirmation_number,
                    "get_payment_data": False
                },
                headers={
                    "hotel_id": hotel_id,
                    "sub_hotel_id": sub_hotel_id,
                })
            data = response.json()
            if data.get("status", "") == "success":
                return clean_reservation_payload(data.get("data"))
            else:
                return {"error": "Reservation not found. Confirmation number (Itenrary) or email is incorrect."}
    except Exception as e:
        print(f"Error getting reservation: {e}")
        return {"error": "Error getting reservation. Please try again later."}

async def get_available_addons(
    hotel_id: str,
    sub_hotel_id: str | None = None,
) -> dict:

    if not hotel_id:
        return {"error": "Hotel ID is required to look up available products and add-ons."}

    headers = {
        "Hotelid": str(hotel_id),
        "current_version": "12",
        "Content-Type": "application/json",
        "ls-bot-key": settings.LS_BOT_TOKEN,
    }
    if sub_hotel_id:
        headers["sub_hotel_id"] = str(sub_hotel_id)

    payload = {
        "typeofService": "retail",
        "happy_hours": False,
        "dataPerPage": 150,
    }

    try:
        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.post(
                settings.LS_API_URL + "Checkout/skipAcl_getFilteredProducts",
                headers=headers,
                json=payload,
            )
            data = response.json()
    except Exception as e:
        print(f"Error getting available add-ons: {e}")
        return {
            "error": "Unable to load available products and add-ons right now. Please try again later."
        }

    if not isinstance(data, dict):
        return {"error": "Unable to load available products and add-ons right now."}
    
    products = data.get("products", {}).get("products", []) or []

    if not products:
        return {
            "message": "No products or add-on options are currently available for this hotel.",
            "products": [],
        }

    return {
        "products": products,
    }