"""Testing background jobs

Due to the asynchronous nature of background jobs, code that uses them needs
to be handled specially when writing tests.

A common approach is to use the mock package to replace the
ckan.plugins.toolkit.enqueue_job function with a mock that executes jobs
synchronously instead of asynchronously
"""
from unittest import mock
import pathlib

import pytest
import requests

import ckan.tests.factories as factories

import dcor_shared
from dcor_shared import s3cc
from dcor_shared.testing import (
    make_dataset_via_s3, make_resource_via_s3, synchronous_enqueue_job
)

data_path = pathlib.Path(__file__).parent / "data"


@pytest.mark.ckan_config('ckan.plugins', 'dcor_depot dcor_schemas dc_view')
@pytest.mark.usefixtures('clean_db', 'with_request_context')
@mock.patch('ckan.plugins.toolkit.enqueue_job',
            side_effect=synchronous_enqueue_job)
def test_create_preview_s3_job(enqueue_job_mock):
    user = factories.User()
    owner_org = factories.Organization(users=[{
        'name': user['id'],
        'capacity': 'admin'
    }])

    create_context = {'ignore_auth': False, 'user': user['name'],
                      'api_version': 3}
    dataset = make_dataset_via_s3(create_context,
                                  owner_org,
                                  activate=False)
    path = data_path / "calibration_beads_47.rtdc"
    rid = make_resource_via_s3(
        resource_path=path,
        organization_id=owner_org['id'],
        dataset_id=dataset['id'],
    )

    # the file is uploaded to S3
    assert s3cc.artifact_exists(resource_id=rid,
                                artifact="resource")
    # the preview is generated by the background job
    assert s3cc.artifact_exists(resource_id=rid,
                                artifact="preview")


@pytest.mark.ckan_config('ckan.plugins', 'dcor_depot dcor_schemas dc_view')
@pytest.mark.usefixtures('clean_db', 'with_request_context')
@mock.patch('ckan.plugins.toolkit.enqueue_job',
            side_effect=synchronous_enqueue_job)
def test_create_preview_s3_job_alternate(enqueue_job_mock):
    user = factories.User()
    owner_org = factories.Organization(users=[{
        'name': user['id'],
        'capacity': 'admin'
    }])

    create_context = {'ignore_auth': False,
                      'user': user['name'],
                      'api_version': 3}
    ds_dict, res_dict = make_dataset_via_s3(
        create_context,
        owner_org,
        resource_path=data_path / "calibration_beads_47.rtdc",
        activate=True)
    bucket_name = dcor_shared.get_ckan_config_option(
        "dcor_object_store.bucket_name").format(
        organization_id=ds_dict["organization"]["id"])
    rid = res_dict["id"]
    object_name = f"preview/{rid[:3]}/{rid[3:6]}/{rid[6:]}"
    endpoint = dcor_shared.get_ckan_config_option(
        "dcor_object_store.endpoint_url")
    prev_url = f"{endpoint}/{bucket_name}/{object_name}"
    response = requests.get(prev_url)
    assert response.ok, "resource is public"
    assert response.status_code == 200
