# -*- coding: utf-8 -*-

# Copyright (c) 2017 Ansible, Inc.
# All Rights Reserved.
import json
import pytest
import mock

from django.apps import apps

from awx.main.models import (
    UnifiedJob,
    NotificationTemplate,
    Credential,
)
from awx.main.models.credential import ssh

from awx.conf.migrations._reencrypt import encrypt_field
from awx.main.migrations._reencrypt import (
    _notification_templates,
    _credentials,
    _unified_jobs
)

from awx.main.utils import decrypt_field


@pytest.mark.django_db
def test_notification_template_migration():
    # Doesn't get tagged as UTF8 because the the internal save call explicitly sets skip_utf8=True
    with mock.patch('awx.main.models.notifications.encrypt_field', encrypt_field):
        nt = NotificationTemplate.objects.create(notification_type='slack', notification_configuration=dict(token='test'))


    assert nt.notification_configuration['token'].startswith('$encrypted$AES$')

    _notification_templates(apps)
    nt.refresh_from_db()

    assert nt.notification_configuration['token'].startswith('$encrypted$AESCBC$')
    assert decrypt_field(nt, 'notification_configuration', subfield='token') == 'test'

    # This is here for a side-effect.
    # Exception if the encryption type of AESCBC is not properly skipped, ensures
    # our `startswith` calls don't have typos
    _notification_templates(apps)


@pytest.mark.django_db
@pytest.mark.parametrize("old_enc, new_enc, value", [
    ('$encrypted$UTF8$AES', '$encrypted$UTF8$AESCBC$', u'Iñtërnâtiônàlizætiøn'),
    ('$encrypted$AES$', '$encrypted$AESCBC$', 'test'),
])
def test_credential_migration(old_enc, new_enc, value):
    with mock.patch('awx.main.models.credential.encrypt_field', encrypt_field):
        cred_type = ssh()
        cred_type.save()

        cred = Credential.objects.create(credential_type=cred_type, inputs=dict(password=value))

    assert cred.password.startswith(old_enc)

    _credentials(apps)
    cred.refresh_from_db()

    assert cred.password.startswith(new_enc)
    assert decrypt_field(cred, 'password') == value

    # This is here for a side-effect.
    # Exception if the encryption type of AESCBC is not properly skipped, ensures
    # our `startswith` calls don't have typos
    _credentials(apps)


@pytest.mark.django_db
@pytest.mark.parametrize("old_enc, new_enc, value", [
    ('$encrypted$AES$', '$encrypted$AESCBC$', u'Iñtërnâtiônàlizætiøn'),
    ('$encrypted$AES$', '$encrypted$AESCBC$', 'test'),
])
def test_unified_job_migration(old_enc, new_enc, value):
    with mock.patch('awx.main.models.base.encrypt_field', encrypt_field):
        uj = UnifiedJob.objects.create(launch_type='manual', start_args=json.dumps({'test':value}))

    assert uj.start_args.startswith(old_enc)

    _unified_jobs(apps)
    uj.refresh_from_db()

    assert uj.start_args.startswith(new_enc)
    assert json.loads(decrypt_field(uj, 'start_args')) == {'test':value}

    # This is here for a side-effect.
    # Exception if the encryption type of AESCBC is not properly skipped, ensures
    # our `startswith` calls don't have typos
    _unified_jobs(apps)
