import pytest
from unittest import mock

from awx.api.versioning import reverse
from awx.main.utils import decrypt_field
from awx.main.models.workflow import (
    WorkflowJobTemplate, WorkflowJobTemplateNode, WorkflowApprovalTemplate
)
from awx.main.models.jobs import JobTemplate
from awx.main.tasks import deep_copy_model_obj


@pytest.mark.django_db
def test_job_template_copy(post, get, project, inventory, machine_credential, vault_credential,
                           credential, alice, job_template_with_survey_passwords, admin):
    job_template_with_survey_passwords.project = project
    job_template_with_survey_passwords.inventory = inventory
    job_template_with_survey_passwords.save()
    job_template_with_survey_passwords.credentials.add(credential)
    job_template_with_survey_passwords.credentials.add(machine_credential)
    job_template_with_survey_passwords.credentials.add(vault_credential)
    job_template_with_survey_passwords.admin_role.members.add(alice)
    project.admin_role.members.add(alice)
    inventory.admin_role.members.add(alice)
    assert get(
        reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
        alice, expect=200
    ).data['can_copy'] is False
    assert get(
        reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
        admin, expect=200
    ).data['can_copy'] is True
    assert post(
        reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
        {'name': 'new jt name'}, alice, expect=403
    ).data['detail'] == 'Insufficient access to Job Template credentials.'
    jt_copy_pk = post(
        reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
        {'name': 'new jt name'}, admin, expect=201
    ).data['id']

    # give credential access to user 'alice'
    for c in (credential, machine_credential, vault_credential):
        c.use_role.members.add(alice)
        c.save()
    assert get(
        reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
        alice, expect=200
    ).data['can_copy'] is True
    jt_copy_pk_alice = post(
        reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
        {'name': 'new jt name'}, alice, expect=201
    ).data['id']

    jt_copy_admin = type(job_template_with_survey_passwords).objects.get(pk=jt_copy_pk)
    jt_copy_alice = type(job_template_with_survey_passwords).objects.get(pk=jt_copy_pk_alice)

    assert jt_copy_admin.created_by == admin
    assert jt_copy_alice.created_by == alice

    for jt_copy in (jt_copy_admin, jt_copy_alice):
        assert jt_copy.name == 'new jt name'
        assert jt_copy.project == project
        assert jt_copy.inventory == inventory
        assert jt_copy.playbook == job_template_with_survey_passwords.playbook
        assert jt_copy.credentials.count() == 3
        assert credential in jt_copy.credentials.all()
        assert vault_credential in jt_copy.credentials.all()
        assert machine_credential in jt_copy.credentials.all()
        assert job_template_with_survey_passwords.survey_spec == jt_copy.survey_spec


@pytest.mark.django_db
def test_project_copy(post, get, project, organization, scm_credential, alice):
    project.credential = scm_credential
    project.save()
    project.admin_role.members.add(alice)
    assert get(
        reverse('api:project_copy', kwargs={'pk': project.pk}), alice, expect=200
    ).data['can_copy'] is False
    project.organization.admin_role.members.add(alice)
    scm_credential.use_role.members.add(alice)
    assert get(
        reverse('api:project_copy', kwargs={'pk': project.pk}), alice, expect=200
    ).data['can_copy'] is True
    project_copy_pk = post(
        reverse('api:project_copy', kwargs={'pk': project.pk}),
        {'name': 'copied project'}, alice, expect=201
    ).data['id']
    project_copy = type(project).objects.get(pk=project_copy_pk)
    assert project_copy.created_by == alice
    assert project_copy.name == 'copied project'
    assert project_copy.organization == organization
    assert project_copy.credential == scm_credential


@pytest.mark.django_db
def test_inventory_copy(inventory, group_factory, post, get, alice, organization):
    group_1_1 = group_factory('g_1_1')
    group_2_1 = group_factory('g_2_1')
    group_2_2 = group_factory('g_2_2')