# Copyright 2022 The Debusine developers
# See the AUTHORS file at the top-level directory of this distribution
#
# This file is part of Debusine. It is subject to the license terms
# in the LICENSE file found in the top-level directory of this
# distribution. No part of Debusine, including this file, may be copied,
# modified, propagated, or distributed except according to the terms
# contained in the LICENSE file.

"""Utility functions for tests."""

from collections.abc import Iterator
from datetime import datetime, timedelta, timezone
from typing import Any, Optional

from debusine.client.models import (
    ArtifactResponse,
    PaginatedResponse,
    StrictBaseModel,
    WorkRequestResponse,
)


def data_generator(size: int) -> Iterator[bytes]:
    """
    Return a data generator of size bytes.

    Each time generates different data.
    """
    number = 0
    while True:
        chunk = bytearray()

        while len(chunk) < size:
            s = str(number).encode("ascii")
            remaining_space = size - len(chunk)
            chunk.extend(s[:remaining_space])
            number += 1
        yield bytes(chunk)


def yesterday() -> datetime:
    """Return datetime of yesterday."""
    return datetime.now(timezone.utc) - timedelta(days=1)


def tomorrow() -> datetime:
    """Return datetime of tomorrow."""
    return datetime.now(timezone.utc) + timedelta(days=1)


def date_time_to_isoformat_rest_framework(value: datetime) -> str:
    """
    Django REST serialize datetime in a specific way.

    It is reimplemented (simplified) here for Debusine client tests (which
    do not use Django REST).

    See rest_framework/fields.py, DateTimeField.to_representation.
    """
    value_str = value.isoformat()
    if value_str.endswith("+00:00"):
        value_str = value_str[:-6] + "Z"

    return value_str


def create_artifact_response(**kwargs) -> ArtifactResponse:
    """Return an ArtifactResponse. Use defaults for certain fields."""
    defaults: dict[str, Any] = {
        "category": "Testing",
        "data": {},
        "files_to_upload": [],
        "created_at": datetime.utcnow(),
        "workspace": "Testing",
        "download_tar_gz_url": "https://example.com/some-path",
    }
    defaults.update(kwargs)

    return ArtifactResponse(**defaults)


def create_work_request_response(**kwargs) -> WorkRequestResponse:
    """Return a WorkRequestResponse. Use defaults for certain fields."""
    defaults: dict[str, Any] = {
        "id": 11,
        "created_at": datetime.utcnow(),
        "status": "pending",
        "result": "",
        "task_name": "sbuild",
        "task_data": {},
        "artifacts": [],
        "workspace": "Testing",
    }
    defaults.update(kwargs)

    return WorkRequestResponse(**defaults)


def create_listing_response(
    *args: StrictBaseModel, next_url: Optional[str] = None
) -> PaginatedResponse:
    """Return a single page of PaginatedResponse, containing args."""
    return PaginatedResponse(
        next=next_url,
        results=[arg.dict() for arg in args],
    )
