import pytest

from playhouse.test_utils import assert_query_count

from data.registry_model import registry_model
from data.database import Manifest

from endpoints.api.test.shared import conduct_api_call
from endpoints.test.shared import client_with_identity
from endpoints.api.tag import RepositoryTag, RestoreTag, ListRepositoryTags

from test.fixtures import *


@pytest.mark.parametrize(
    "expiration_time, expected_status",
    [
        (None, 201),
        ("aksdjhasd", 400),
    ],
)
def test_change_tag_expiration_default(expiration_time, expected_status, client, app):
    with client_with_identity("devtable", client) as cl:
        params = {
            "repository": "devtable/simple",
            "tag": "latest",
        }

        request_body = {
            "expiration": expiration_time,
        }

        conduct_api_call(cl, RepositoryTag, "put", params, request_body, expected_status)


def test_change_tag_expiration(client, app):
    with client_with_identity("devtable", client) as cl:
        params = {
            "repository": "devtable/simple",
            "tag": "latest",
        }

        repo_ref = registry_model.lookup_repository("devtable", "simple")
        tag = registry_model.get_repo_tag(repo_ref, "latest")

        updated_expiration = tag.lifetime_start_ts + 60 * 60 * 24

        request_body = {
            "expiration": updated_expiration,
        }

        conduct_api_call(cl, RepositoryTag, "put", params, request_body, 201)
        tag = registry_model.get_repo_tag(repo_ref, "latest")
        assert tag.lifetime_end_ts == updated_expiration


@pytest.mark.parametrize(
    "manifest_exists,test_tag,expected_status",
    [
        (True, "-INVALID-TAG-NAME", 400),
        (True, ".INVALID-TAG-NAME", 400),
        (
            True,
            "INVALID-TAG_NAME-BECAUSE-THIS-IS-WAY-WAY-TOO-LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG",
            400,
        ),
        (False, "newtag", 404),
        (True, "generatemanifestfail", None),
        (True, "latest", 201),
        (True, "newtag", 201),
    ],
)
def test_move_tag(manifest_exists, test_tag, expected_status, client, app):
    with client_with_identity("devtable", client) as cl:
        test_image = "unknown"
        if manifest_exists:
            repo_ref = registry_model.lookup_repository("devtable", "simple")
            tag_ref = registry_model.get_repo_tag(repo_ref, "latest")
            assert tag_ref

            test_image = tag_ref.manifest.digest

        params = {"repository": "devtable/simple", "tag": test_tag}
        request_body = {"manifest_digest": test_image}
        if expected_status is None:
            with pytest.raises(Exception):
                conduct_api_call(cl, RepositoryTag, "put", params, request_body, expected_status)
        else:
            conduct_api_call(cl, RepositoryTag, "put", params, request_body, expected_status)


@pytest.mark.parametrize(
    "repo_namespace, repo_name, query_count",
    [
        ("devtable", "simple", 4),
        ("devtable", "history", 4),
        ("devtable", "complex", 4),
        ("devtable", "gargantuan", 4),
        ("buynlarge", "orgrepo", 6),  # +2 for permissions checks.
        ("buynlarge", "anotherorgrepo", 6),  # +2 for permissions checks.
    ],
)
def test_list_repo_tags(repo_namespace, repo_name, client, query_count, app):
    # Pre-cache media type loads to ensure consistent query count.
    Manifest.media_type.get_name(1)

    params = {"repository": repo_namespace + "/" + repo_name}
    with client_with_identity("devtable", client) as cl:
        with assert_query_count(query_count):
            tags = conduct_api_call(cl, ListRepositoryTags, "get", params).json["tags"]

        repo_ref = registry_model.lookup_repository(repo_namespace, repo_name)
        history, _ = registry_model.list_repository_tag_history(repo_ref)
        assert len(tags) == len(history)

[(15, 'pytest.mark.parametrize', 'pytest.mark.parametrize', False, 'import pytest\n'), (57, 'pytest.mark.parametrize', 'pytest.mark.parametrize', False, 'import pytest\n'), (92, 'pytest.mark.parametrize', 'pytest.mark.parametrize', False, 'import pytest\n'), (105, 'data.database.Manifest.media_type.get_name', 'Manifest.media_type.get_name', False, 'from data.database import Manifest\n'), (23, 'endpoints.test.shared.client_with_identity', 'client_with_identity', False, 'from endpoints.test.shared import client_with_identity\n'), (33, 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', False, 'from endpoints.api.test.shared import conduct_api_call\n'), (37, 'endpoints.test.shared.client_with_identity', 'client_with_identity', False, 'from endpoints.test.shared import client_with_identity\n'), (43, 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', False, 'from data.registry_model import registry_model\n'), (44, 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', False, 'from data.registry_model import registry_model\n'), (52, 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', False, 'from endpoints.api.test.shared import conduct_api_call\n'), (53, 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', False, 'from data.registry_model import registry_model\n'), (74, 'endpoints.test.shared.client_with_identity', 'client_with_identity', False, 'from endpoints.test.shared import client_with_identity\n'), (108, 'endpoints.test.shared.client_with_identity', 'client_with_identity', False, 'from endpoints.test.shared import client_with_identity\n'), (112, 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', False, 'from data.registry_model import registry_model\n'), (113, 'data.registry_model.registry_model.list_repository_tag_history', 'registry_model.list_repository_tag_history', False, 'from data.registry_model import registry_model\n'), (77, 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', False, 'from data.registry_model import registry_model\n'), (78, 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', False, 'from data.registry_model import registry_model\n'), (89, 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', False, 'from endpoints.api.test.shared import conduct_api_call\n'), (109, 'playhouse.test_utils.assert_query_count', 'assert_query_count', False, 'from playhouse.test_utils import assert_query_count\n'), (86, 'pytest.raises', 'pytest.raises', False, 'import pytest\n'), (87, 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', False, 'from endpoints.api.test.shared import conduct_api_call\n'), (110, 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', False, 'from endpoints.api.test.shared import conduct_api_call\n')]