"""Testing functions for the CMT services."""

import strax
import straxen
import utilix
import numpy as np
from .test_basics import test_run_id_1T
from straxen.test_utils import nt_test_run_id as test_run_id_nT
from straxen.common import aux_repo
import unittest


@unittest.skipIf(not straxen.utilix_is_configured(), "No db access, cannot test!")
def test_connect_to_db():
    """Test connection to db."""
    corrections_collection = utilix.rundb.xent_collection(database="corrections")
    client = corrections_collection.database.client
    cmt = strax.CorrectionsInterface(client, database_name="corrections")
    df = cmt.read("global_xenonnt")
    mes = "Return empty dataframe when reading DB. Please check"
    assert not df.empty, mes


@unittest.skipIf(not straxen.utilix_is_configured(), "No db access, cannot test!")
def test_1T_elife():
    """Test elife from CMT DB against historical data(aux file)"""
    elife_conf = ("elife_xenon1t", "ONLINE", False)
    elife_cmt = straxen.get_correction_from_cmt(test_run_id_1T, elife_conf)
    elife_file = aux_repo + "3548132b55f81a43654dba5141366041e1daaf01/strax_files/elife.npy"
    x = straxen.get_resource(elife_file, fmt="npy")
    run_index = np.where(x["run_id"] == int(test_run_id_1T))[0]
    elife = x[run_index[0]]["e_life"]
    mes = "Elife values do not match. Please check"
    assert elife_cmt == elife, mes


@unittest.skipIf(not straxen.utilix_is_configured(), "No db access, cannot test!")
def test_cmt_conf_option(option="mlp_model", version="ONLINE", is_nT=True):
    """Test CMT conf options If wrong conf is passed it would raise an error accordingly."""
    conf = option, version, is_nT
    correction = straxen.get_correction_from_cmt(test_run_id_nT, conf)
    assert isinstance(correction, (float, int, str, np.ndarray))


@unittest.skipIf(not straxen.utilix_is_configured(), "No db access, cannot test!")
def test_mc_wrapper_elife(
    run_id="009000",
    cmt_id="016000",
    mc_id="mc_0",
):
    """Test that for two different run ids, we get different elifes using the MC wrapper.

    :param run_id: First run-id (used for normal query)
    :param cmt_id: Second run-id used as a CMT id (should not be the same as run_id! otherwise the
        values might actually be the same and the test does not work).
    :return: None

    """
    assert np.abs(int(run_id) - int(cmt_id)) > 500, "runs must be far apart"

    # First for the run-id let's get the value
    elife = straxen.get_correction_from_cmt(run_id, ("elife", "ONLINE", True))

    # Now, we repeat the same query using the MC wrapper, this should
    # give us a different result since we are now asking for a very
    # different run-number.
    mc_elife_diff = straxen.get_correction_from_cmt(
        mc_id, ("cmt_run_id", cmt_id, "elife", "ONLINE", True)
    )

    # Repeat the query from above to verify, let's see if we are getting
    # the same results as for `elife` above
    mc_elife_same = straxen.get_correction_from_cmt(
        mc_id, ("cmt_run_id", run_id, "elife", "ONLINE", True)
    )

    assert elife != mc_elife_diff
    assert elife == mc_elife_same


@unittest.skipIf(not straxen.utilix_is_configured(), "No db access, cannot test!")
def test_mc_wrapper_gains(
    run_id="009000",
    cmt_id="016000",
    mc_id="mc_0",
    execute=True,
):
    """Test that for two different run ids, we get different gains using the MC wrapper.

    :param run_id: First run-id (used for normal query)
    :param cmt_id: Second run-id used as a CMT id (should not be the same as run_id! otherwise the
        values might actually be the same and the test does not work).
    :param execute: Execute this test (this is set to False since the test takes 9 minutes which is
        too long. We can activate this if the testing time due to faster CMT queries is reduced).
    :return: None

    """
    if not execute:
        return
    assert np.abs(int(run_id) - int(cmt_id)) > 500, "runs must be far apart"

    # First for the run-id let's get the value
    gains = straxen.get_correction_from_cmt(run_id, ("to_pe_model", "ONLINE", True))

    # Now, we repeat the same query using the MC wrapper, this should
    # give us a different result since we are now asking for a very
    # different run-number.
    mc_gains_diff = straxen.get_correction_from_cmt(
        mc_id, ("cmt_run_id", cmt_id, "to_pe_model", "ONLINE", True)
    )

    # Repeat the query from above to verify, let's see if we are getting
    # the same results as for `gains` above
    mc_gains_same = straxen.get_correction_from_cmt(
        mc_id, ("cmt_run_id", run_id, "to_pe_model", "ONLINE", True)
    )

    assert not np.all(gains == mc_gains_diff)
    assert np.all(gains == mc_gains_same)


def test_is_cmt_option():
    """Catches if we change the CMT option structure.

    The example dummy_option works at least before Jun 13 2021

    """
    dummy_option = ("hit_thresholds_tpc", "ONLINE", True)
    assert straxen.is_cmt_option(dummy_option), "Structure of CMT options changed!"

    dummy_url_config = "cmt://correction?version=ONLINE&run_id=plugin.run_id"
    assert straxen.is_cmt_option(dummy_url_config), "Structure of CMT options changed!"


def test_replace_url_version():
    """Tests the replace_url_version function which is important in apply_cmt_version."""
    url = "cmt://elife?version=ONLINE&run_id=plugin.run_id"
    url_check = "cmt://elife?version=v1&run_id=plugin.run_id"
    url_test = straxen.corrections_services.replace_url_version(url, "v1")
    if url_check != url_test:
        raise AssertionError(
            "replace_url_version did not do its job! "
            f"it returns:\n{url_test}\nwhen it should return:\n{url_check}"
        )
