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)

[((369, 468), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""expiration_time, expected_status"""', "[(None, 201), ('aksdjhasd', 400)]"], {}), "('expiration_time, expected_status', [(None, 201), (\n    'aksdjhasd', 400)])\n", (392, 468), False, 'import pytest\n'), ((1609, 2020), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""manifest_exists,test_tag,expected_status"""', "[(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)])\n", (1632, 2020), False, 'import pytest\n'), ((2953, 3213), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""repo_namespace, repo_name, query_count"""', "[('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)])\n", (2976, 3213), False, 'import pytest\n'), ((3475, 3506), 'data.database.Manifest.media_type.get_name', 'Manifest.media_type.get_name', (['(1)'], {}), '(1)\n', (3503, 3506), False, 'from data.database import Manifest\n'), ((594, 634), 'endpoints.test.shared.client_with_identity', 'client_with_identity', (['"""devtable"""', 'client'], {}), "('devtable', client)\n", (614, 634), False, 'from endpoints.test.shared import client_with_identity\n'), ((833, 918), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', (['cl', 'RepositoryTag', '"""put"""', 'params', 'request_body', 'expected_status'], {}), "(cl, RepositoryTag, 'put', params, request_body,\n    expected_status)\n", (849, 918), False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((971, 1011), 'endpoints.test.shared.client_with_identity', 'client_with_identity', (['"""devtable"""', 'client'], {}), "('devtable', client)\n", (991, 1011), False, 'from endpoints.test.shared import client_with_identity\n'), ((1142, 1196), 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', (['"""devtable"""', '"""simple"""'], {}), "('devtable', 'simple')\n", (1174, 1196), False, 'from data.registry_model import registry_model\n'), ((1211, 1258), 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', (['repo_ref', '"""latest"""'], {}), "(repo_ref, 'latest')\n", (1238, 1258), False, 'from data.registry_model import registry_model\n'), ((1417, 1486), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', (['cl', 'RepositoryTag', '"""put"""', 'params', 'request_body', '(201)'], {}), "(cl, RepositoryTag, 'put', params, request_body, 201)\n", (1433, 1486), False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((1501, 1548), 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', (['repo_ref', '"""latest"""'], {}), "(repo_ref, 'latest')\n", (1528, 1548), False, 'from data.registry_model import registry_model\n'), ((2209, 2249), 'endpoints.test.shared.client_with_identity', 'client_with_identity', (['"""devtable"""', 'client'], {}), "('devtable', client)\n", (2229, 2249), False, 'from endpoints.test.shared import client_with_identity\n'), ((3579, 3619), 'endpoints.test.shared.client_with_identity', 'client_with_identity', (['"""devtable"""', 'client'], {}), "('devtable', client)\n", (3599, 3619), False, 'from endpoints.test.shared import client_with_identity\n'), ((3781, 3840), 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', (['repo_namespace', 'repo_name'], {}), '(repo_namespace, repo_name)\n', (3813, 3840), False, 'from data.registry_model import registry_model\n'), ((3862, 3914), 'data.registry_model.registry_model.list_repository_tag_history', 'registry_model.list_repository_tag_history', (['repo_ref'], {}), '(repo_ref)\n', (3904, 3914), False, 'from data.registry_model import registry_model\n'), ((2339, 2393), 'data.registry_model.registry_model.lookup_repository', 'registry_model.lookup_repository', (['"""devtable"""', '"""simple"""'], {}), "('devtable', 'simple')\n", (2371, 2393), False, 'from data.registry_model import registry_model\n'), ((2416, 2463), 'data.registry_model.registry_model.get_repo_tag', 'registry_model.get_repo_tag', (['repo_ref', '"""latest"""'], {}), "(repo_ref, 'latest')\n", (2443, 2463), False, 'from data.registry_model import registry_model\n'), ((2868, 2953), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', (['cl', 'RepositoryTag', '"""put"""', 'params', 'request_body', 'expected_status'], {}), "(cl, RepositoryTag, 'put', params, request_body,\n    expected_status)\n", (2884, 2953), False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((3640, 3671), 'playhouse.test_utils.assert_query_count', 'assert_query_count', (['query_count'], {}), '(query_count)\n', (3658, 3671), False, 'from playhouse.test_utils import assert_query_count\n'), ((2718, 2742), 'pytest.raises', 'pytest.raises', (['Exception'], {}), '(Exception)\n', (2731, 2742), False, 'import pytest\n'), ((2760, 2845), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', (['cl', 'RepositoryTag', '"""put"""', 'params', 'request_body', 'expected_status'], {}), "(cl, RepositoryTag, 'put', params, request_body,\n    expected_status)\n", (2776, 2845), False, 'from endpoints.api.test.shared import conduct_api_call\n'), ((3692, 3747), 'endpoints.api.test.shared.conduct_api_call', 'conduct_api_call', (['cl', 'ListRepositoryTags', '"""get"""', 'params'], {}), "(cl, ListRepositoryTags, 'get', params)\n", (3708, 3747), False, 'from endpoints.api.test.shared import conduct_api_call\n')]