"""Tests for channel grid component."""

from pathlib import Path

import pytest

from impakt.io.mme import MMEReader
from impakt.web.components.channel_grid import (
    _build_channel_rows,
    build_selected_channels_badges,
    filter_rows,
)
from impakt.web.state import AppState

FIXTURE_DATA = Path(__file__).parent.parent / "fixtures" / "sample_mme"
MME_DATA = Path(__file__).parent.parent / "mme_data"


class TestChannelRows:
    def test_build_rows_from_synthetic(self):
        state = AppState()
        state.load_test(FIXTURE_DATA)
        rows = _build_channel_rows(state)
        assert len(rows) == 26
        # Each row should have required fields
        for r in rows:
            assert "key" in r
            assert "iso_code" in r
            assert "unit" in r
            assert "min" in r
            assert "max" in r
            assert "::" in r["key"]

    @pytest.mark.skipif(not (MME_DATA / "3239").exists(), reason="Real data not available")
    def test_build_rows_from_real_data(self):
        state = AppState()
        state.load_test(MME_DATA / "3239")
        rows = _build_channel_rows(state)
        assert len(rows) == 133

    def test_multi_test_rows_have_test_id(self):
        state = AppState()
        state.load_test(FIXTURE_DATA)
        if (MME_DATA / "VW1FGS15").exists():
            state.load_test(MME_DATA / "VW1FGS15")
            rows = _build_channel_rows(state)
            assert len(rows) == 36  # 26 + 10
            # Multi-test rows should have test_id filled
            test_ids = {r["test_id"] for r in rows}
            assert len(test_ids) == 2

    def test_rows_preserve_load_order(self):
        state = AppState()
        state.load_test(FIXTURE_DATA)
        rows = _build_channel_rows(state)
        # First channel in fixture should be first row
        # (this depends on how MMEReader yields channels — sorted by name)
        iso_codes = [r["iso_code"] for r in rows]
        assert len(iso_codes) == 26


class TestFilterRows:
    @pytest.fixture
    def rows(self):
        state = AppState()
        state.load_test(FIXTURE_DATA)
        return _build_channel_rows(state)

    def test_no_filter_returns_all(self, rows):
        result = filter_rows(rows)
        assert len(result) == len(rows)

    def test_wildcard_filter_head(self, rows):
        result = filter_rows(rows, pattern="*HEAD*")
        assert len(result) > 0
        assert all("HEAD" in r["iso_code"] for r in result)

    def test_wildcard_filter_accel(self, rows):
        result = filter_rows(rows, pattern="*AC*")
        assert len(result) > 0
        assert all("AC" in r["iso_code"] for r in result)

    def test_partial_text_auto_wrapped(self, rows):
        """Typing 'HEAD' without wildcards should auto-wrap to *HEAD*."""
        result = filter_rows(rows, pattern="HEAD")
        assert len(result) > 0
        assert all("HEAD" in r["iso_code"] for r in result)

    def test_filter_by_body_facet(self, rows):
        result = filter_rows(rows, body="Head")
        assert len(result) > 0
        assert all(r["body"] == "Head" for r in result)

    def test_filter_by_direction_facet(self, rows):
        result = filter_rows(rows, direction="X")
        assert len(result) > 0
        assert all(r["direction"] == "X" for r in result)

    def test_combined_filter(self, rows):
        result = filter_rows(rows, pattern="*AC*", direction="X")
        assert len(result) > 0
        for r in result:
            assert "AC" in r["iso_code"]
            assert r["direction"] == "X"

    def test_no_match_returns_empty(self, rows):
        result = filter_rows(rows, pattern="NONEXISTENT")
        assert len(result) == 0

    @pytest.mark.skipif(not (MME_DATA / "3239").exists(), reason="Real data not available")
    def test_wildcard_filter_real_data(self):
        state = AppState()
        state.load_test(MME_DATA / "3239")
        rows = _build_channel_rows(state)

        # Filter for head channels
        head = filter_rows(rows, pattern="*HEAD*")
        assert len(head) > 0

        # Filter for barrier load cells
        barrier = filter_rows(rows, pattern="B0FBAR*")
        assert len(barrier) > 0

        # Filter for femur
        femur = filter_rows(rows, pattern="*FEMR*")
        assert len(femur) >= 2  # Left and right


class TestSelectedBadges:
    def test_empty_selection(self):
        state = AppState()
        badges = build_selected_channels_badges([], state)
        assert len(badges) == 1  # "No channels selected"

    def test_with_selection(self):
        state = AppState()
        state.load_test(FIXTURE_DATA)
        keys = ["IMPAKT_SYNTH_001::11HEAD0000ACXA", "IMPAKT_SYNTH_001::11HEAD0000ACYA"]
        badges = build_selected_channels_badges(keys, state)
        assert len(badges) == 2
