from typing import Iterable, Any, Optional
from singer_sdk import typing as th
from singer_sdk.streams import RESTStream
from singer_sdk.helpers.types import Context
from singer_sdk.helpers.jsonpath import extract_jsonpath
from singer_sdk.authenticators import APIKeyAuthenticator

class HostStream(RESTStream):
    records_jsonpath = "$[*]"
    name = "hosts"
    path = "/nms/api/v2.1/devices"

    @property
    def url_base(self) -> str:
        return self.config['uisp_url']

    @property
    def schema(self) -> dict:
        return th.PropertiesList(
            th.Property("hostname", th.StringType),
            th.Property("ip", th.StringType)
        ).to_dict()

    @property
    def authenticator(self) -> APIKeyAuthenticator:
        auth_headers = self._get_bearer_token()
        token = auth_headers["x-auth-token"]
        return APIKeyAuthenticator.create_for_stream(
            stream=self,
            key="x-auth-token",
            value=token,
            location="header",
        )
        
    def _get_bearer_token(self) -> dict:
        if not hasattr(self, "_auth_headers"):
            auth_url = self.config["uisp_url"] + '/nms/api/v2.1/user/login'
            payload = {
                "username": self.config["uisp"]["username"],
                "password": self.config["uisp"]["password"]
            }
            response = self.requests_session.post(auth_url, json=payload)

            response.raise_for_status()

            x_auth_token = response.headers.get("x-auth-token")

            self._auth_headers = {
                "x-auth-token": x_auth_token,
            }

        return self._auth_headers

    def parse_response(self, response: Any) -> Iterable[dict]:
        all_records = extract_jsonpath(self.records_jsonpath, input=response.json())

        for item in all_records:
            ident = item.get("identification", {}) or {}
            ip_address = item.get("ipAddress") or ""
            if ident.get("type") != "olt" or ip_address == "":
                continue

            yield {
                "hostname": ident.get("name"),
                "ip": ip_address.split("/")[0]
            }

class OltStream(HostStream):
