import json
import logging
import typing
from typing import Tuple

import aiohttp

from anova_wifi.exceptions import AnovaException, InvalidLogin
from anova_wifi.precission_cooker import AnovaPrecisionCooker

_LOGGER = logging.getLogger(__name__)

# Found here - https://github.com/ammarzuberi/pyanova-api/blob/master/anova/AnovaCooker.py and personally confirmed.
ANOVA_FIREBASE_KEY = "AIzaSyDQiOP2fTR9zvFcag2kSbcmG9zPh6gZhHw"


class AnovaApi:
    """A class to handle communicating with the anova api to get devices"""

    def __init__(
        self, session: aiohttp.ClientSession, username: str, password: str
    ) -> None:
        """Creates an anova api class"""
        self.session = session
        self.username = username
        self.password = password
        self._jwt: str | None = None
        self._firebase_jwt: str | None = None

    async def authenticate(self) -> bool:
        """Auth with Firebase server"""
        # Code loving yoinked from https://github.com/ammarzuberi/pyanova-api/blob/master/anova/AnovaCooker.py
        firebase_req_data = {
            "email": self.username,
            "password": self.password,
            "returnSecureToken": True,
        }

        firebase_req = await self.session.post(
            f"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key={ANOVA_FIREBASE_KEY}",
            json=firebase_req_data,
        )
        firebase_id_token_json = await firebase_req.json()
        self._firebase_jwt = firebase_id_token_json.get("idToken")

        if not self._firebase_jwt:
            raise InvalidLogin("Could not log in with Google Firebase")

        # Now authenticate with Anova using the Firebase ID token to get the JWT
        anova_auth_req = await self.session.post(
            "https://anovaculinary.io/authenticate",
            json={},
            headers={"firebase-token": self._firebase_jwt},
        )
        jwt_json = await anova_auth_req.json()
        jwt = jwt_json.get("jwt")  # Looks like this JWT is valid for an entire year...

        if not jwt:
            raise InvalidLogin("Could not authenticate with Anova")

        # Set JWT local variable
        self._jwt = jwt

        return True

    async def get_devices(self) -> typing.List[AnovaPrecisionCooker]:
        """Get all devices by connecting to anova websocket"""
        if self._firebase_jwt is None or self._jwt is None:
            raise AnovaException("Cannot get devices without first authenticating")
        url = f"https://devices.anovaculinary.io/?token={self._firebase_jwt}"
        user_devices = []
        async with aiohttp.ClientSession() as session:
            async with session.ws_connect(url) as ws:
                async for msg in ws:
                    # Filter messages based on the "command" field
                    data = json.loads(msg.data)
                    if data.get("command") == "EVENT_APC_WIFI_VERSION":
                        payload = data.get("payload")
                        devices: typing.List[Tuple[str, str]] = [
                            (d["cookerId"], d["type"]) for d in payload
                        ]
                        for device in devices:
                            user_devices.append(
                                AnovaPrecisionCooker(
                                    self.session, device[0], device[1], self._jwt
                                )
                            )
                        return user_devices
        return user_devices
