from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

from use_cases.book_appointment_permissive import BookAppointmentPermissiveUseCase
from use_cases.resolve_offer_by_title import ResolveOfferByTitleUseCase
from use_cases.resolve_services_by_names import ResolveServicesByNamesUseCase


class BookAppointmentsUseCase:
    def __init__(
        self,
        resolve_services: ResolveServicesByNamesUseCase,
        resolve_offer: ResolveOfferByTitleUseCase,
        book_permissive: BookAppointmentPermissiveUseCase,
    ):
        self._resolve_services = resolve_services
        self._resolve_offer = resolve_offer
        self._book_permissive = book_permissive

    async def execute(
        self,
        *,
        salon_id: str,
        client_id: str,
        timezone: str,
        service_names: list[str],
        requested_start: dict[str, str],
        offer_title: str | None = None,
    ) -> dict | str:
        services = await self._resolve_services.execute(salon_id, service_names)
        if not services:
            return "I could not find the active services you requested."

        offer_id = None
        if offer_title:
            offer_id = await self._resolve_offer.execute(
                salon_id, client_id, offer_title
            )

        current_start = self._parse_local_start(requested_start, timezone)
        results: list[dict] = []

        for index, service in enumerate(services):
            slot = {
                "date": current_start.strftime("%Y-%m-%d"),
                "time": current_start.strftime("%H:%M"),
            }
            try:
                data = await self._book_permissive.execute(
                    salon_id=salon_id,
                    service_id=service.id,
                    client_id=client_id,
                    requested_start=slot,
                    offer_id=offer_id if index == 0 else None,
                )
                if not data.get("success"):
                    results.append(
                        {
                            "service": service.name,
                            "status": "failed",
                            "error": data.get("reason", "BOOKING_FAILED"),
                        }
                    )
                else:
                    results.append(
                        {"service": service.name, "status": "success", "data": data}
                    )
                    minutes = service.duration or 30
                    current_start += timedelta(minutes=minutes)
            except Exception as exc:
                results.append(
                    {"service": service.name, "status": "failed", "error": str(exc)}
                )

        return {"result": results}

    @staticmethod
    def _parse_local_start(requested_start: dict[str, str], timezone: str) -> datetime:
        date_str = requested_start["date"]
        time_str = requested_start["time"]
        local = datetime.strptime(f"{date_str} {time_str}", "%Y-%m-%d %H:%M")
        return local.replace(tzinfo=ZoneInfo(timezone))
