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, 1, 21, 1), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(16, 4, 16, 38): '"""expiration_time, expected_status"""', (17, 4, 20, 5): "[(None, 201), ('aksdjhasd', 400)]"}, {}), "('expiration_time, expected_status', [(None, 201), (\n    'aksdjhasd', 400)])", False, 'import pytest\n'), ((57, 1, 72, 1), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(58, 4, 58, 46): '"""manifest_exists,test_tag,expected_status"""', (59, 4, 71, 5): "[(True, '-INVALID-TAG-NAME', 400), (True, '.INVALID-TAG-NAME', 400), (True,\n    'INVALID-TAG_NAME-BECAUSE-THIS-IS-WAY-WAY-TOO-LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG'\n    , 400), (False, 'newtag', 404), (True, 'generatemanifestfail', None), (\n    True, 'latest', 201), (True, 'newtag', 201)]"}, {}), "('manifest_exists,test_tag,expected_status', [(True,\n    '-INVALID-TAG-NAME', 400), (True, '.INVALID-TAG-NAME', 400), (True,\n    'INVALID-TAG_NAME-BECAUSE-THIS-IS-WAY-WAY-TOO-LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG'\n    , 400), (False, 'newtag', 404), (True, 'generatemanifestfail', None), (\n    True, 'latest', 201), (True, 'newtag', 201)])", False, 'import pytest\n'), ((92, 1, 102, 1), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(93, 4, 93, 44): '"""repo_namespace, repo_name, query_count"""', (94, 4, 101, 5): "[('devtable', 'simple', 4), ('devtable', 'history', 4), ('devtable',\n    'complex', 4), ('devtable', 'gargantuan', 4), ('buynlarge', 'orgrepo', \n    6), ('buynlarge', 'anotherorgrepo', 6)]"}, {}), "('repo_namespace, repo_name, query_count', [(\n    'devtable', 'simple', 4), ('devtable', 'history', 4), ('devtable',\n    'complex', 4), ('devtable', 'gargantuan', 4), ('buynlarge', 'orgrepo', \n    6), ('buynlarge', 'anotherorgrepo', 6)])", False, 'import pytest\n'), ((105, 4, 105, 35), 'data.database.Manifest.media_type.get_name', 'Manifest.media_type.get_name', ({(105, 33, 105, 34): '(1)'}, {}), '(1)', False, 'from data.database import Manifest\n'), ((23, 9, 23, 49), 'endpoints.test.shared.client_with_identity', 'client_with_identity', ({(23, 30, 23, 40): '"""devtable"""', (23, 42, 23, 48): 'client'}, {}), "('devtable', client)", False, 'from endpoints.test.shared import client_with_identity\n'), ((33, 8, 33, 89), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', ({(33, 25, 33, 27): 'cl', (33, 29, 33, 42): 'RepositoryTag', (33, 44, 33, 49): '"""put"""', (33, 51, 33, 57): 'params', (33, 59, 33, 71): 'request_body', (33, 73, 33, 88): 'expected_status'}, {}), "(cl, RepositoryTag, 'put', params, request_body,\n    expected_status)", False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((37, 9, 37, 49), 'endpoints.test.shared.client_with_identity', 'client_with_identity', ({(37, 30, 37, 40): '"""devtable"""', (37, 42, 37, 48): 'client'}, {}), "('devtable', client)", False, 'from endpoints.test.shared import client_with_identity\n'), ((43, 19, 43, 73), 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', ({(43, 52, 43, 62): '"""devtable"""', (43, 64, 43, 72): '"""simple"""'}, {}), "('devtable', 'simple')", False, 'from data.registry_model import registry_model\n'), ((44, 14, 44, 61), 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', ({(44, 42, 44, 50): 'repo_ref', (44, 52, 44, 60): '"""latest"""'}, {}), "(repo_ref, 'latest')", False, 'from data.registry_model import registry_model\n'), ((52, 8, 52, 77), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', ({(52, 25, 52, 27): 'cl', (52, 29, 52, 42): 'RepositoryTag', (52, 44, 52, 49): '"""put"""', (52, 51, 52, 57): 'params', (52, 59, 52, 71): 'request_body', (52, 73, 52, 76): '(201)'}, {}), "(cl, RepositoryTag, 'put', params, request_body, 201)", False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((53, 14, 53, 61), 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', ({(53, 42, 53, 50): 'repo_ref', (53, 52, 53, 60): '"""latest"""'}, {}), "(repo_ref, 'latest')", False, 'from data.registry_model import registry_model\n'), ((74, 9, 74, 49), 'endpoints.test.shared.client_with_identity', 'client_with_identity', ({(74, 30, 74, 40): '"""devtable"""', (74, 42, 74, 48): 'client'}, {}), "('devtable', client)", False, 'from endpoints.test.shared import client_with_identity\n'), ((108, 9, 108, 49), 'endpoints.test.shared.client_with_identity', 'client_with_identity', ({(108, 30, 108, 40): '"""devtable"""', (108, 42, 108, 48): 'client'}, {}), "('devtable', client)", False, 'from endpoints.test.shared import client_with_identity\n'), ((112, 19, 112, 78), 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', ({(112, 52, 112, 66): 'repo_namespace', (112, 68, 112, 77): 'repo_name'}, {}), '(repo_namespace, repo_name)', False, 'from data.registry_model import registry_model\n'), ((113, 21, 113, 73), 'data.registry_model.registry_model.list_repository_tag_history', 'registry_model.list_repository_tag_history', ({(113, 64, 113, 72): 'repo_ref'}, {}), '(repo_ref)', False, 'from data.registry_model import registry_model\n'), ((77, 23, 77, 77), 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', ({(77, 56, 77, 66): '"""devtable"""', (77, 68, 77, 76): '"""simple"""'}, {}), "('devtable', 'simple')", False, 'from data.registry_model import registry_model\n'), ((78, 22, 78, 69), 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', ({(78, 50, 78, 58): 'repo_ref', (78, 60, 78, 68): '"""latest"""'}, {}), "(repo_ref, 'latest')", False, 'from data.registry_model import registry_model\n'), ((89, 12, 89, 93), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', ({(89, 29, 89, 31): 'cl', (89, 33, 89, 46): 'RepositoryTag', (89, 48, 89, 53): '"""put"""', (89, 55, 89, 61): 'params', (89, 63, 89, 75): 'request_body', (89, 77, 89, 92): 'expected_status'}, {}), "(cl, RepositoryTag, 'put', params, request_body,\n    expected_status)", False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((109, 13, 109, 44), 'playhouse.test_utils.assert_query_count', 'assert_query_count', ({(109, 32, 109, 43): 'query_count'}, {}), '(query_count)', False, 'from playhouse.test_utils import assert_query_count\n'), ((86, 17, 86, 41), 'pytest.raises', 'pytest.raises', ({(86, 31, 86, 40): 'Exception'}, {}), '(Exception)', False, 'import pytest\n'), ((87, 16, 87, 97), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', ({(87, 33, 87, 35): 'cl', (87, 37, 87, 50): 'RepositoryTag', (87, 52, 87, 57): '"""put"""', (87, 59, 87, 65): 'params', (87, 67, 87, 79): 'request_body', (87, 81, 87, 96): 'expected_status'}, {}), "(cl, RepositoryTag, 'put', params, request_body,\n    expected_status)", False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((110, 19, 110, 74), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', ({(110, 36, 110, 38): 'cl', (110, 40, 110, 58): 'ListRepositoryTags', (110, 60, 110, 65): '"""get"""', (110, 67, 110, 73): 'params'}, {}), "(cl, ListRepositoryTags, 'get', params)", False, 'from endpoints.api.test.shared import conduct_api_call\n')]