from datetime import datetime

from bson import ObjectId
from motor.motor_asyncio import AsyncIOMotorCollection

from domain.availability import build_stylist_availability


class MongoAvailabilityRepository:
    def __init__(
        self,
        service_collection: AsyncIOMotorCollection,
        salon_collection: AsyncIOMotorCollection,
        stylist_collection: AsyncIOMotorCollection,
        appointment_collection: AsyncIOMotorCollection,
    ):
        self._services = service_collection
        self._salons = salon_collection
        self._stylists = stylist_collection
        self._appointments = appointment_collection

    async def get_next_7_days_availability(
        self, service_id: str, requested_date: str, timezone: str
    ) -> list[dict]:
        service = await self._services.find_one({"_id": ObjectId(service_id)})
        if not service:
            return []

        salon = await self._salons.find_one({"_id": service["salonId"]})
        if not salon:
            return []

        salon_timezone = salon.get("timezone") or timezone or "Asia/Kolkata"
        service_oid = ObjectId(service_id)
        salon_oid = salon["_id"]

        stylists = await self._stylists.find(
            {"salonId": salon_oid, "services": service_oid, "active": True},
        ).to_list(length=None)

        if not stylists:
            return []

        from zoneinfo import ZoneInfo

        tz = ZoneInfo(salon_timezone)
        requested_local = datetime.strptime(requested_date, "%Y-%m-%d").replace(tzinfo=tz)
        start_day = requested_local.replace(
            hour=0, minute=0, second=0, microsecond=0
        )
        query_from = start_day.astimezone(ZoneInfo("UTC"))

        appointments = await self._appointments.find(
            {
                "salonId": salon_oid,
                "stylistId": {"$in": [stylist["_id"] for stylist in stylists]},
                "status": {"$in": ["pending", "confirmed"]},
                "start": {"$gte": query_from},
            },
        ).to_list(length=None)

        duration = int(service.get("duration") or 0)
        results = []
        for stylist in stylists:
            days = build_stylist_availability(
                stylist,
                salon,
                appointments,
                duration,
                start_day,
                salon_timezone,
            )
            results.append(
                {
                    "stylistId": str(stylist["_id"]),
                    "name": stylist.get("name") or "Unknown stylist",
                    "days": days,
                }
            )
        return results
