from datetime import datetime, timedelta, timezone

from .base import PMSConnector
from .errors import PMSChargeFailed, PMSInvalidRoom, PMSNoCheckedInGuest


class MockPMSConnector(PMSConnector):
    provider = "mock"

    def _rooms(self):
        return [str(room) for room in self.config.get("rooms", [])]

    def _secure_room_id(self, room_id):
        hotel = self.config.get("hotel") or "default"
        return f"{hotel}-room-{room_id}-mock"

    def getGuestByRoom(self, room_id):
        reservation = self.getReservation(room_id)
        return {
            "roomId": reservation["roomId"],
            "reservationId": reservation["reservationId"],
            "displayName": "Checked-in guest",
        }

    def getReservation(self, room_id):
        room_id = str(room_id)
        if room_id not in self._rooms():
            raise PMSInvalidRoom("Room does not exist in mock PMS")
        checkout = datetime.now(timezone.utc) + timedelta(days=1)
        return {
            "roomId": room_id,
            "reservationId": f"mock-res-{room_id}",
            "checkInStatus": "checked_in",
            "checkOutStatus": "not_checked_out",
            "expiresAt": checkout.isoformat(),
        }

    def verifyGuest(self, room_id, secure_room_id=None):
        reservation = self.getReservation(room_id)
        expected = self._secure_room_id(room_id)
        if secure_room_id and secure_room_id not in (expected, room_id):
            raise PMSNoCheckedInGuest("Secure room identifier does not match this room")
        return {**reservation, "verified": True}

    def getCheckedInGuests(self):
        return [self.getGuestByRoom(room) for room in self._rooms()]

    def getRoomStatus(self, room_id):
        self.getReservation(room_id)
        return {"roomId": str(room_id), "status": "occupied"}

    def postChargeToRoom(self, charge):
        amount = float(charge.get("amount") or 0)
        if amount < 0:
            raise PMSChargeFailed("Charge amount cannot be negative")
        return {
            "status": "posted",
            "pmsReference": f"mock-charge-{charge.get('idempotencyKey') or charge.get('orderId')}",
        }

    def getCheckInStatus(self, room_id):
        return self.getReservation(room_id)["checkInStatus"]

    def getCheckOutStatus(self, room_id):
        return self.getReservation(room_id)["checkOutStatus"]
