"""
Tests focused on validating AssonantDataLogger integration in beamlines

This tests will evaluate AssonantDataLogger functionalities with some real data
and real metadata.csv files from beamlines. The goal here is to verify if nothing will
break when going to production in the beamline.
"""

import json
import os

import pytest

from assonant.data_logger import AssonantDataLogger
from assonant.naming_standards import AcquisitionType, BeamlineName, ExperimentStage


@pytest.mark.parametrize("beamline_name", [beamline_name for beamline_name in BeamlineName])
@pytest.mark.forked  # This is MANDATORY for this test to correctly isolate env variables for EPICS_CA_ADDR_LIST
def test_log_nexus_file_from_real_bluesky_data_files_from_files(
    beamline_name, real_csv_metadata_file_path_map, tmp_path, real_bluesky_data_test_cases_dir_path_map
):
    """
    Validate that AssonantDataLogger works correctly when using real beamline
    csv metadata to log real beamline bluesky data if directly accessing
    bluesky json files.

    PS: Content is not being validated only if module does not break!

    Expected Behavior:
        - Tests must be manually evaluated as expected behavior may vary among test cases, but
        it is important to check if overall generate structure within nexus file is standardized
        as expected.
    """
    if not os.path.exists(real_csv_metadata_file_path_map[beamline_name.value]):
        pytest.skip(reason=f"CSV metadata for {beamline_name} does not exist yet!")
    elif beamline_name.value not in real_bluesky_data_test_cases_dir_path_map.keys():
        pytest.skip(reason=f"There is no test case with real data for {beamline_name} beamline yet!")
    else:
        log_file_name = f"test_{beamline_name.value}_file"

        data_logger = AssonantDataLogger(
            beamline_name,
            data_schema_file_path=real_csv_metadata_file_path_map[beamline_name.value],
        )

        for i in range(0, len(real_bluesky_data_test_cases_dir_path_map[beamline_name.value])):
            # Execute test for each test case dir that exist for that beamline
            test_case_dir = real_bluesky_data_test_cases_dir_path_map[beamline_name.value][i]
            log_file_path = tmp_path / f"test_case_{i}"

            for test_case_file in os.scandir(test_case_dir):
                if test_case_file.is_file() and test_case_file.name.endswith(".json"):
                    data_logger.log_bluesky_data_from_json_file(
                        log_file_path,
                        log_file_name,
                        ExperimentStage.SAMPLE_ACQUISITION,
                        AcquisitionType.SNAPSHOT_AT_START,
                        test_case_file.path,
                    )
                    data_logger.log_bluesky_data_from_json_file(
                        log_file_path,
                        log_file_name,
                        ExperimentStage.SAMPLE_ACQUISITION,
                        AcquisitionType.SCAN,
                        test_case_file.path,
                    )
                    data_logger.log_bluesky_data_from_json_file(
                        log_file_path,
                        log_file_name,
                        ExperimentStage.SAMPLE_ACQUISITION,
                        AcquisitionType.SNAPSHOT_AT_END,
                        test_case_file.path,
                    )


@pytest.mark.parametrize("beamline_name", [beamline_name for beamline_name in BeamlineName])
@pytest.mark.forked  # This is MANDATORY for this test to correctly isolate env variables for EPICS_CA_ADDR_LIST
def test_log_nexus_file_from_real_bluesky_data_files_from_documents_list(
    beamline_name, real_csv_metadata_file_path_map, tmp_path, real_bluesky_data_test_cases_dir_path_map
):
    """
    Validate that AssonantDataLogger works correctly when using real beamline
    csv metadata to log real beamline bluesky data if directly accessing
    bluesky json files.

    PS: Content is not being validated only if module does not break!

    Expected Behavior:
        - Tests must be manually evaluated as expected behavior may vary among test cases, but
        it is important to check if overall generate structure within nexus file is standardized
        as expected.
    """
    if not os.path.exists(real_csv_metadata_file_path_map[beamline_name.value]):
        pytest.skip(reason=f"CSV metadata for {beamline_name} does not exist yet!")
    elif beamline_name.value not in real_bluesky_data_test_cases_dir_path_map.keys():
        pytest.skip(reason=f"There is no test case with real data for {beamline_name} beamline yet!")
    else:
        log_file_name = f"test_{beamline_name.value}_file"

        data_logger = AssonantDataLogger(
            beamline_name,
            data_schema_file_path=real_csv_metadata_file_path_map[beamline_name.value],
        )

        for i in range(0, len(real_bluesky_data_test_cases_dir_path_map[beamline_name.value])):
            # Execute test for each test case dir that exist for that beamline
            test_case_dir = real_bluesky_data_test_cases_dir_path_map[beamline_name.value][i]
            log_file_path = tmp_path / f"test_case_{i}"

            for test_case_file in os.scandir(test_case_dir):
                if test_case_file.is_file() and test_case_file.name.endswith(".json"):

                    with open(test_case_file) as f:
                        test_case_file_data = json.load(f)

                    data_logger.log_bluesky_data_from_documents_list(
                        log_file_path,
                        log_file_name,
                        ExperimentStage.SAMPLE_ACQUISITION,
                        AcquisitionType.SNAPSHOT_AT_START,
                        test_case_file_data,
                    )
                    data_logger.log_bluesky_data_from_documents_list(
                        log_file_path,
                        log_file_name,
                        ExperimentStage.SAMPLE_ACQUISITION,
                        AcquisitionType.SCAN,
                        test_case_file_data,
                    )
                    data_logger.log_bluesky_data_from_documents_list(
                        log_file_path,
                        log_file_name,
                        ExperimentStage.SAMPLE_ACQUISITION,
                        AcquisitionType.SNAPSHOT_AT_END,
                        test_case_file_data,
                    )
