"""Fixtures for workflow tests."""

import subprocess
import sys
from pathlib import Path

import pytest
import yaml
from qualpipe.tests.conftest import *  # noqa: D100, F403

# Import WorkflowGroup from test module - add the parent directory to sys.path
sys.path.insert(0, str(Path(__file__).parent))
from test_run_workflows import WorkflowGroup


def _replace_placeholders(obj, **replacements):
    """Replace placeholder paths with actual file paths."""
    if isinstance(obj, dict):
        return {k: _replace_placeholders(v, **replacements) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [_replace_placeholders(item, **replacements) for item in obj]
    elif isinstance(obj, str):
        return replacements.get(obj, obj)
    else:
        return obj


@pytest.fixture()
def metric_config_factory(
    calibpipe_camera_calib_dl1_obsfile_1, calibpipe_camera_calib_dl1_obsfile_2
):
    """Create metric workflow configuration factory."""

    def _make_metric_config(uc_id, base_path, **kwargs):
        # Append metric-specific configuration paths

        if uc_id == "1.2.1":
            config = {
                "configuration": {
                    "class": "File",
                    "path": str(base_path / "camera_calibration_quality_config.yaml"),
                },
                "log-level": "INFO",
                "provenance_log_filename": "qualpipe-evaluate-metric.provenance.log",
            }
        else:
            raise ValueError(f"Unknown metric UC ID: {uc_id}")

        # Allow overriding any config values
        config.update(kwargs)
        # Replace placeholder paths with actual fixture file paths
        config = _replace_placeholders(
            config,
            DL1_MON_FILE_1=str(calibpipe_camera_calib_dl1_obsfile_1),
            DL1_MON_FILE_2=str(calibpipe_camera_calib_dl1_obsfile_2),
        )
        return config

    return _make_metric_config


@pytest.fixture()
def workflow_config_factory(
    metric_config_factory,
):
    """Create workflow configuration files using factories."""

    def _make_workflow_config(group, uc_id, tmp_path, base_path, **config_overrides):
        # Find workflow file
        path_to_workflows = Path(__file__).parent / "../workflows"
        workflow_pattern = f"uc-140-{uc_id}*.cwl"
        workflow_file_path = path_to_workflows / group.value

        try:
            workflow_file = next(workflow_file_path.glob(workflow_pattern))
        except StopIteration:
            pytest.fail(
                f"No matching workflow file found for pattern {workflow_pattern} "
                f"in {workflow_file_path}."
            )

        # Generate CWL template
        try:
            make_tpl = subprocess.run(
                ["cwltool", "--make-template", str(workflow_file)],
                check=True,
                capture_output=True,
                text=True,
            )
        except subprocess.CalledProcessError as e:
            pytest.fail(
                f"cwltool --make-template failed for {workflow_file}: {e.stderr}"
            )

        # Parse template
        template = yaml.safe_load(make_tpl.stdout) or {}

        # Create config based on workflow group using factories
        if group == WorkflowGroup.METRIC:
            config_values = metric_config_factory(uc_id, base_path, **config_overrides)
        else:
            raise ValueError(f"Unknown workflow group: {group}")

        # Merge template with fixture-based config
        populated = dict(template)
        for k, v in config_values.items():
            populated[k] = v

        # Write to temporary file
        config_path = tmp_path / f"uc-140-{uc_id}.yml"
        config_path.write_text(yaml.safe_dump(populated))

        return config_path

    return _make_workflow_config


@pytest.fixture()
def workflow_config(request, tmp_path, workflow_config_factory):
    """Generate workflow config for parameterized tests with optional kwargs."""
    group, uc_id, base_path, config_kwargs = (
        request.node.callspec.params["group"],
        request.node.callspec.params["id"],
        request.node.callspec.params["base_path"],
        request.node.callspec.params["config_kwargs"],
    )
    return workflow_config_factory(group, uc_id, tmp_path, base_path, **config_kwargs)
