from __future__ import annotations

import json
import logging
from pathlib import Path

from ...bliss_globals import current_session  # type: ignore
from ...id31.stop_scan_preset import StopIntegrateSum
from ...utils import directories
from .streamline_id31 import id31_patching
from .utils.pyfai_calib import DEFAULT_CALIB

_logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Minimal Ewoks workflow: PyFaiConfig → IntegrateAndSendMsg
# ---------------------------------------------------------------------------
_DEMO_WORKFLOW = {
    "graph": {"schema_version": "1.1", "id": "stop_scan_pyfai_demo"},
    "nodes": [
        {
            "id": "config",
            "task_type": "class",
            "task_identifier": "ewoksxrpd.tasks.pyfaiconfig.PyFaiConfig",
        },
        {
            "id": "integrate",
            "task_type": "class",
            "task_identifier": "blissoda.demo.tasks.stop_scan_xrpd_integrate.IntegrateAndSendMsg",
        },
    ],
    "links": [
        {
            "source": "config",
            "target": "integrate",
            "data_mapping": [
                {
                    "source_output": "detector_config",
                    "target_input": "detector_config",
                },
                {"source_output": "energy", "target_input": "energy"},
                {
                    "source_output": "integration_options",
                    "target_input": "integration_options",
                },
                {"source_output": "detector", "target_input": "detector"},
                {"source_output": "mask", "target_input": "mask"},
                {"source_output": "geometry", "target_input": "geometry"},
            ],
        },
    ],
}


# ---------------------------------------------------------------------------
# DemoStopIntegrateSum
# ---------------------------------------------------------------------------
class DemoStopIntegrateSum(StopIntegrateSum):
    """A demo-friendly ``StopIntegrateSum`` for the Bliss demo session.

    Calls ``id31_patching()`` before ``super().__init__()`` so that:

    * ``setup_globals.atten`` resolves to the mock ``controllers.Attenuator``
      (with ``.bits`` attribute),
    * ``from id31.attenuator import Attenuator, SiO2trans`` resolves to the
      mock implementations.

    The PyFAI config JSON and Ewoks workflow are auto-created in the
    processed directory before the parent is initialised.

    All other behaviour (workflow submission, Redis stream feedback,
    ``ScanPointIterator`` / ``_adjust_filter`` logic) is inherited unchanged.
    """

    def __init__(
        self,
        workflow_threshold: float,
        detector_name: str = "difflab6",
        detector_saturation: float = 1e6,
        frame_target_max: float | None = None,
        frame_target_min: float | None = None,
    ) -> None:
        id31_patching(energy=75.05)  # need it for proper atten tests
        pyfai_config_path = _ensure_demo_pyfai_config()
        workflow_path = _ensure_demo_workflow()

        super().__init__(
            workflow_threshold=workflow_threshold,
            workflow_path=workflow_path,
            detector_name=detector_name,
            detector_saturation=detector_saturation,
            pyfai_config_path=pyfai_config_path,
            attenuator_name="atten",
            frame_target_max=frame_target_max,
            frame_target_min=frame_target_min,
            ewoksjob_queue="celery",
        )


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _ensure_demo_pyfai_config() -> str:
    """Create a demo PyFAI config JSON for ``difflab6`` if it doesn't exist."""
    processed_dir = directories.get_processed_dir(current_session.scan_saving.filename)
    config_path = Path(processed_dir, "config", "pyfaicalib.json")
    if not config_path.is_file():
        _logger.info("Create demo PyFAI config file: %s", config_path)
        config_path.parent.mkdir(parents=True, exist_ok=True)
        config_path.write_text(json.dumps(DEFAULT_CALIB["difflab6"]))
    return str(config_path)


def _ensure_demo_workflow() -> str:
    """Write the demo workflow JSON into the processed directory."""
    processed_dir = directories.get_processed_dir(current_session.scan_saving.filename)
    workflow_path = Path(processed_dir, "workflows", "stop_scan_xrpd_id31.json")
    if not workflow_path.is_file():
        _logger.info("Create demo stop_scan_xrpd_id31 workflow: %s", workflow_path)
        workflow_path.parent.mkdir(parents=True, exist_ok=True)
        workflow_path.write_text(json.dumps(_DEMO_WORKFLOW, indent=2))
    return str(workflow_path)
