from __future__ import annotations

from datetime import datetime
from typing import TYPE_CHECKING

from esiosapy.managers.base import BaseArchiveManager
from esiosapy.utils.request_helper import RequestHelper


if TYPE_CHECKING:
    from esiosapy.models.archive.archive import Archive
    from esiosapy.models.archive.archive_date_type import ArchiveDateType


class ArchiveManager(BaseArchiveManager[RequestHelper]):
    """
    Manages archive-related operations for the ESIOS API.

    This class provides methods to retrieve and filter archives from the ESIOS
    API, such as listing all archives or filtering them by date or date range.
    """

    def __init__(self, request_helper: RequestHelper) -> None:
        """
        Initializes the ArchiveManager with a RequestHelper.

        :param request_helper: An instance of RequestHelper used to make API requests.
        """
        super().__init__(request_helper)

    def list_all(self) -> list[Archive]:
        """
        Retrieves a list of all archives.

        This method sends a GET request to the `/archives` endpoint and
        returns a list of Archive objects representing all available archives.

        :return: A list of Archive objects representing all archives.
        """
        response = self.request_helper.get_request(self._endpoint)
        return [self._init_archive(archive) for archive in response.json()["archives"]]

    def list_by_date(
        self,
        target_dt: datetime | str,
        date_type: ArchiveDateType | None = None,
        taxonomy_terms: list[str] | None = None,
    ) -> list[Archive]:
        """
        Retrieves a list of archives filtered by a specific date.

        This method sends a GET request to the `/archives` endpoint with filters
        based on the provided date, date type, and optional taxonomy terms.

        :param target_dt: The target date for filtering archives. Can be a datetime
                          object or an ISO 8601 formatted string.
        :param date_type: The type of date to filter by (e.g., publication date),
                          defaults to None.
        :param taxonomy_terms: A list of taxonomy terms to further filter the archives,
                               defaults to None.
        :return: A list of Archive objects filtered by the specified date.
        """
        if isinstance(target_dt, datetime):
            target_dt = target_dt.strftime("%Y-%m-%dT%H:%M:%S.%f%z")

        params: dict[str, str | int | list[str]] = {"date": target_dt}
        if date_type:
            params["date_type"] = date_type.value
        if taxonomy_terms:
            params["taxonomy_terms[]"] = taxonomy_terms

        response = self.request_helper.get_request(self._endpoint, params=params)
        return [self._init_archive(archive) for archive in response.json()["archives"]]

    def list_by_date_range(
        self,
        target_dt_start: datetime | str,
        target_dt_end: datetime | str,
        date_type: ArchiveDateType | None = None,
        taxonomy_terms: list[str] | None = None,
    ) -> list[Archive]:
        """
        Retrieves a list of archives filtered by a date range.

        This method sends a GET request to the `/archives` endpoint with filters
        based on the provided start and end dates, date type, and optional taxonomy
        terms.

        :param target_dt_start: The start date for filtering archives. Can be a datetime
                                object or an ISO 8601 formatted string.
        :param target_dt_end: The end date for filtering archives. Can be a datetime
                              object or an ISO 8601 formatted string.
        :param date_type: The type of date to filter by (e.g., publication date),
                          defaults to None.
        :param taxonomy_terms: A list of taxonomy terms to further filter the archives,
                               defaults to None.
        :return: A list of Archive objects filtered by the specified date range.
        """
        if isinstance(target_dt_start, datetime):
            target_dt_start = target_dt_start.strftime("%Y-%m-%dT%H:%M:%S.%f%z")
        if isinstance(target_dt_end, datetime):
            target_dt_end = target_dt_end.strftime("%Y-%m-%dT%H:%M:%S.%f%z")

        params: dict[str, str | int | list[str]] = {
            "start_date": target_dt_start,
            "end_date": target_dt_end,
        }
        if date_type:
            params["date_type"] = date_type.value
        if taxonomy_terms:
            params["taxonomy_terms[]"] = taxonomy_terms

        response = self.request_helper.get_request(self._endpoint, params=params)
        return [self._init_archive(archive) for archive in response.json()["archives"]]
