from __future__ import annotations

import time
from typing import TYPE_CHECKING, Callable

from ..errors import WhatsrbCloudError

if TYPE_CHECKING:
    from ..client import WhatsrbCloud
    from .message import Message


class Session:
    def __init__(self, data: dict, *, client: WhatsrbCloud | None = None):
        self.id = data.get("id")
        self.name = data.get("name")
        self.status = data.get("status")
        self.status_reason = data.get("status_reason")
        self.phone_number = data.get("phone_number")
        self.qr_code = data.get("qr_code")
        self.connected = data.get("connected")
        self.last_connected_at = data.get("last_connected_at")
        self.created_at = data.get("created_at")
        self.updated_at = data.get("updated_at")
        self._client = client
        self._raw = data

    @property
    def is_connected(self) -> bool:
        return self.connected is True or self.status == "connected"

    def send_message(self, *, to: str, text: str) -> Message:
        return self._messages_resource().create(to=to, text=text)

    def send_image(self, *, to: str, url: str) -> Message:
        return self._messages_resource().create(to=to, message_type="image", content=url)

    def send_document(self, *, to: str, url: str) -> Message:
        return self._messages_resource().create(to=to, message_type="document", content=url)

    def send_video(self, *, to: str, url: str) -> Message:
        return self._messages_resource().create(to=to, message_type="video", content=url)

    def send_audio(self, *, to: str, url: str) -> Message:
        return self._messages_resource().create(to=to, message_type="audio", content=url)

    def send_location(self, *, to: str, latitude: float, longitude: float) -> Message:
        return self._messages_resource().create(
            to=to, message_type="location", content=f"{latitude},{longitude}"
        )

    def send_contact(self, *, to: str, name: str, phone: str) -> Message:
        return self._messages_resource().create(
            to=to, message_type="contact", content=f"{name}:{phone}"
        )

    def messages(self):
        return self._messages_resource()

    def reload(self) -> Session:
        refreshed = self._client.sessions.retrieve(self.id)
        self.status = refreshed.status
        self.status_reason = refreshed.status_reason
        self.phone_number = refreshed.phone_number
        self.qr_code = refreshed.qr_code
        self.connected = refreshed.connected
        self.last_connected_at = refreshed.last_connected_at
        self.name = refreshed.name
        self.updated_at = refreshed.updated_at
        return self

    def refresh(self) -> Session:
        return self.reload()

    def wait_for_qr(
        self,
        *,
        timeout: int = 60,
        interval: int = 2,
        on_qr: Callable[[str], None] | None = None,
    ) -> Session:
        deadline = time.time() + timeout

        while True:
            self.reload()
            if self.status == "qr_pending" and self.qr_code and on_qr:
                on_qr(self.qr_code)
            if self.is_connected:
                return self
            if time.time() >= deadline:
                raise WhatsrbCloudError("Timed out waiting for QR scan")
            time.sleep(interval)

    def to_dict(self) -> dict:
        return self._raw

    def _messages_resource(self):
        return self._client.messages(self.id)
