#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#

import urllib.parse
from abc import ABC
from typing import Any, Iterable, Mapping, MutableMapping, Optional

import requests
from airbyte_cdk.sources.streams.http import HttpStream


class OrbitStream(HttpStream, ABC):
    url_base = "https://app.orbit.love/api/v1/"

    def __init__(self, workspace: str, start_date: Optional[str] = None, **kwargs):
        super().__init__(**kwargs)
        self.workspace = workspace
        self.start_date = start_date

    def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
        return None

    def parse_response(
        self,
        response: requests.Response,
        stream_state: Mapping[str, Any] = None,
        stream_slice: Mapping[str, Any] = None,
        next_page_token: Mapping[str, Any] = None,
    ) -> Iterable[Mapping]:
        data = response.json()
        records = data["data"]
        yield from records


class OrbitStreamPaginated(OrbitStream):
    def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, str]]:
        decoded_response = response.json()
        links = decoded_response.get("links")
        if not links:
            return None

        next = links.get("next")
        if not next:
            return None

        next_url = urllib.parse.urlparse(next)
        return {str(k): str(v) for (k, v) in urllib.parse.parse_qsl(next_url.query)}

    def request_params(
        self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None
    ) -> MutableMapping[str, Any]:

        params = super().request_params(stream_state, stream_slice, next_page_token)
        return {**params, **next_page_token} if next_page_token else params


class Members(OrbitStreamPaginated):
    # Docs: https://docs.orbit.love/reference/members-overview
    primary_key = "id"

    def path(
        self, stream_state: Mapping[str, Any] = None, stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None
    ) -> str:
        return f"{self.workspace}/members"

    def request_params(
        self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None
    ) -> MutableMapping[str, Any]:

        params = super().request_params(stream_state, stream_slice, next_page_token)
        params["sort"] = "created_at"
        if self.start_date is not None:
            params["start_date"] = self.start_date  # The start_date parameter is filtering the last_activity_occurred_at field
        return params


class Workspace(OrbitStream):
    # Docs: https://docs.orbit.love/reference/get_workspaces-workspace-slug
    # This stream is primarily used for connnection checking.
    primary_key = "id"

    def path(
        self, stream_state: Mapping[str, Any] = None, stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None
    ) -> str:
        return f"workspaces/{self.workspace}"

    def parse_response(
        self,
        response: requests.Response,
        stream_state: Mapping[str, Any] = None,
        stream_slice: Mapping[str, Any] = None,
        next_page_token: Mapping[str, Any] = None,
    ) -> Iterable[Mapping]:
        data = response.json()
        yield data["data"]
