"""Shared read helpers used by both the LLM agent tools and the plain REST hospital API,
so the two surfaces don't duplicate query/formatting logic."""

import json
from datetime import date as date_cls

from sqlalchemy.orm import Session

from app.db.models import Appointment, Doctor, Property, SiteVisit

_DAY_KEYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]  # matches date.weekday() 0..6


def doctor_summary(d: Doctor) -> dict:
    return {
        "id": d.id,
        "name": d.name,
        "specialization": d.specialization,
        "department": d.department_name,
        "branch": d.branch,
        "fee": d.consultation_fee,
        "rating": d.rating,
        "status": d.status,
        "next_available": d.next_available,
    }


def doctor_detail(d: Doctor) -> dict:
    return {
        **doctor_summary(d),
        "qualification": d.qualification,
        "experience_years": d.experience_years,
        "languages": [x.strip() for x in d.languages.split(",") if x.strip()],
        "bio": d.bio,
        "reviews": d.reviews,
    }


def _to_minutes(hhmm: str) -> int:
    h, m = hhmm.split(":")
    return int(h) * 60 + int(m)


def _label(minutes: int) -> str:
    h24, m = divmod(minutes, 60)
    ampm = "PM" if h24 >= 12 else "AM"
    h12 = h24 % 12 or 12
    return f"{h12:02d}:{m:02d} {ampm}"


def compute_slots(db: Session, doctor: Doctor, iso_date: str) -> list[dict]:
    """Real availability: the doctor's weekly template for that weekday, minus any
    already-confirmed appointment at the same doctor/date/time."""
    schedule = json.loads(doctor.schedule_json or "[]")
    day_key = _DAY_KEYS[date_cls.fromisoformat(iso_date).weekday()]
    day = next((d for d in schedule if d.get("day") == day_key), None)
    if not day or not day.get("enabled"):
        return []

    booked = {
        a.time
        for a in db.query(Appointment).filter(
            Appointment.doctor_id == doctor.id,
            Appointment.date == iso_date,
            Appointment.status == "confirmed",
        )
    }

    slot_duration = day["slotDuration"]
    slots: list[dict] = []
    for session in day["sessions"]:
        t = _to_minutes(session["start"])
        end = _to_minutes(session["end"])
        while t + slot_duration <= end:
            label = _label(t)
            slots.append({"time": label, "available": label not in booked})
            t += slot_duration
    return slots


def property_summary(p: Property) -> dict:
    return {
        "id": p.id,
        "title": p.title,
        "type": p.type,
        "bhk": p.bhk,
        "city": p.city,
        "locality": p.locality,
        "price": p.price,
        "area_sqft": p.area_sqft,
        "status": p.status,
    }


# Standard site-visit slots, offered every day (unlike doctors, properties don't have a
# per-listing weekly schedule — a fixed daily template is realistic and much simpler).
VISIT_TIMES = ["10:00 AM", "11:30 AM", "01:00 PM", "03:30 PM", "05:00 PM"]


def compute_visit_slots(db: Session, property_id: str, iso_date: str) -> list[dict]:
    """Real availability: the fixed daily slot template, minus any already-confirmed
    site visit for the same property/date/time (a property can only be shown once per slot)."""
    booked = {
        v.time
        for v in db.query(SiteVisit).filter(
            SiteVisit.property_id == property_id,
            SiteVisit.date == iso_date,
            SiteVisit.status == "confirmed",
        )
    }
    return [{"time": t, "available": t not in booked} for t in VISIT_TIMES]
