#
# # Copyright © 2026 Peak AI Limited. or its affiliates. All Rights Reserved.
# #
# # Licensed under the Apache License, Version 2.0 (the "License"). You
# # may not use this file except in compliance with the License. A copy of
# # the License is located at:
# #
# # https://github.com/PeakBI/peak-sdk/blob/main/LICENSE
# #
# # or in the "license" file accompanying this file. This file is
# # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# # ANY KIND, either express or implied. See the License for the specific
# # language governing permissions and limitations under the License.
# #
# # This file is part of the peak-sdk.
# # see (https://github.com/PeakBI/peak-sdk)
# #
# # You should have received a copy of the APACHE LICENSE, VERSION 2.0
# # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
#
"""S3 iteration operations."""

from __future__ import annotations

from itertools import chain
from typing import Any, Iterator

from botocore.client import BaseClient  # type: ignore[import-not-found]

from peak.tools.s3.s3_object import S3Object


def iter_raw_objects(s3_client: Any, bucket_name: str, prefix: str, delimiter: str = "") -> Iterator[dict[str, Any]]:
    """Iterate over "raw" s3 file objects using `list_objects_v2`.

    Given a provided `s3_client` instance and  `bucket_name`, returns an
    iterator over paginated response(s) from list_objects_v2, given prefix
    `prefix` and optional delimiter `delimiter`.

    Will return results in "raw" (dictionary) format.

    Parameters
    ----------
    s3_client:
        s3 client instance.
    bucket_name: str
        The s3 bucket name.
    prefix: str
        The prefix to search for objects in.
    delimiter: str, optional
        Optional string delimiter. If specified, list_objects_v2 will group
        objects with the same prefix up to the delimiter under a
        "CommonPrefixes" field. This can be used to emulate directory-like
        behaviour. Default="".

    Returns:
    -------
    Iterator[dict]
        Iterator over "raw" s3 object results.
    """
    paginator = s3_client.get_paginator("list_objects_v2")
    pages = paginator.paginate(Bucket=bucket_name, Prefix=prefix, Delimiter=delimiter)
    # create generator over page contents for all retrieved pages of results
    # note contents needs to be iterable, so use safe-getter and default to
    # empty list
    page_contents = (page.get("Contents", []) for page in pages)
    # chain all the page contents together
    return chain.from_iterable(page_contents)


def iter_objects(s3_client: BaseClient, bucket_name: str, prefix: str, delimiter: str = "") -> Iterator[S3Object]:
    """Iterate over s3 file objects using `list_objects_v2`.

    Given a provided `s3_client` instance and  `bucket_name`, returns an
    iterator over paginated response(s) from list_objects_v2, given prefix
    `prefix` and optional delimiter `delimiter`.

    Will return results in (validated) S3Object instance format.

    Parameters
    ----------
    s3_client:
        s3 client instance.
    bucket_name: str
        The s3 bucket name.
    prefix: str
        The prefix to search for objects in.
    delimiter: str, optional
        Optional string delimiter. If specified, list_objects_v2 will group
        objects with the same prefix up to the delimiter under a
        "CommonPrefixes" field. This can be used to emulate directory-like
        behaviour. Default="".

    Returns:
    -------
    Iterator[dict]
        Iterator over "raw" s3 object results.
    """
    return (S3Object.model_validate(raw_obj) for raw_obj in iter_raw_objects(s3_client, bucket_name, prefix, delimiter))
