###############################################################################
# (c) Copyright 2026 CERN for the benefit of the LHCb Collaboration           #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
#                                                                             #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization  #
# or submit itself to any jurisdiction.                                       #
###############################################################################
"""Load CWL test fixture data from tests/fixtures/ directory.

Fixtures are organized by production name, with a manifest.yaml
that ties jobs to DST files and LFNs. Each job has a query_result.json
containing the captured output of LbAPCommon's query_dirac().

Usage:
    from fixture_loader import get_fixture, discover_fixtures

    # Load a specific fixture set
    fs = get_fixture("executabletests")
    result = fs.get_query_result("2016_MagDown_PromptMC_D02KK")

    # Auto-discover all fixtures
    all_fixtures = discover_fixtures()
"""

from __future__ import annotations

import json
from pathlib import Path

import yaml

FIXTURES_DIR = Path(__file__).parent / "fixtures"
TEST_DST_DIR = Path(__file__).parent / "test-input-dst"


class FixtureSet:
    """Loaded fixture data for one production."""

    def __init__(self, production_name: str):
        self._production_name = production_name
        self._fixture_dir = FIXTURES_DIR / production_name

        manifest_path = self._fixture_dir / "manifest.yaml"
        with open(manifest_path) as f:
            self._manifest = yaml.safe_load(f)

        self._query_results: dict[str, dict] = {}

    @property
    def production_name(self) -> str:
        return self._production_name

    @property
    def ap_repo(self) -> str:
        return self._manifest.get("ap_repo", "data-pkg-repo")

    @property
    def job_names(self) -> list[str]:
        return list(self._manifest["jobs"].keys())

    def _resolve_job(self, job_name: str) -> str:
        """Resolve same_as references to the actual job name."""
        config = self._manifest["jobs"][job_name]
        if "same_as" in config:
            return config["same_as"]
        return job_name

    def get_job_config(self, job_name: str) -> dict:
        """Get manifest config for a job, resolving same_as references."""
        actual = self._resolve_job(job_name)
        return self._manifest["jobs"][actual]

    def get_query_result(self, job_name: str) -> dict:
        """Load the query_result.json for a job."""
        actual = self._resolve_job(job_name)
        if actual not in self._query_results:
            result_path = self._fixture_dir / actual / "query_result.json"
            with open(result_path) as f:
                self._query_results[actual] = json.load(f)
        return self._query_results[actual]

    def get_dst_path(self, job_name: str) -> Path:
        """Get absolute path to the local DST file for a job."""
        config = self.get_job_config(job_name)
        return TEST_DST_DIR / config["dst_file"]

    def get_lfn(self, job_name: str) -> str:
        """Get the LFN that maps to the local DST for a job."""
        config = self.get_job_config(job_name)
        return config["lfn"]


def get_fixture(production_name: str) -> FixtureSet:
    """Get a specific fixture set by production name."""
    return FixtureSet(production_name)


def discover_fixtures() -> dict[str, FixtureSet]:
    """Discover all available fixture sets by scanning tests/fixtures/."""
    fixtures = {}
    if FIXTURES_DIR.exists():
        for manifest_path in sorted(FIXTURES_DIR.glob("*/manifest.yaml")):
            production_name = manifest_path.parent.name
            fixtures[production_name] = FixtureSet(production_name)
    return fixtures
