"""MRI sequence identification helpers."""

from typing import List

import pydicom

from dicom_mcp.constants import SequenceType
from dicom_mcp.helpers.tags import _safe_get_tag


def _identify_sequence_type(ds: pydicom.Dataset) -> SequenceType:
    """Identify the MRI sequence type from DICOM metadata.

    Uses a two-tier approach:
      1. Series description keyword matching (fast, covers named protocols)
      2. DICOM acquisition tag inspection (structural fallback)

    IMPORTANT: Keyword matching order matters. More specific terms (e.g., 't1_mapping',
    'molli') must be checked before generic terms (e.g., 't1') to avoid false positives.
    """
    series_desc = _safe_get_tag(ds, (0x0008, 0x103E), "").lower()

    # --- Tier 1: keyword matches on series description ---
    # NOTE: Order is intentional - specific patterns checked before generic ones

    # Dixon variants (check before MOST/IDEAL since some descriptions contain both)
    if any(kw in series_desc for kw in ["dixon", "ideal", "flex"]):
        return SequenceType.DIXON

    # T1 mapping protocols (MOLLI, NOLLI, ShMOLLI, SASHA, etc.)
    # Must check before generic 't1' to avoid misclassification
    if any(kw in series_desc for kw in ["molli", "nolli", "shmolli", "sasha"]):
        return SequenceType.T1_MAPPING

    # Multi-echo GRE (MOST protocol for T2*/PDFF)
    if "most" in series_desc or "multi" in series_desc and "echo" in series_desc:
        return SequenceType.MULTI_ECHO_GRE

    # Localizer / survey / scout
    if any(kw in series_desc for kw in ["localizer", "survey", "scout"]):
        return SequenceType.LOCALIZER

    # Standard named sequences (specific before generic)
    if "flair" in series_desc:
        return SequenceType.FLAIR
    if "dwi" in series_desc or "diffusion" in series_desc:
        return SequenceType.DWI
    # Check 't2' before 't1' since 't2' is more specific
    if "t2" in series_desc:
        return SequenceType.T2
    if "t1" in series_desc:
        return SequenceType.T1

    # --- Tier 2: inspect DICOM acquisition tags ---

    image_type = _safe_get_tag(ds, (0x0008, 0x0008), "").lower()
    if "dixon" in image_type or "ideal" in image_type:
        return SequenceType.DIXON

    scanning_seq = _safe_get_tag(ds, (0x0018, 0x0020), "")
    seq_variant = _safe_get_tag(ds, (0x0018, 0x0021), "")

    has_ir = "IR" in scanning_seq
    has_se = "SE" in scanning_seq
    has_gr = "GR" in scanning_seq
    has_mp = "MP" in seq_variant  # Magnetization Prepared

    # GR + IR (+ MP) = gradient echo inversion recovery (MOLLI-like T1 mapping)
    if has_gr and has_ir and has_mp:
        return SequenceType.T1_MAPPING

    # SE + IR = spin echo inversion recovery
    if has_se and has_ir:
        return SequenceType.SPIN_ECHO_IR

    # Multi-echo detection via NumberOfEchoes tag
    num_echoes = _safe_get_tag(ds, (0x0018, 0x0086), "")
    try:
        if int(num_echoes) > 1 and has_gr:
            return SequenceType.MULTI_ECHO_GRE
    except (ValueError, TypeError):
        pass

    return SequenceType.UNKNOWN


def _is_dixon_sequence(ds: pydicom.Dataset) -> bool:
    """Check if a DICOM file is from a Dixon sequence."""
    return _identify_sequence_type(ds) == SequenceType.DIXON


def _get_dixon_image_types(ds: pydicom.Dataset) -> List[str]:
    """Extract Dixon image types (water, fat, in-phase, out-phase) from metadata."""
    image_types = []

    image_type_tag = ds.get((0x0008, 0x0008))
    if image_type_tag:
        image_type_str = str(image_type_tag.value).lower()
        if "water" in image_type_str or "w" in image_type_str.split("\\"):
            image_types.append("water")
        if "fat" in image_type_str or "f" in image_type_str.split("\\"):
            image_types.append("fat")
        if "in" in image_type_str or "ip" in image_type_str:
            image_types.append("in-phase")
        if "out" in image_type_str or "op" in image_type_str:
            image_types.append("out-phase")

    series_desc = _safe_get_tag(ds, (0x0008, 0x103E), "").lower()
    if "water" in series_desc and "water" not in image_types:
        image_types.append("water")
    if "fat" in series_desc and "fat" not in image_types:
        image_types.append("fat")

    return image_types if image_types else ["unknown"]
