from collections import defaultdict
from math import ceil
from datetime import datetime, timedelta, date
from django.shortcuts import render
from django.conf import settings
from .forms import ReservationInlineGuestForm
from .ohip import (
    get_inventory_statistics_with_roomtype_list,
    create_reservation_inline_guest,
    get_valid_token,
)

PACKAGE_ROOM_MAP = {
    "A": [
        (settings.OHIP_ROOM_TYPE1, settings.OHIP_ROOM_NIGHT1),
        (settings.OHIP_ROOM_TYPE2, settings.OHIP_ROOM_NIGHT2),
        (settings.OHIP_ROOM_TYPE3, settings.OHIP_ROOM_NIGHT3),
    ],
    "B": [
        (settings.OHIP_ROOM_TYPE4, settings.OHIP_ROOM_NIGHT1),
        (settings.OHIP_ROOM_TYPE5, settings.OHIP_ROOM_NIGHT2),
        (settings.OHIP_ROOM_TYPE6, settings.OHIP_ROOM_NIGHT3),
    ],
    "C": [
        (settings.OHIP_ROOM_TYPE7, settings.OHIP_ROOM_NIGHT1),
        (settings.OHIP_ROOM_TYPE8, settings.OHIP_ROOM_NIGHT2),
        (settings.OHIP_ROOM_TYPE9, settings.OHIP_ROOM_NIGHT3),
    ],
}

def get_package_availability_summary_init(room_data, package_map, arrival_date):
    summary = {}
    for pkg_name, room_nights in package_map.items():
        day_pointer = arrival_date
        min_values = []

        for room_type, nights in room_nights:
            dates = [(day_pointer + timedelta(days=i)).strftime("%m-%d<br>%a") for i in range(nights)]
            availability_values = [
                room_data.get(room_type, {}).get(date) for date in dates
            ]
            numeric_values = [v for v in availability_values if v is not None]
            if numeric_values:
                min_values.append(min(numeric_values))
            day_pointer += timedelta(days=nights)

        summary[pkg_name] = min(min_values) if min_values else "-"
    return summary
    print("DEBUG: Package Summary Init:", summary_init)

def get_package_availability_summary(room_data, package_map, all_dates_sorted):
    from collections import defaultdict
    from datetime import datetime, timedelta

    package_summary = defaultdict(dict)

    for raw_date_str, _ in all_dates_sorted:
        date_obj = datetime.strptime(raw_date_str, "%Y-%m-%d").date()
        formatted_key = f"{date_obj.strftime('%m-%d')}<br>{date_obj.strftime('%a')}"

        for pkg_name, room_nights in package_map.items():
            day_pointer = date_obj
            min_values = []

            for room_type, nights in room_nights:
                dates = [
                    (day_pointer + timedelta(days=i)).strftime("%m-%d<br>%a")
                    for i in range(nights)
                ]
                availability_values = [
                    room_data.get(room_type, {}).get(date) for date in dates
                ]
                numeric_values = [v for v in availability_values if isinstance(v, (int, float))]
                if numeric_values:
                    min_values.append(min(numeric_values))
                day_pointer += timedelta(days=nights)

            package_summary[pkg_name][formatted_key] = min(min_values) if min_values else "-"

    return package_summary
    print("DEBUG: Package Summary Full:", summary_full)

def inventory_and_reservation_view(request):
    token = get_valid_token()
    today = datetime.today().date()
    start_date = today.strftime("%Y-%m-%d")
    end_date = (today + timedelta(days=27)).strftime("%Y-%m-%d")
    raw_data = get_inventory_statistics_with_roomtype_list(token=token, start_date=start_date, end_date=end_date)

    room_data = defaultdict(dict)
    all_dates = set()
    statistics = raw_data[0]["statistics"] if isinstance(raw_data, list) and raw_data else []

    for stat in statistics:
        if stat.get("statCategoryCode") != "HotelRoomCode":
            continue

        stat_code = stat.get("statCode")
        label = stat_code

        for entry in stat.get("statisticDate", []):
            date_str = entry.get("statisticDate")
            if not date_str:
                continue
            value = next((inv["value"] for inv in entry.get("inventory", []) if inv["code"] == "AvailableRooms"), None)
            date_obj = datetime.strptime(date_str, "%Y-%m-%d")
            raw_date = date_obj.strftime('%Y-%m-%d')
            formatted_date = f"{date_obj.strftime('%m-%d')}<br>{date_obj.strftime('%a')}"
            room_data[label][formatted_date] = value
            all_dates.add((raw_date, formatted_date))

    all_dates_sorted = sorted(all_dates, key=lambda x: x[0])
    date_headers = []
    for raw_date, _ in all_dates_sorted:
        date_obj = datetime.strptime(raw_date, "%Y-%m-%d")
        formatted = f"{date_obj.strftime('%m-%d')}<br>{date_obj.strftime('%a')}"
        date_headers.append(formatted)


    ordered_room_types = []
    for package in ["A", "B", "C"]:
        ordered_room_types.extend(rt for rt, _ in PACKAGE_ROOM_MAP.get(package, []))

    sorted_room_data = {
        rt: room_data[rt] for rt in ordered_room_types if rt in room_data
    }

    message = None
    message_type = None
    response_data = []
    reservation_ids = []
    confirmation_numbers = []
    total_nights = None

    if request.method == "POST":
        form = ReservationInlineGuestForm(request.POST)
        if form.is_valid():
            first_name = form.cleaned_data["first_name"]
            last_name = form.cleaned_data["last_name"]
            arrival_date = form.cleaned_data["arrival_date"]
            package = form.cleaned_data["package"]
            room_nights = PACKAGE_ROOM_MAP.get(package, [])

            total_nights = sum(n for _, n in room_nights)
            departure_date = arrival_date + timedelta(days=total_nights)

            current_date = arrival_date
            for room_type, nights in room_nights:
                next_date = current_date + timedelta(days=nights)
                result = create_reservation_inline_guest(
                    token=token,
                    arrival_date=current_date.strftime('%Y-%m-%d'),
                    departure_date=next_date.strftime('%Y-%m-%d'),
                    guest_first_name=first_name,
                    guest_last_name=last_name,
                    room_type=room_type
                )
                response_data.append(result)

                if result["status"] == "success":
                    reservation_ids.append(result.get("reservation_id"))
                    confirmation_numbers.append(result.get("confirmation_number", "N/A"))

                current_date = next_date

            if reservation_ids:
                message_type = "success"
                message = (
                    f"✅ Reservations created!<br>"
                    f"<strong>IDs:</strong> {', '.join(reservation_ids)}<br>"
                    f"<strong>Confirmations:</strong> {', '.join(confirmation_numbers)}"
                )
            else:
                message_type = "danger"
                message = "❌ Reservation failed. See details below."
    else:
        default_package = "A"
        room_nights = PACKAGE_ROOM_MAP[default_package]
        total_nights = sum(n for _, n in room_nights)

        form = ReservationInlineGuestForm(initial={
            "arrival_date": today,
            "departure_date": today + timedelta(days=total_nights),
            "package": default_package
        })

    form_arrival_date = form["arrival_date"].value()
    if isinstance(form_arrival_date, datetime):
        parsed_arrival_date = form_arrival_date.date()
    elif isinstance(form_arrival_date, str):
        parsed_arrival_date = datetime.strptime(form_arrival_date, "%Y-%m-%d").date()
    elif isinstance(form_arrival_date, date):
        parsed_arrival_date = form_arrival_date
    else:
        parsed_arrival_date = today

    #package_summary = get_package_availability_summary_init(sorted_room_data, PACKAGE_ROOM_MAP, parsed_arrival_date)
    package_summary = dict(get_package_availability_summary(sorted_room_data, PACKAGE_ROOM_MAP, all_dates_sorted))

    return render(request, "book_engine/inventory_and_reservation.html", {
        "form": form,
        "message": message,
        "message_type": message_type,
        "response_data": response_data,
        "total_nights": total_nights,
        "room_data": sorted_room_data,
        "date_headers": date_headers,
        "package_summary": package_summary,
    })

from django.views.decorators.http import require_GET
from django.http import JsonResponse

@require_GET
def refresh_room_data(request):
    token = get_valid_token()
    today = datetime.today().date()
    start_date = today.strftime("%Y-%m-%d")
    end_date = (today + timedelta(days=27)).strftime("%Y-%m-%d")
    raw_data = get_inventory_statistics_with_roomtype_list(token=token, start_date=start_date, end_date=end_date)

    room_data = defaultdict(dict)
    all_dates = set()
    statistics = raw_data[0]["statistics"] if isinstance(raw_data, list) and raw_data else []

    for stat in statistics:
        if stat.get("statCategoryCode") != "HotelRoomCode":
            continue
        stat_code = stat.get("statCode")
        for entry in stat.get("statisticDate", []):
            date_str = entry.get("statisticDate")
            if not date_str:
                continue
            value = next((inv["value"] for inv in entry.get("inventory", []) if inv["code"] == "AvailableRooms"), None)
            date_obj = datetime.strptime(date_str, "%Y-%m-%d")
            raw_date = date_obj.strftime('%Y-%m-%d')
            formatted_date = f"{date_obj.strftime('%m-%d')}<br>{date_obj.strftime('%a')}"
            room_data[stat_code][formatted_date] = value
            all_dates.add((raw_date, formatted_date))

    all_dates_sorted = sorted(all_dates, key=lambda x: x[0])
    date_headers = [f"{datetime.strptime(d[0], '%Y-%m-%d').strftime('%m-%d')}<br>{datetime.strptime(d[0], '%Y-%m-%d').strftime('%a')}" for d in all_dates_sorted]

    ordered_room_types = []
    for package in ["A", "B", "C"]:
        ordered_room_types.extend(rt for rt, _ in PACKAGE_ROOM_MAP.get(package, []))

    sorted_room_data = {
        rt: room_data[rt] for rt in ordered_room_types if rt in room_data
    }

    return JsonResponse({
        "date_headers": date_headers,
        "room_data": sorted_room_data,
    })


@require_GET
def refresh_package_data(request):
    token = get_valid_token()
    today = datetime.today().date()
    start_date = today.strftime("%Y-%m-%d")
    end_date = (today + timedelta(days=27)).strftime("%Y-%m-%d")
    raw_data = get_inventory_statistics_with_roomtype_list(token=token, start_date=start_date, end_date=end_date)

    room_data = defaultdict(dict)
    all_dates = set()
    statistics = raw_data[0]["statistics"] if isinstance(raw_data, list) and raw_data else []

    for stat in statistics:
        if stat.get("statCategoryCode") != "HotelRoomCode":
            continue
        stat_code = stat.get("statCode")
        for entry in stat.get("statisticDate", []):
            date_str = entry.get("statisticDate")
            if not date_str:
                continue
            value = next((inv["value"] for inv in entry.get("inventory", []) if inv["code"] == "AvailableRooms"), None)
            date_obj = datetime.strptime(date_str, "%Y-%m-%d")
            raw_date = date_obj.strftime('%Y-%m-%d')
            formatted_date = f"{date_obj.strftime('%m-%d')}<br>{date_obj.strftime('%a')}"
            room_data[stat_code][formatted_date] = value
            all_dates.add((raw_date, formatted_date))

    all_dates_sorted = sorted(all_dates, key=lambda x: x[0])
    ordered_room_types = []
    for package in ["A", "B", "C"]:
        ordered_room_types.extend(rt for rt, _ in PACKAGE_ROOM_MAP.get(package, []))

    sorted_room_data = {
        rt: room_data[rt] for rt in ordered_room_types if rt in room_data
    }

    package_summary = dict(get_package_availability_summary(sorted_room_data, PACKAGE_ROOM_MAP, all_dates_sorted))
    date_headers = [f"{datetime.strptime(d[0], '%Y-%m-%d').strftime('%m-%d')}<br>{datetime.strptime(d[0], '%Y-%m-%d').strftime('%a')}" for d in all_dates_sorted]

    return JsonResponse({
        "date_headers": date_headers,
        "package_summary": package_summary,
    })
