############################################################################
# Copyright (c) 2025-2026 University of Helsinki
# All Rights Reserved
# See file LICENSE for details.
############################################################################

"""
Unit tests for barcode detector classes.

Each detector has:
- test_init: Basic initialization
- test_no_match_random_sequence: Random sequence with no expected match
- test_real_sequence: Placeholder for real data (TODO: add real sequences)
"""

import pytest
from src.barcode_calling.callers import (
    # Stereo-seq
    StereoBarcodeDetector,
    StereoSplittingBarcodeDetector,
    SharedMemoryStereoBarcodeDetector,
    SharedMemoryStereoSplittingBarcodeDetector,
    # 10x Genomics
    TenXBarcodeDetector,
    VisiumHDBarcodeDetector,
    # Curio
    CurioBarcodeDetector,
    CurioIlluminaDetector,
)
from src.barcode_calling.callers.base import (
    SplittingBarcodeDetectionResult,
    TSOBarcodeDetectionResult,
    TenXBarcodeDetectionResult,
    LinkerBarcodeDetectionResult,
)


# =============================================================================
# Dummy data for testing
# =============================================================================

# Random sequence with no expected barcode match (just random nucleotides)
RANDOM_SEQUENCE = (
    "GCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTA"
    "ATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCG"
    "CGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGAT"
)

# Dummy barcodes for initializing indexers
DUMMY_BARCODES_16 = [
    "ACTGACTGACTGACTG",
    "TGCATGCATGCATGCA",
    "GGGGGGGGGGGGGGGG",
]

DUMMY_BARCODES_25 = [
    "ACTGACTGACTGACTGACTGACTGA",
    "TGCATGCATGCATGCATGCATGCAT",
    "GGGGGGGGGGGGGGGGGGGGGGGGG",
]

DUMMY_BARCODES_14 = [
    "ACTGACTGACTGAC",
    "TGCATGCATGCATG",
    "GGGGGGGGGGGGGG",
]

DUMMY_BARCODES_8 = [
    "ACTGACTG",
    "TGCATGCA",
    "GGGGGGGG",
]

DUMMY_BARCODES_6 = [
    "ACTGAC",
    "TGCATG",
    "GGGGGG",
]

DUMMY_BARCODES_15 = [
    "ACTGACTGACTGACT",
    "TGCATGCATGCATGC",
    "GGGGGGGGGGGGGGG",
]


# =============================================================================
# Stereo-seq Detector Tests
# =============================================================================

class TestStereoBarcodeDetector:
    """Test Stereo-seq barcode detector."""

    def test_init(self):
        """Test basic initialization."""
        detector = StereoBarcodeDetector(DUMMY_BARCODES_25)
        assert detector.barcode_indexer is not None
        assert detector.min_score == 22

    def test_init_empty_barcodes(self):
        """Test initialization with empty barcode list."""
        detector = StereoBarcodeDetector([])
        assert detector.barcode_indexer is None

    def test_no_match_random_sequence(self):
        """Test that random sequence returns no valid barcode."""
        detector = StereoBarcodeDetector(DUMMY_BARCODES_25)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert isinstance(result, (LinkerBarcodeDetectionResult, TSOBarcodeDetectionResult))
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert not result.is_valid()

    @pytest.mark.parametrize("read_sequence, true_barcode, true_umi",
                             [("CTTCCGATCTATGGCGACCTCAGGAAGGAGGGATCCATAACCGGCCCCATTGTCTTCCTAAGACATTTATCCGATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTC"
                               "AAAACTAGCTTTTGTGCTGGGTAATTTTATTTTTTTAAGAAATGGGGGAAAGCTAAAAAGAGAGCGTCAGGGTC",
                               "GAAGGAGGGATCCATAACGGCCCCA", "ATTTATCCGA"),
                              ("TTCCGATCTATGGCGACCTTATCAGTCCCCACTTTCACTCTCACCCCATTTTGTCTTCCTAAGACCTAGTGTAGCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "CACATATAAATATGACTTTATTAACCAGTCTGTGTTTGATTTAGCACTCTAGTGGCTATCAGTGATTTTCTTTTA",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("TTCCGATCTATGGCGACCTTATCAGAGTTGGCGCCCAAATGGTCAGAGGGTTGTCTTCCTAAGACACGCAATCACTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "GCAGACATCAGTAGTTTATTGTTTTAGTCCAAACACATTCAAAATGGAAACTCAAAAGAATACTTTCTACCTGAA",
                               "AGTTGGCGCCCAAATGGTCAGAGGG", "ACGCAATCAC"),
                              ("ATCTTTCTGATATCACTGTCTACCCATTATTAAAAGAAAATCACTGATAGCCACTAGAGTGCTAAATCAAACACAGACTGGTTAATAAAGTCATATTTATATGTG"
                               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTACACTAGGTCTTAGGAAGACAAAATGGGGTGAGAGTGAAAGTGGGGACTGATAAGGTCGCCATAGATCGGAAG",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("TTCCGATCTATGGCGACCTTATCAGTCCCCACTTTCACTCTCACCCCATTTTGTCTTCCTAAGACCTAGTGTAGCTTT",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("TTCCGATCTATGGCGACCTTATCAGAGTTGGCGCCCAAATGGTCAGAGGGTTGTCTTCCTAAGACACGCAATCACTT",
                               "AGTTGGCGCCCAAATGGTCAGAGGG", "ACGCAATCAC"),
                              ("AGCTACACTAGGTCTTAGGAAGACAAAATGGGGTGAGAGTGAAAGTGGGGACTGATAAGGTCGCCATAGATCGGAAG",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ])
    def test_real_sequence(self, read_sequence, true_barcode, true_umi):
        # Test with real sequence data.

        barcodes = ["GAAGGAGGGATCCATAACGGCCCCA",
                    "TCCCCACTTTCACTCTCACCCCATT",
                    "AGTTGGCGCCCAAATGGTCAGAGGG",
                    "CATCAAAGGTTCACCGAATCTCCAC",
                    "GTCGCCTTCAACGTATACTGATATA",
                    "ACCAATTAGCAGCCATGGGAACTCC"]
        detector = StereoBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, (LinkerBarcodeDetectionResult, TSOBarcodeDetectionResult))
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert result.is_valid()
        assert result.barcode == true_barcode
        assert result.UMI == true_umi


class TestStereoSplittingBarcodeDetector:
    """Test Stereo-seq splitting barcode detector."""

    def test_init(self):
        """Test basic initialization."""
        detector = StereoSplittingBarcodeDetector(DUMMY_BARCODES_25)
        assert detector.barcode_indexer is not None

    def test_init_empty_barcodes(self):
        """Test initialization with empty barcode list."""
        detector = StereoSplittingBarcodeDetector([])
        assert detector.barcode_indexer is None

    def test_no_match_random_sequence(self):
        """Test that random sequence returns empty splitting result."""
        detector = StereoSplittingBarcodeDetector(DUMMY_BARCODES_25)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert result.read_id == "test_read"
        # Should return empty or no valid patterns
        assert result.empty() or not any(p.is_valid() for p in result.detected_patterns)

    @pytest.mark.parametrize("read_sequence, true_barcodes, true_umis",
                             [("CTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTGGGACTAACCCTTCTGTGTCCATGCAGAAGAAGCTAGGTCTATGTGAAGGAACTTTAATATAGAAAAAATTAATGGGGAATGGTACACTATTATCCTGGCTTCTGACAAAAGGGAAAAGATAGAAGAACATGGCAGCATGATACTTTTTGGGAGCACATTCATGTCTTGGAGAATTCCTTAGGTTTTAAACTCCATACTGTTATAGATTAAGAGTGCTCCAAAGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAGCTGATGTTGCTTTATGACCTAGAACCGGATTTGAGGTCAGACATCAAGGAAGAATTTGCAAAACTATTTGAGGAGCATGGAATCGTTAGAGAAAATAGCATTGACCTATCTAATGCCAATCACTGTCTCCAGGCCCTAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCAGTGGCCGGTCTTAGGAAGACAATTTTCGCTTTCTGAGGAATGTGCCCCTGATAAGGTCGCCATAGATCGGAAGCTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTGGGACTAATCACTAGTCTGTGTCACATGCAGAAGAAGAGCTAGCTAGTGAAGGAACTCTTAACCAGCGAAAATTAACCGGGAATACTCTGTGGATCCTGGCTTCTGACAAAAGAGAAAAGATAGAAGAACATGGCAGCATGAGACTTAGTTTGTGGAGCACATTCATGTCTTGGAGAATTCCTTAGGTTTTAAACTCCATACTGTTATAGATTAAGAGTGCTGCAAAGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAGCTGATGTTGCTTTATGACCTAGAACCGGATTTGAGGTCAGACATCAAGGAAGAATTTGCAAAACTATTTGAGGAGCATGGAATCGTTAGAGAAAATAGCATTGACCTAATTCTAATGCCAATCACTGTCTCCAGGCCAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCGCGAAGGTGTCTTAGGAAGACAAGTCCACCGACAAACGTTTAGGGGAGCTGATAAGGTCGCCATAGATCGGAAGCTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTGGGACTAACACTAGTCTGTGTCCATGCAGAAGAAGCTAGGTCTATGTAAGGAACTTTAATATAGAAAAAATTAATGGGGAATGGTACACTATTATCCTGGCTTCTGACAAAAGAGAAAAGATAGAAGAACATGGCAGCATGAGACTTTTTGTGGAGCACATTCATGTCTTGGAGAATTCCTTAGGTTTTAAACTCCATACTGTTATAGATTAAGAGTGCTCCAAAGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAACCGATGTTGCTTTATGACCTAGGAACCGCGTTTGAGGTCCAGACATACCAATTGCAAAACTAATTTGAGGAGCAAATCGTTAGAGAAAATAGATTGACCTATCTAATGCCAATCACTGTCTCCAGGCCCTAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATGGGGCGGAGGTCTTAGGAAGAAACTTGCTATCCTAAGTTCTTGCTGATAAGGTCGCCATAGATCGGAAGCTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTTGGAATAACCCTAGTCTGTGTCCATGCAGAAGAAGCTAGGTCTATGTGAAGGAACTTTAATATAGAAAAAATTAATGGGGAATGGTACACTATTATCCTGGCTTCTGAAAAAGAGAAAAGATAGAAGAACATGGCAGCATGAGACTCTTTGTGGAGCACATTCATGTCTTGGAGAATTCCTTAGGATTTAAACTCCTTACTGTTATAGATGAAAGGTGCCAATGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAGCTGATGTTGCTTTATGACCTAGAACCGGATTTGAGGTCAGACATCAAGGAAGAATTTGCAAAACTATTTGAGGAGCATGGAATCGTTAAGAGAAAATAGCATTGACCTATCTAATGCCAATCACTGTCTCCAGGCCCTAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAACATAATCGGGTTCAGTCTTAGGAAGACAACTCGACGAGTAACTAATGGCTGCCTGATAAGGTCGCCATAGATCGGAA",
                               ("GGCAGGCCATTAGTTACTCGTCGAG", "CTCCCCTAATCGTTTGTCGGTGGAC", "GGGCACATTCCTCAGAAAGCGAAAA"),
                               ("TGAACCCGATTATG", "ACCTTCGCGC", "CGGCCACTGC")),
                              ("TTCCGATCTATGGCGACCTTATCAGTATGTACGAATTTAACCGTACCCTCTTGTCTTCCTAAGACCTTGCCGTCGTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTAGCATTGTGCACATTGGTTTATTTAGCACTTCTAACCACGCCGCAAAGAAAGCACTAAACAACTTTGCAAACCTCATTCGGTTCAGATGGGGCAAATGGGGGCCCCTGGCAGCAGGAGCCCAGAGACAGAGCCTGGGTTTGGATCATGGGACCAGTTAGGTTCTTGGGAAGGGGTACTGTGAAGCTGGGCTTTGAGGGATGTGTAGGAGTTTATTAGAGTATTATTTACTCATTTGTTGCCGCAGATTAAAGAGTAGAGCCAGCCCTATAACCTCCCCATTCAGTGATGTTTGTGCACCCAGACCGGGAACGCCTTGTCCACACTTAATCCGCCTAGTTTATCGCCATATTATGACCTTCAGGGCCTTTTGTCGCTCCTCTTCCAAGCAGAGAACACCTGAAGGCTACCGCCTGGGATCTGAGAGTGCTGTGTGGAAGTGGCTGAGAGCCAGGCGGCGCGCTCCACCCTCAGGCAGTGATCTAGTTTCTCTCGCATCGATCTGGCCGGCCTTGCCCCTCCTCCGCACCCTGCCCCGCCCAGCACTCTTCTCTTTGTTTCCCGGCAGTACTGTCCTGGAAAGGGCGGGGGACAGAGGCAGGGTGATGATGACAACCCCTTCCCTCACAGAAGGAATCCTTGGGGTCTGAATCGGTGACTCCGACGTCTTTTTACCTGGTGGCTGTTGGCAGGCCTGAGAGTTCTGACCCTCGGGTTCCAATATGAACCCAAAGAACCGGGATGTCCTTTGCTTACAGCCTAGGAAACAGGCCAGGAGCCAGCAGAAGCGACCCATGGTCTCCTTTAGACTTCTCCAGACGCAGCGCCACCCGCGGTGTCCTGGGCACTTGCTTCACTTCCAGGCCTCAGTTCCCTTTAAGCCTTGGCCTTGCTCCAGGGTTCAGTTTTCCCACTAACCAGTAAAGAAGGTTCAGTTGGAGGGGGTACCCTCTGAGTCTGAGGTTCTCTTGTCCTGGACCCCAGCCTGTGCACTGGCCCAGGCCCTATTTGGACCCTATTTAGAAGTAAAGTTGGGCAGGATATGACTGAACGTGTCAAGGACCCGGATAGTCTCATCCTGCCTCTACCACCCAGACCTCAAGTTCCCTTTTGTGCCTTATCCTTACCCTAGCCCTCGGTTTCCTCACTGAGCAAACCCGGTGGAACAGTGGCTTAAGGGATACTTAGGGGCCGGAGGATAGCTCTACAAAGCCAGGCCTCAGTTTATCAACTTAGAAGTAAAGAAGGGCAGGATGTTGCTGGAACAGTGGTGAAGGGTGGCCTCGGGGTTAGGGGATCACTCCCTGCACCTGCGACTTCAGGCCTTAGTTTCTCTATTTAGAAGAAACACGAGAAGGGAGGATAGGATGCTGCTGGAGTGAAGGCAGAGACTTGGAAGTTGAAGAATGGCGCCCCGCCCCGTGTATGCGACCCCTGTCCTCAGTTTCCCCATCGGTCTGAGCCTGACTGGACATTCCCTCGGGGAGCCCCGGCAGGCATCGCTAGGTCGGAGGCGGCGCTGCCAGAACAGGGTCGGGGTCCCAGGAGTGTAGCCCCCCGCGGCTACGCGCTGCGCGGAGCGGTGACATCACTCGGCGGGGAGGAGCGCACGGCTGTGGACCAGGCTCGCGCCGGGGCTCCTCGGGCCGCCCGCTCCAGTACGGGTCAGCAGCTGCTGACGTACTGAGAGGCGGGCGGCCGCCGAGGAGCCCCGGCTGAGCCTGGTCCAGAGCCGTGCGCTCCTCCCCGCCGAGTGATGTCACCGCTCCGCGCAGCGCGCAGCCGCGGGGGGCTACACTCCTGGGACCCCGACCCTGTTCTGGCAGCGCCGCCTCCGACCTAGCGCAGCCTGCCGGGGCTCCCCGAGGGAATGTCCAGTCAGGCTCAGACCGATGGGGAAACTAGAGGACAGGGGTCGCATACACGGGGCGGGGCGCCATTCTTCAACTTCCAAGTCTCTGCCTTCACTCCAGCAGCATCCTATCCTCCCTTCTTTTCTTCTAAATAGAGAAACTAAGGCCTGAAGTCGCAGGTGCAGGGAGTGATCCCCTAACCCCGAGGCCACCCTTCACCACTGTTCCAGCAACATCCTGCCCTTCTTTACTTCTAAGTTGAGAAACTGAGGCCTGGCTTTGTAGAGCTATCCTCCGGCCCCTAAGTATCCCTTAAGCACCTTCTCCACCGGCTTCGCTCCCAGTGAGGAAACCGAGGGCTAGGGTAAGGATAAGGCACAAAAGGGAACTTGAGGTCTGGGTGGTAGAGGCAGGATGAGACTATCCGGGTCCTTGACACGTTCAGTCATATCCTGCCCAACTTACTTCTCAATATGGTTAGGGCCTGGGCCAGAGTGCACAGGCTGGGGTCCAGGACAAGAGAACCTCAGACTCAGAGGGTACCCCCTCCAACTGAACCTTCTTTACTGGTTAGTGGGAAAACTGAACCCTGGAGCAAGGCCAAGGCTTAAAGGGAAACTGAGGCCTGGAAGTGAAGCAAGTGCCCAGGACACCGCGGGTGGCGCTGCGTCTGGAGAAGTCTAAAGGTGACCATGGGTCGCTTCTGCTGGCTCCTGGCCTGTTTCCTAGGCTGTAAGCAAAGGACATCCATCGGTTCTTTGGGATATTGGAACCCGGGTCACTCTCAGGCCTGACATGAGCGCTGCAGGCCATGAGAGCCTCGGAGACACCGATTCAGACCCCAAGGGGATTCCTTCTGTGAGGGAAGGGGTTGTCATCATCACCCTGCCTCTGTCCCCCGCCCTTTCCAGGACAGTACTGCCGGGAAACAAAGAGAAGAGTGCTGGGCGGGGCAGGGTGCGGAGGAGGGGGAAGACCACCCAGATCGATGCGAGAGAAACTACATCCGACTGCCTCGGGAGGGAGCGGAGGCGCGCGCGCCTGGCACTCAGCCACTTCCACACAGGCACTCTCAGGAGCCCAGCCAGGTCGCCTTTGGTGTTGTCGGCTGGAAGAGGAGCGCCACTGGGCTGAAGTCTGAAAAATGGCTGTAGAATCTAGCTGATTAAGTGTGGATCAAAGGCTTCCGGTTTCTGGGTCCGCACAAACATTACTGAAATGGGGAGGTTATAGGGCTGGCTCTACTCTTTAATCTGGCGGCAACAATGACGTAAATAATACTCTAATAAACTCCTACACATCCCTCAAAGCCCAGCTTCACAGTACCCCTTCCCAAGAACCTAACTGGTCCCATGATCCAAACCCAGGCTCTGTCTCTGGTCTCCTGCTGCAGGGGCCCCCATTTGCCCCATGTGAGGCCGAATGAGGTTTGCAAAGTTGTTTAGTGCTTTCTATGCTGGCGGGTTACAAGTGCTAAACAAAATGTAAACAATGTAAAAAAAGTAAAAAAAAAAAAAAAAAAAAAAAAACGGGCTTTCAGTCATAGGAAGACAAGTGCGCATGCCACGGAGGATCATGTCTGATAAGGTCGCCATAGATCGGAAG",
                               ("TATGTACGAATTTAACCGTACCCTC", "ACATGATCCTCCGTGGCATGCGCAC"),
                               ("CTTGCCGTCG", "TGAAAGCCCG")),
                              ])
    def test_real_sequence(self, read_sequence, true_barcodes, true_umis):
        # Test with real sequence data.

        barcodes = ["GAAGGAGGGATCCATAACGGCCCCA",
                    "TCCCCACTTTCACTCTCACCCCATT",
                    "AGTTGGCGCCCAAATGGTCAGAGGG",
                    "CATCAAAGGTTCACCGAATCTCCAC",
                    "GTCGCCTTCAACGTATACTGATATA",
                    "ACCAATTAGCAGCCATGGGAACTCC",
                    "ACATGATCCTCCGTGGCATGCGCAC",
                    "TATGTACGAATTTAACCGTACCCTC",
                    "GGGCACATTCCTCAGAAAGCGAAAA",
                    "GGCAGGCCATTAGTTACTCGTCGAG",
                    "CTCCCCTAATCGTTTGTCGGTGGAC"]
        detector = StereoSplittingBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, SplittingBarcodeDetectionResult)
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert len(result.detected_patterns) == len(true_barcodes)
        for i, r in enumerate(result.detected_patterns):
            assert r.is_valid()
            assert r.barcode == true_barcodes[i]
            assert r.UMI == true_umis[i]


class TestSharedMemStereoBarcodeDetector:
    """Test Stereo-seq barcode detector."""

    def test_init(self):
        """Test basic initialization."""
        detector = SharedMemoryStereoBarcodeDetector(DUMMY_BARCODES_25)
        assert detector.barcode_indexer is not None
        assert detector.min_score == 22

    def test_no_match_random_sequence(self):
        """Test that random sequence returns no valid barcode."""
        detector = SharedMemoryStereoBarcodeDetector(DUMMY_BARCODES_25)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert isinstance(result, (LinkerBarcodeDetectionResult, TSOBarcodeDetectionResult))
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert not result.is_valid()

    @pytest.mark.parametrize("read_sequence, true_barcode, true_umi",
                             [("CTTCCGATCTATGGCGACCTCAGGAAGGAGGGATCCATAACCGGCCCCATTGTCTTCCTAAGACATTTATCCGATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "CAAAACTAGCTTTTGTGCTGGGTAATTTTATTTTTTTAAGAAATGGGGGAAAGCTAAAAAGAGAGCGTCAGGGTC",
                               "GAAGGAGGGATCCATAACGGCCCCA", "ATTTATCCGA"),
                              ("TTCCGATCTATGGCGACCTTATCAGTCCCCACTTTCACTCTCACCCCATTTTGTCTTCCTAAGACCTAGTGTAGCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "CACATATAAATATGACTTTATTAACCAGTCTGTGTTTGATTTAGCACTCTAGTGGCTATCAGTGATTTTCTTTTA",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("TTCCGATCTATGGCGACCTTATCAGAGTTGGCGCCCAAATGGTCAGAGGGTTGTCTTCCTAAGACACGCAATCACTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "GCAGACATCAGTAGTTTATTGTTTTAGTCCAAACACATTCAAAATGGAAACTCAAAAGAATACTTTCTACCTGAA",
                               "AGTTGGCGCCCAAATGGTCAGAGGG", "ACGCAATCAC"),
                              ("ATCTTTCTGATATCACTGTCTACCCATTATTAAAAGAAAATCACTGATAGCCACTAGAGTGCTAAATCAAACACAGACTGGTTAATAAAGTCATATTTATATGTG"
                               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTACACTAGGTCTTAGGAAGACAAAATGGGGTGAGAGTGAAAGTGGGGACTGATAAGGTCGCCATAGATCGGAAG",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("CTTCCGATCTATGGCGACCTCAGGAAGGAGGGATCCATAACCGGCCCCATTGTCTTCCTAAGACATTTATCCGATT",
                               "GAAGGAGGGATCCATAACGGCCCCA", "ATTTATCCGA"),
                              ("AAGCTACACTAGGTCTTAGGAAGACAAAATGGGGTGAGAGTGAAAGTGGGGACTGATAAGGTCGCCATAGATCGGAAG",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("GTCCCCACTTTCACTCTCACCCCATTTTGTCTTCCTAAGACCTAGTGTAGCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "CACATATAAATATGACTTTATTAACCAGTCTGTGTTTGATTTAGCACTCTAGTGGCTATCAGTGATTTTCTTTTA",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("GAGTTGGCGCCCAAATGGTCAGAGGGTTGTCTTCCTAAGACACGCAATCACTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
                               "GCAGACATCAGTAGTTTATTGTTTTAGTCCAAACACATTCAAAATGGAAACTCAAAAGAATACTTTCTACCTGAA",
                               "AGTTGGCGCCCAAATGGTCAGAGGG", "ACGCAATCAC"),
                              ("ATCTTTCTGATATCACTGTCTACCCATTATTAAAAGAAAATCACTGATAGCCACTAGAGTGCTAAATCAAACACAGACTGGTTAATAAAGTCATATTTATATGTG"
                               "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTACACTAGGTCTTAGGAAGACAAAATGGGGTGAGAGTGAAAGTGGGGACTGATAAGG",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAGC"),
                              ("CTACACTAGGTCTTAGGAAGACAAAATGGGGTGAGAGTGAAAGTGGGGACTGATAAGG",
                               "TCCCCACTTTCACTCTCACCCCATT", "CTAGTGTAG")
                              ])
    def test_real_sequence(self, read_sequence, true_barcode, true_umi):
        # Test with real sequence data.

        barcodes = ["GAAGGAGGGATCCATAACGGCCCCA",
                    "TCCCCACTTTCACTCTCACCCCATT",
                    "AGTTGGCGCCCAAATGGTCAGAGGG",
                    "CATCAAAGGTTCACCGAATCTCCAC",
                    "GTCGCCTTCAACGTATACTGATATA",
                    "ACCAATTAGCAGCCATGGGAACTCC"]
        detector = SharedMemoryStereoBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, (LinkerBarcodeDetectionResult, TSOBarcodeDetectionResult))
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert result.is_valid()
        assert result.barcode == true_barcode
        assert result.UMI == true_umi


    @pytest.mark.parametrize("read_sequence",
                             [("GCAGACATCAGTAGTTTATTGTTTTAGTCCAAACACATTCAAAATGGAAACTCAAAAGAATACTTTCTACCTGAA"),
                              ])
    def test_real_sequence_no_bc(self, read_sequence):
        # Test with real sequence data.

        barcodes = ["GAAGGAGGGATCCATAACGGCCCCA",
                    "TCCCCACTTTCACTCTCACCCCATT",
                    "AGTTGGCGCCCAAATGGTCAGAGGG",
                    "CATCAAAGGTTCACCGAATCTCCAC",
                    "GTCGCCTTCAACGTATACTGATATA",
                    "ACCAATTAGCAGCCATGGGAACTCC"]
        detector = SharedMemoryStereoBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, (LinkerBarcodeDetectionResult, TSOBarcodeDetectionResult))
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert not result.is_valid()
        assert result.barcode == '*'
        assert result.UMI == '*'

class TestSharedMemStereoSplittingBarcodeDetector:
    """Test Stereo-seq splitting barcode detector."""

    def test_init(self):
        """Test basic initialization."""
        detector = SharedMemoryStereoSplittingBarcodeDetector(DUMMY_BARCODES_25)
        assert detector.barcode_indexer is not None

    def test_no_match_random_sequence(self):
        """Test that random sequence returns empty splitting result."""
        detector = SharedMemoryStereoSplittingBarcodeDetector(DUMMY_BARCODES_25)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert result.read_id == "test_read"
        # Should return empty or no valid patterns
        assert result.empty() or not any(p.is_valid() for p in result.detected_patterns)

    @pytest.mark.parametrize("read_sequence, true_barcodes, true_umis",
                             [("CTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTGGGACTAACCCTTCTGTGTCCATGCAGAAGAAGCTAGGTCTATGTGAAGGAACTTTAATATAGAAAAAATTAATGGGGAATGGTACACTATTATCCTGGCTTCTGACAAAAGGGAAAAGATAGAAGAACATGGCAGCATGATACTTTTTGGGAGCACATTCATGTCTTGGAGAATTCCTTAGGTTTTAAACTCCATACTGTTATAGATTAAGAGTGCTCCAAAGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAGCTGATGTTGCTTTATGACCTAGAACCGGATTTGAGGTCAGACATCAAGGAAGAATTTGCAAAACTATTTGAGGAGCATGGAATCGTTAGAGAAAATAGCATTGACCTATCTAATGCCAATCACTGTCTCCAGGCCCTAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCAGTGGCCGGTCTTAGGAAGACAATTTTCGCTTTCTGAGGAATGTGCCCCTGATAAGGTCGCCATAGATCGGAAGCTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTGGGACTAATCACTAGTCTGTGTCACATGCAGAAGAAGAGCTAGCTAGTGAAGGAACTCTTAACCAGCGAAAATTAACCGGGAATACTCTGTGGATCCTGGCTTCTGACAAAAGAGAAAAGATAGAAGAACATGGCAGCATGAGACTTAGTTTGTGGAGCACATTCATGTCTTGGAGAATTCCTTAGGTTTTAAACTCCATACTGTTATAGATTAAGAGTGCTGCAAAGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAGCTGATGTTGCTTTATGACCTAGAACCGGATTTGAGGTCAGACATCAAGGAAGAATTTGCAAAACTATTTGAGGAGCATGGAATCGTTAGAGAAAATAGCATTGACCTAATTCTAATGCCAATCACTGTCTCCAGGCCAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCGCGAAGGTGTCTTAGGAAGACAAGTCCACCGACAAACGTTTAGGGGAGCTGATAAGGTCGCCATAGATCGGAAGCTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTGGGACTAACACTAGTCTGTGTCCATGCAGAAGAAGCTAGGTCTATGTAAGGAACTTTAATATAGAAAAAATTAATGGGGAATGGTACACTATTATCCTGGCTTCTGACAAAAGAGAAAAGATAGAAGAACATGGCAGCATGAGACTTTTTGTGGAGCACATTCATGTCTTGGAGAATTCCTTAGGTTTTAAACTCCATACTGTTATAGATTAAGAGTGCTCCAAAGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAACCGATGTTGCTTTATGACCTAGGAACCGCGTTTGAGGTCCAGACATACCAATTGCAAAACTAATTTGAGGAGCAAATCGTTAGAGAAAATAGATTGACCTATCTAATGCCAATCACTGTCTCCAGGCCCTAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATGGGGCGGAGGTCTTAGGAAGAAACTTGCTATCCTAAGTTCTTGCTGATAAGGTCGCCATAGATCGGAAGCTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGTGTTTTGGAATAACCCTAGTCTGTGTCCATGCAGAAGAAGCTAGGTCTATGTGAAGGAACTTTAATATAGAAAAAATTAATGGGGAATGGTACACTATTATCCTGGCTTCTGAAAAAGAGAAAAGATAGAAGAACATGGCAGCATGAGACTCTTTGTGGAGCACATTCATGTCTTGGAGAATTCCTTAGGATTTAAACTCCTTACTGTTATAGATGAAAGGTGCCAATGTATTTTTAGTTGGTGACAATACAGAAAAGGCTGGTAATATTCTGTGACATATGATGGATTCAATACATTTACTATACTGAAGACAGAATATGATAATTATATTATGTTTCATCTCATTAATGAAATGAATGGGGAAACCTTCCAGCTGATGTTGCTTTATGACCTAGAACCGGATTTGAGGTCAGACATCAAGGAAGAATTTGCAAAACTATTTGAGGAGCATGGAATCGTTAAGAGAAAATAGCATTGACCTATCTAATGCCAATCACTGTCTCCAGGCCCTAGAATGAAAAAAAAAAAAAAAAAAAAAAAAAACATAATCGGGTTCAGTCTTAGGAAGACAACTCGACGAGTAACTAATGGCTGCCTGATAAGGTCGCCATAGATCGGAA",
                               ("GGCAGGCCATTAGTTACTCGTCGAG", "CTCCCCTAATCGTTTGTCGGTGGAC", "GGGCACATTCCTCAGAAAGCGAAAA"),
                               ("TGAACCCGATTATG", "ACCTTCGCGC", "CGGCCACTGC")),
                              ("TTCCGATCTATGGCGACCTTATCAGTATGTACGAATTTAACCGTACCCTCTTGTCTTCCTAAGACCTTGCCGTCGTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTAGCATTGTGCACATTGGTTTATTTAGCACTTCTAACCACGCCGCAAAGAAAGCACTAAACAACTTTGCAAACCTCATTCGGTTCAGATGGGGCAAATGGGGGCCCCTGGCAGCAGGAGCCCAGAGACAGAGCCTGGGTTTGGATCATGGGACCAGTTAGGTTCTTGGGAAGGGGTACTGTGAAGCTGGGCTTTGAGGGATGTGTAGGAGTTTATTAGAGTATTATTTACTCATTTGTTGCCGCAGATTAAAGAGTAGAGCCAGCCCTATAACCTCCCCATTCAGTGATGTTTGTGCACCCAGACCGGGAACGCCTTGTCCACACTTAATCCGCCTAGTTTATCGCCATATTATGACCTTCAGGGCCTTTTGTCGCTCCTCTTCCAAGCAGAGAACACCTGAAGGCTACCGCCTGGGATCTGAGAGTGCTGTGTGGAAGTGGCTGAGAGCCAGGCGGCGCGCTCCACCCTCAGGCAGTGATCTAGTTTCTCTCGCATCGATCTGGCCGGCCTTGCCCCTCCTCCGCACCCTGCCCCGCCCAGCACTCTTCTCTTTGTTTCCCGGCAGTACTGTCCTGGAAAGGGCGGGGGACAGAGGCAGGGTGATGATGACAACCCCTTCCCTCACAGAAGGAATCCTTGGGGTCTGAATCGGTGACTCCGACGTCTTTTTACCTGGTGGCTGTTGGCAGGCCTGAGAGTTCTGACCCTCGGGTTCCAATATGAACCCAAAGAACCGGGATGTCCTTTGCTTACAGCCTAGGAAACAGGCCAGGAGCCAGCAGAAGCGACCCATGGTCTCCTTTAGACTTCTCCAGACGCAGCGCCACCCGCGGTGTCCTGGGCACTTGCTTCACTTCCAGGCCTCAGTTCCCTTTAAGCCTTGGCCTTGCTCCAGGGTTCAGTTTTCCCACTAACCAGTAAAGAAGGTTCAGTTGGAGGGGGTACCCTCTGAGTCTGAGGTTCTCTTGTCCTGGACCCCAGCCTGTGCACTGGCCCAGGCCCTATTTGGACCCTATTTAGAAGTAAAGTTGGGCAGGATATGACTGAACGTGTCAAGGACCCGGATAGTCTCATCCTGCCTCTACCACCCAGACCTCAAGTTCCCTTTTGTGCCTTATCCTTACCCTAGCCCTCGGTTTCCTCACTGAGCAAACCCGGTGGAACAGTGGCTTAAGGGATACTTAGGGGCCGGAGGATAGCTCTACAAAGCCAGGCCTCAGTTTATCAACTTAGAAGTAAAGAAGGGCAGGATGTTGCTGGAACAGTGGTGAAGGGTGGCCTCGGGGTTAGGGGATCACTCCCTGCACCTGCGACTTCAGGCCTTAGTTTCTCTATTTAGAAGAAACACGAGAAGGGAGGATAGGATGCTGCTGGAGTGAAGGCAGAGACTTGGAAGTTGAAGAATGGCGCCCCGCCCCGTGTATGCGACCCCTGTCCTCAGTTTCCCCATCGGTCTGAGCCTGACTGGACATTCCCTCGGGGAGCCCCGGCAGGCATCGCTAGGTCGGAGGCGGCGCTGCCAGAACAGGGTCGGGGTCCCAGGAGTGTAGCCCCCCGCGGCTACGCGCTGCGCGGAGCGGTGACATCACTCGGCGGGGAGGAGCGCACGGCTGTGGACCAGGCTCGCGCCGGGGCTCCTCGGGCCGCCCGCTCCAGTACGGGTCAGCAGCTGCTGACGTACTGAGAGGCGGGCGGCCGCCGAGGAGCCCCGGCTGAGCCTGGTCCAGAGCCGTGCGCTCCTCCCCGCCGAGTGATGTCACCGCTCCGCGCAGCGCGCAGCCGCGGGGGGCTACACTCCTGGGACCCCGACCCTGTTCTGGCAGCGCCGCCTCCGACCTAGCGCAGCCTGCCGGGGCTCCCCGAGGGAATGTCCAGTCAGGCTCAGACCGATGGGGAAACTAGAGGACAGGGGTCGCATACACGGGGCGGGGCGCCATTCTTCAACTTCCAAGTCTCTGCCTTCACTCCAGCAGCATCCTATCCTCCCTTCTTTTCTTCTAAATAGAGAAACTAAGGCCTGAAGTCGCAGGTGCAGGGAGTGATCCCCTAACCCCGAGGCCACCCTTCACCACTGTTCCAGCAACATCCTGCCCTTCTTTACTTCTAAGTTGAGAAACTGAGGCCTGGCTTTGTAGAGCTATCCTCCGGCCCCTAAGTATCCCTTAAGCACCTTCTCCACCGGCTTCGCTCCCAGTGAGGAAACCGAGGGCTAGGGTAAGGATAAGGCACAAAAGGGAACTTGAGGTCTGGGTGGTAGAGGCAGGATGAGACTATCCGGGTCCTTGACACGTTCAGTCATATCCTGCCCAACTTACTTCTCAATATGGTTAGGGCCTGGGCCAGAGTGCACAGGCTGGGGTCCAGGACAAGAGAACCTCAGACTCAGAGGGTACCCCCTCCAACTGAACCTTCTTTACTGGTTAGTGGGAAAACTGAACCCTGGAGCAAGGCCAAGGCTTAAAGGGAAACTGAGGCCTGGAAGTGAAGCAAGTGCCCAGGACACCGCGGGTGGCGCTGCGTCTGGAGAAGTCTAAAGGTGACCATGGGTCGCTTCTGCTGGCTCCTGGCCTGTTTCCTAGGCTGTAAGCAAAGGACATCCATCGGTTCTTTGGGATATTGGAACCCGGGTCACTCTCAGGCCTGACATGAGCGCTGCAGGCCATGAGAGCCTCGGAGACACCGATTCAGACCCCAAGGGGATTCCTTCTGTGAGGGAAGGGGTTGTCATCATCACCCTGCCTCTGTCCCCCGCCCTTTCCAGGACAGTACTGCCGGGAAACAAAGAGAAGAGTGCTGGGCGGGGCAGGGTGCGGAGGAGGGGGAAGACCACCCAGATCGATGCGAGAGAAACTACATCCGACTGCCTCGGGAGGGAGCGGAGGCGCGCGCGCCTGGCACTCAGCCACTTCCACACAGGCACTCTCAGGAGCCCAGCCAGGTCGCCTTTGGTGTTGTCGGCTGGAAGAGGAGCGCCACTGGGCTGAAGTCTGAAAAATGGCTGTAGAATCTAGCTGATTAAGTGTGGATCAAAGGCTTCCGGTTTCTGGGTCCGCACAAACATTACTGAAATGGGGAGGTTATAGGGCTGGCTCTACTCTTTAATCTGGCGGCAACAATGACGTAAATAATACTCTAATAAACTCCTACACATCCCTCAAAGCCCAGCTTCACAGTACCCCTTCCCAAGAACCTAACTGGTCCCATGATCCAAACCCAGGCTCTGTCTCTGGTCTCCTGCTGCAGGGGCCCCCATTTGCCCCATGTGAGGCCGAATGAGGTTTGCAAAGTTGTTTAGTGCTTTCTATGCTGGCGGGTTACAAGTGCTAAACAAAATGTAAACAATGTAAAAAAAGTAAAAAAAAAAAAAAAAAAAAAAAAACGGGCTTTCAGTCATAGGAAGACAAGTGCGCATGCCACGGAGGATCATGTCTGATAAGGTCGCCATAGATCGGAAG",
                               ("TATGTACGAATTTAACCGTACCCTC", "ACATGATCCTCCGTGGCATGCGCAC"),
                               ("CTTGCCGTCG", "TGAAAGCCCG")),
                              ])
    def test_real_sequence(self, read_sequence, true_barcodes, true_umis):
        # Test with real sequence data.

        barcodes = ["GAAGGAGGGATCCATAACGGCCCCA",
                    "TCCCCACTTTCACTCTCACCCCATT",
                    "AGTTGGCGCCCAAATGGTCAGAGGG",
                    "CATCAAAGGTTCACCGAATCTCCAC",
                    "GTCGCCTTCAACGTATACTGATATA",
                    "ACCAATTAGCAGCCATGGGAACTCC",
                    "ACATGATCCTCCGTGGCATGCGCAC",
                    "TATGTACGAATTTAACCGTACCCTC",
                    "GGGCACATTCCTCAGAAAGCGAAAA",
                    "GGCAGGCCATTAGTTACTCGTCGAG",
                    "CTCCCCTAATCGTTTGTCGGTGGAC"]
        detector = SharedMemoryStereoSplittingBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, SplittingBarcodeDetectionResult)
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert len(result.detected_patterns) == len(true_barcodes)
        for i, r in enumerate(result.detected_patterns):
            assert r.is_valid()
            assert r.barcode == true_barcodes[i]
            assert r.UMI == true_umis[i]


    @pytest.mark.parametrize("read_sequence",
                             [("CTGCTGACGTACTGAGAGGCGGGATGAAGCAGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGCTGC"),
                              ("TTCCTAAGACCTTGCCGTCGTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTAGCATTGTGCACATTGGTTTATTTAGCACTTCTAACCA"),
                              ])

    def test_real_sequence_no_bc(self, read_sequence):
        # Test with real sequence data.

        barcodes = ["GAAGGAGGGATCCATAACGGCCCCA",
                    "TCCCCACTTTCACTCTCACCCCATT",
                    "AGTTGGCGCCCAAATGGTCAGAGGG",
                    "CATCAAAGGTTCACCGAATCTCCAC",
                    "GTCGCCTTCAACGTATACTGATATA",
                    "ACCAATTAGCAGCCATGGGAACTCC",
                    "ACATGATCCTCCGTGGCATGCGCAC",
                    "TATGTACGAATTTAACCGTACCCTC",
                    "GGGCACATTCCTCAGAAAGCGAAAA",
                    "GGCAGGCCATTAGTTACTCGTCGAG",
                    "CTCCCCTAATCGTTTGTCGGTGGAC"]
        detector = SharedMemoryStereoSplittingBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, SplittingBarcodeDetectionResult)
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert len(result.detected_patterns) == 1
        for i, r in enumerate(result.detected_patterns):
            assert not r.is_valid()
            assert r.barcode == '*'
            assert r.UMI == '*'

# =============================================================================
# 10x Genomics Detector Tests
# =============================================================================

class TestTenXBarcodeDetector:
    """Test 10x Genomics v3 barcode detector."""

    def test_init(self):
        """Test basic initialization."""
        detector = TenXBarcodeDetector(DUMMY_BARCODES_16)
        assert detector.barcode_indexer is not None
        assert detector.min_score == 14  # Default for small whitelist

    def test_init_large_whitelist(self):
        """Test that min_score increases for large whitelists."""
        large_barcodes = [f"ACTG{i:012d}"[:16] for i in range(100001)]
        detector = TenXBarcodeDetector(large_barcodes)
        assert detector.min_score == 16

    def test_no_match_random_sequence(self):
        """Test that random sequence returns no valid barcode."""
        detector = TenXBarcodeDetector(DUMMY_BARCODES_16)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert isinstance(result, TenXBarcodeDetectionResult)
        assert result.read_id == "test_read"
        assert not result.is_valid()

    @pytest.mark.parametrize("read_sequence, true_barcode, true_umi",
                             [("TACACGACGCTCTTCCGATCTTCCATTGTCAACAAGGCTCATGGCCCCATTTTTTTTTTTTTTTGTTTTTTTTTTTTTTTTGCTTTTTG",
                               "TCCATTGTCAACAAGG", "CTCATGGCCCCA"),
                              ("TACACGACGCTCTTCCGATCTCAATCTAAGTACTGGTATCCAGGCTAGATTTTTTTTTTTTTTTTTTTTTTTTTTTTTT",
                               "CAATCTAAGTACTGGT", "ATCCAGGCTAGA"),
                              ("TACACGACGCTCTTCCGATCTTTCTAGTGACATGCTAGCGTCTAACATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT",
                               "GTTTCTAGTGACATGC", "TAGCGTCTAACA"),
                              ("AAGCAGTGGTATCAACGCAGAGTACATGGGATGAGAAGAATGGCTCTTAAGAAATTGAAGGTGATACCAAAGGAAGGTTACTTATTACTTTTGGACTTTGATGATGAGGACGATGACATAAAAGTTTCAGAGGAGGCTCTTTCGGAAGTAAAGAGCCCAGCATCTGATAAAAATGAGAATATATCGCCTCAAGCAGAAGCAGATGAAGATATGGGAGATGAAGTAGCCAATATTGGATATATCTGGAAGATAGATAATGCAGTCACAATTGGTAAAGAGTGAAAATGGTCGCCTCAAGTAAAAGGAGATGAAGACATGGGACATGAAGTAGGCAGTATGTTGGATAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGGGTGCAATAGGTCTATCGTGGGTTACGAGATCGGAAGAGCGTCGTGTA",
                               "CGTAACCCAGATAGAC", "CTATTGCACCCG"),
                              ("ATGTTCTGTAGAGAAATTTGATAGAAAAACTGCTATTTAAATAATTTAGCAACGAAAGAATACACTATAGTCTCAATAGGGCAGAGGCAGGAGTATTAGTGAAGTTCAAAGCTAGTGTGGGCTACATTGTATGACACTTGTCCACACCCCTGTAAAAGAGTGAGGAAGATGGGAGCTCATACATATGGTCCTAGCACGTGGGAGGTGGAATCCCAAGGATTAGGAGGCCATTGTCCTTACAGAGCAAGCTCTAAACTAACTTGTGCTGCATGAGACCCTGCCTCAACACAAAAAATAAAAACTCCTTACATGCATACATCTTAAACTTCAAATATTTTTCCCAAGTTACATGTTTTATATGTTCGCATAATCTATTATTTAACTTTCTTTATGGAACCAGGCTTGTATTAAAGTACCGCTAAGTCAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATCGGGAGTGTGGTACGCTAACTGAATAGAGATCGGAAGAGCGTCGTGTA",
                               "CTATTCAGTTAGCGTA", "CCACACTCCCGA"),
                              ("AAGCAGTGGTATCAACGATTCAGGTACATGGGGAAACATGCTGGCCTTTATTCAAATCTGTGAAAAAGACTAGGCTAGTGAACTCCAGGCCTATCTGGTATCTAAAAGAGCTTTCTGAACACCATCTTTGTAGAGATTTTGGCTTACATTATTAAAGCCTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGAAGATAATCAAGAAGATAGAAGAATGAAAGTAGAATCAAGATGTTGAACAGTGGTAGCCCTACCTTGACCTACAGAAGCGTGGCAGTAAGAGTCTCAATTAATGGTTAAAGTAGCTTGGGAATAAGTTAAGGCCAATATCTCTTTATAGAGACGGATTATTGTTAAACAACCACCACCATGGGATGAATAAGAATGCTCCTATAAGATATGCTATGAACTGCAACCTCATTAAAATAATAAATACTATGGATCCTTTAACTACATCCCAACCAAGGTGAATGAAGTCAGAAAGTGGACTTCTGACTGGAAGCTCTGACAAAACACTCTCTCTTAATAGTACTGCAGGAGGAATCTGAGGGTTATATAAAAAGTGATGCTGTTCCAAAAATTATGGTGGAATCATTCAGAGAGGACAAGGTTTCTCCAACGTAAACCATATGTACCGTGCACAATCATTGAAAGACTAAACACAATTTGGCCTTCTCCTTCCTTTAAACCTAGTCAAGTTTTTAGAAGGCAGCATATTCAAGATCTTTTAACCATTCTGTGGATGATACATTGCTGTGCGTCAGGTTTTATCAGAACAATAAAAACTTGCTTGATTCACTTGACCAGGTTTATGAATAGAATCTGACAAGGATGAGACTTTTATGATAGTGGCACTGGAAAATAAACTTGACTCTTTGGATATAATACAGCAAGAACTATAGAATGGAGATGATTATGTCAAAAATGAACATGTGACTTCTAGGACTGTCTACCTCAAAACTGACCAGGCTCAGAGAGAAGCACTTGTTTGCAACAGCACAGAAAAGATGTTGAAGGGATGGACTGTGGCAGCAACTACATGACACTGGATGCCTGGAAACAACTTGAAGACGATGATCAATTGTTATCTCTCATCAAAAGAAAAATTAAAAAAAGGGTGGTTGCCCAACGTCACGCATTGGCCAATCCAGCGCCCTACGGGGCTCCGATGCTACAAAAAAATAAAAAATTGACTCGATCGTTAAGCCTCAGGAGGAGATCGGAAGAGCGTCGAATA",
                               "CCTCCTGAGGCTTAAC", "GATCGAGTCAA"),
                              ("TACACGACGCTCTTCCGATCTAATCATCCACCTCACCCGGGAAGCGACCTTTCATTTTTTTTTTTTTTTTTTTTTTTTTATCAAATTTAATTGTCCCGCTCCAGCCAAAGAAGATCTGGGGGTGGAGGCTGCTTGAGAGGGAAGCCACAGCTGGCTCTGGGTGTGCAACTCTGGGGACAATGGCTATCCATTAACCCCTGTCAAGATTGTCTTTGGCTGGAGGCACACTTACAGCCTTCGCAGCTGCAGGAGCCACCTTAGTTCTACCAAGTGTAGCAGAGCGAGCGCAAGCTTCCCACCAGGAGCAGTCTCCGCGTGCAGAGGGTGCACCCAGCAGGGGGCGTTTCTTCTGCGCCCGCCACTGGGCGGCCCGCAGCCCATGTACTCTGCGTTGATACCACTGCTT",
                               "AATCATCCACCTCACC", "CGGGAAGCGACCTTTCA"),
                              ("TACACGACGCTCTTCCGATCTTCCATTGTCAACAAGGCTCATGGCCCCAT",
                               "TCCATTGTCAACAAGG", "CTCATGGCCCCA"),
                              ("TACACGACGCTCTTCCGATCTCAATCTAAGTACTGGTATCCAGGCTAGAT",
                               "CAATCTAAGTACTGGT", "ATCCAGGCTAGA"),
                              ("TACACGACGCTCTTCCGATCTTTCTAGTGACATGCTAGCGTCTAACAT",
                               "GTTTCTAGTGACATGC", "TAGCGTCTAACA"),
                              ("ACGGGTGCAATAGGTCTATCGTGGGTTACGAGATCGGAAGAGCGTCGTGTA",
                               "CGTAACCCAGATAGAC", "CTATTGCACCCG"),
                              ])
    def test_real_sequence(self, read_sequence, true_barcode, true_umi):
        # Test with real sequence data.

        barcodes = ["TACTGGCCACGTTACA",
                    "CGCTTCTAGCACTTGG",
                    "AGAGAGGAGCGTGCAC",
                    "GTCATCCTCATCCTAT",
                    "GTCAAACTCGATTTAG",
                    "GCAGGTGAGTCATTTC",
                    "TCCATTGTCAACAAGG",
                    "CAATCTAAGTACTGGT",
                    "GTTTCTAGTGACATGC",
                    "CGTAACCCAGATAGAC",
                    "CTATTCAGTTAGCGTA",
                    "CCTCCTGAGGCTTAAC",
                    "AATCATCCACCTCACC"]
        detector = TenXBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, TenXBarcodeDetectionResult)
        assert result.read_id == "test_read"
        assert result.is_valid()
        assert result.barcode == true_barcode
        assert result.UMI == true_umi


    @pytest.mark.parametrize("read_sequence",
                             [("GGCCCCATTTTTTTTTTTTTTTGTTTTTTTTTTTTTTTTGCTTTTTG"),
                              ("TCAAATTTAATTGTCCCGCTCCAGCCAAAGAAGATCTGGGGGTGGAGGCTGCTTGAGAGGGAAGCCACAGCTGGCTCTGGGTGTGCAACTCTGGGGACAATGGCTATCCATTAACCCCTGTCAAGATTGTCTTTGGCTGGAGGCACACTTACAGCCTTCGCAGCTGCAGGAGCCACCTTAGTTCTACCAAGTGTAGCAGAGCGAGCGCAAGCTTCCCACCAGGAGCAGTCTCCGCGTGCAGAGGGTGCACCCAGCAGGGGGCGTTTCTTCTGCGCCCGCCACTGGGCGGCCCGCAGCCCATGTACTCTGCGTTGATACCACTGCTT"),
                              ])
    def test_real_sequence(self, read_sequence):
        # Test with real sequence data.

        barcodes = ["TACTGGCCACGTTACA",
                    "CGCTTCTAGCACTTGG",
                    "AGAGAGGAGCGTGCAC",
                    "GTCATCCTCATCCTAT",
                    "GTCAAACTCGATTTAG",
                    "GCAGGTGAGTCATTTC",
                    "TCCATTGTCAACAAGG",
                    "CAATCTAAGTACTGGT",
                    "GTTTCTAGTGACATGC",
                    "CGTAACCCAGATAGAC",
                    "CTATTCAGTTAGCGTA",
                    "CCTCCTGAGGCTTAAC",
                    "AATCATCCACCTCACC"]
        detector = TenXBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, TenXBarcodeDetectionResult)
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert not result.is_valid()
        assert result.barcode == '*'
        assert result.UMI == '*'

class TestVisiumHDBarcodeDetector:
    """Test Visium HD spatial barcode detector."""

    def test_init(self):
        """Test basic initialization."""
        barcode_pairs = [DUMMY_BARCODES_16, DUMMY_BARCODES_15]
        detector = VisiumHDBarcodeDetector(barcode_pairs)

        assert detector.part1_barcode_indexer is not None
        assert detector.part2_barcode_indexer is not None
        assert detector.min_score == 13

    def test_no_match_random_sequence(self):
        """Test that random sequence returns no valid barcode."""
        barcode_pairs = [DUMMY_BARCODES_16, DUMMY_BARCODES_15]
        detector = VisiumHDBarcodeDetector(barcode_pairs)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert isinstance(result, TenXBarcodeDetectionResult)
        assert result.read_id == "test_read"
        assert not result.is_valid()

    @pytest.mark.parametrize("read_sequence, true_barcode, true_umi",
                             [("TACACGACGCTCTTCCGATCTAATACCACAGTCACTAACCTGCAAGAAGATCATGTGCAAGACTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTCCATTGCTGAGTGAAAATACAGGTTAAAATGCAAAAACAATGCAAAGCAATAGTCTCTACCTTTTCAAATACATTACATGTCTAGAATAGGACCTTATAAAGTTTTATGCTATGTTCTGGACAGTCCTTCATTAGTGGTCCAAACATTTTATCATATCTGGGCTGAACTTTATTAATTTATTTATGCATTTAGTAAATAAGTATGGAGCATCTTCAATGGGTCAAAATGTATTCAAGTCATCAAAGCAGGCGCATGAAGTTAAAATAGATCAAGCTAATGCTCTTACTTAGATTTAGATTCCAGCTGAGGTGCTCATGAGCATTGTGAAGACAAGGCAGAATGGAGGGACAGTGTAAATGGGAAGGAAAGTGACTGTCTTATATGGGAGTCATGGAAGACTTCCACGATGGCTAGCCCCTGTTTAAGCGAAGTGAATGTAGTGAAGGAAATGTCCATGCAGGGGAGCTGCAAGCTCAAGTTTCCTGAAGTAGGGATGTGGGTGCAGCTGGGAAGACCATCAAGGGGATCAGTATGAATGGGGTGAGGGGACAGACTGTGAGTGACAAGAGATGATGCAAATATGTTAAGCATAAGTGAGCACCACTGAGTCCCCAGAAGCACTTGCAGAGATAATACATGGAAAACATAAGTTGCCAGGACACTTTAAAAGCAGTACATATGGGGGTAGTCACATGTAAAGTGGACACGTCCTTTGTTTTTACTCTATTTTCATGGTAGCATAATTTTCCTTTTGAATCATAGAAAGCAAAAAATTAAGTCTCTATAAAATGACGGACACAAAGAAATATCTGTTCATTTAAGATACTTTATTGCTAAACCTCTCAGTAAAATACCCAAAGAGTTTAAGCACATATTTAAACCTACATCACTTGAAGCATGTGGAATAGTATCTCAATTGAAGAGAAGTAAACAAATTGATATTCTATTACCCCAAAATAAATTATTTAAATTATTTGTGGAAAACTAAGGGTGGATTTAGGGAGATGATCCAGTGGGCAAAACAAATATCATACAAACATAAAGACCAGAGTTGTGGATCTTCAGAACCTTCATAAATTTTGGAAGGGTGTGGGCACCCACCTATAATTCCAGAGGTTGAAACAAGGAATCAGAAGAGGAAAATGACTATCTAGACCAGCTGACAGAAGAGATCTTGGCTTAATTGAGAGATCTTTTCTTCAATCGAAAAGGTAAACAGCCAGCCAGTCATTAAGAAAGACTTCCATGTCACCTGTAAGTCTCTGTATATAAACACAGACACAAACACACTTAAACACACATGTATTCAAGCACATACAAACACCATTTGTGTCCGGCGACACCAATGGTAGAGCATGGATCCATACACCTTCAAAAGAGAATACTAGCAGAATGCCATTGTACTCTGTGTATGTTTCTGCATCCAAATGTCTATACCCATGTGTGTCACAAGCAGAAACTTCTTCTCATGGGCTTTTCCTTCCATCTTCTTTAGATATGCACTACTAGTGGCCTGTAGAAAAATACTTGTAGAAATGGTGTTTAAACAGTCTGAGCCACGAGTGTTTAGAAAAACATAACCAACTCATGCTAAACTTCACATTAGCCATTCTAAAACAGATATTGCATTTACAGCATTATTTCTATTTTCTGAAAAGCAAACATTTGAAAAGATAAATGTATTAATTCTTCCACTTGACATCAATGTGACCTGACTCTAGGTCACTAGGTACCTAAGAAAATGTGATAGGTATGGAGTTGCGTTACAATACCATACAATGCTAGACTTAAAATCCTAAGGAATACTTTGCTTTCTCCACAACTTTCTTGAATGCACTTTTCACCTCCTTGTTCCTTAGACTGTAAACCATAGGGTTAAGCATGGGGATGACCATGGTGTAGAACACAGACACGGTTTTATCAGTGTCCATGGAGTGGCTGGAGGTGGGTTGTAAGTACATGAAAATAACAGTCCCGTAGAAAATGGAGACAGCAGTGAAGTGAGAAACACTGGTAGACATAGCCTTGGGCTGGTATCCGCGCTGACGCATCCTGAAGATGGTGATAAAAATGAATGTATAAGATTCAAAATAACAAGGAGTGCAGAACAGATAATGAAGCCTGCTCCATAAATGAGTACTATCATCTCACTAACATGTCTATCAGAACAGGAGAGAGTCATGACTGCTGGAACATCACAGAAAAAGTGATGAACTGCATTGGATCCACAAAATGAAAGCGGGAATGTGTCCCCAGTGTGGATGGAGGAATTCAGGAAACCACCAGTATAGCAGGCCATTATCAGACATCTACGCACCGTTGGAGTCATGATGGTGGTATAATGCAGGGGTTTGCACACTGCTGCATACGATCATTCAGGCCATTGCCGTCAAAAGTAAATCTTCTGTAGTGACAAAGGCTGAGAAGTGAATCATCTGAGCAACACAGGCATTGTAGGAGACAACTATGTTTCCTACAAGAAGTCCAGTTAAAATTGTTGGAGCTACAGCTGAGGAGTAAAGGTGTCAGAGACAGGTTAGCAAGAAAACAGTACATGGGAGTGTGGAGTCGAGAATCCCAGAGAATCAGCACAATCATTCCCTAGTTTCCAATCACATTGGTGAAATAGATAAAGCTGATTATGATAAACAGAGGGGCCCTCAGTTCTAGTGCGTTCGTCAGTCCTAGGAGGATGAACCCGTGACTGAAATATCTGTGTTCTGTTCTCGGCATTAATGTTATTTGGGAACACCAGAATGTGCCCTTGTTCCTTGAACAAGGGTGACCGTCAGTTCTGAATCATATGCTTGCAATGAGACGTCCTTCCAAGGAGTAATAACCAGGGATCATCAGAGACGCTCTCATTTTTATCCTGTGTGTTTTTCTCAACCATGTTTATAGATTCCTAGGAAATCTAAGTCAGAAATTCAATGTGTATGCAGGATGTGACATTCACATGACTAATAAGGATGAAGGTCGGCCAGTATGAAGTGTGGTCCTGGTCTTCTAAACTAATGTTGGACTTCTTGAGAGAACAATGCATGTGAACCAGCTTGGTATTATTTATTCTTTGAGCTCTCTGGGGATCTTTCCCCTGAGGATATCTGTAGGTCCTCATTTCACCTTCCTAAGAAATGTACTCTGCGTTGATACCACTGCTT",
                               "GTCACTATACTGCAAG|AAGATCATGTGCAAG", "AATACCACA"),
                              ("TACACGACGCTCTTCCGATCTTTCGGTACTCGTTGAGCATCCCCAGATATGTCATGCACTGCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTCAAAGTAGTAGGTCTTCCTCCAGTGTTAATCAGTGGAACCATTTAATGTTAGCTCTTTGTCATCAGAGACGAAGCTACATCACTTTTATGAACTCATTTATTACTCAGATGGTTGCATTCCATTCAAGCGCACTTAATACAGTCCATTCAAGAACACTTAGTTGATTGCAGTTAAAGAGACCAATTGGCAATGGGACTTTCAAAAATACAACTTATTATGTTTAAGTAATTACTTAAACTATCTAGACCTTTTACATATTAAAATAGAAGTGAGAAAATAGATCTTTGGAATCTAGATCTATAGTCAACGGCTGAATACACCTCTGCTAGATTGGCATGATCAATCCGGAGTATGGCTAAGATGCAAGAACAGGTCAGGAGTGTTTTACAATTAGTCACATCTGGTGAAACGAAAAAAGAAAAAAAGGTAGCTAAAATGAAGTCCTACAATGATCATATTGTGTAATATTTTTCAGACCAACCCATATCCTGAAATCTCGAACATTCAACTTCTGAACTGATTTCTAGCTACTGAAAGGGAATTTTAAGAATCCAGTGGGGTTGCATCTAAAGTGAGGCTGCTTTTTCACTGTGGACAAAATACTCTTGCTTTTTGGGCAATGGCGACAGTACATAGGTAGGCGATGAGAATTTCCAATGCTTTTTGAGAAGCATGGGGTGCTGATCTGGAAAATCTCCATTGTTTTGTGAGGCTTCTTTGGGTCTTGAGAGCTTTGCTCATCTATGAACGCCTCCTTTCTCTGTTCCTGCAACCGAAGGCATCGGCTGGATCTTCAATCTTCACTTCTGATAGGATTCCCGAACTTTGGCCTGCAGAGCGTCACATGTCTTCTTGGCGTCCCCCAGAAGCATAGCTGTGTTAGGTTTGTAGAAGATCGGATTGTCCAGCGCCAGGTGGCCCCACGCCAAGGGACCCTTCATGACAATGACCATTTTAAACCTTCCAGATCTCAAAGACCGGCATCCATTCAATTATAGAATTGGGGTCTTCTTTGTGCCGTCGCAATTCACAGTTACGTTGCTCCAATGACAAGAACCTTAGTCGATGTTGGAGAAAATCAGTTGCTCATAGGCTGCATTTCTGACACAATATCATAGGGCACTCCCGCCTCGGCCAGGAGCACATTAAGCTGACCAGGCATTCGGCCCGCAACTGGGTGGATTCCAAACCTGACTTTTTTGCCTTGTTCAGTAAGCATCTTCACCAAATCGGCAATGGGGTACTGAGCTTTAGCAGCACAGAGCCCATACCCTGGAGTAATAACAATGCTGTTAGCTTCCCGGATCATCTCAACTGCGTTGTCCAGGTTGATTTCTGTATGTGTGCCAGAAATTTCCATGGGTTTTCCACCAGCTGTTGACGTTGTGCCATAGCCTCCAAGAATGACATTAGCCAGGGAGCGGTTCATGGCCACACACATGATGTACGACAGGATTGCACCAGAGGAGCCGATGAGCGCGCCCACGATGGTCAGCAGGTTGTTGTTGAGCAGGAAGCCCTCGGCACACAGAGCCCAGCCCGAGTAGCTGTTTAGCACGGTGATGACGACAGGCATGTCAGCACCACCAATAGCAGCCGTCAAAGTCACACCCATGAGAGTAGAGAGTGCGGACACAGAGCCCAGACAGGTGATGCCCGTGGTAAAGCTAGGGTCAGCCATAAATGCAATTATCCCACCCACGCTAGCAGCCAGCAGGCCTGCATTGAGTGCGTGCCTGTCCAGGGAGCAGCAGAGGAGCTGATTTCAAAATACCCTGTAATTTTCCGTAGGCAACAAGAGACCCACTAAAGGTGACTCCGCCGATGTAAGTGCCAAGGTAAGCCACAATCTTGGTGAAATTTGACGTGGCATCCATTGCAAAAGTGGATACTCTGTACTCGGCCATGCAGGTAAGAACTGCGGCCAGCCCCACCAAACTGTGAAAAGCAGCGGGCATCTGTGGCAAGTCGGAAATCTGGATCCGCTTTGCGATCGTCAGGCCGATGGTGCCACCCATTGCCATTGCTCCAGACATCTGAGCTAACTGCTTCACGGCTTCAGGCCTCCAAGGTGGCTGCCAGGCCTCCTGCAACCCCGATCATGCCCAAGGCATTGCCGAGTCGTCGTGTTCCCTGAGTGGAAAGGCCGCCCAGGGCCCCAACACAGCACAAGCCTGACCCAGGTACATGATTTCTTCGATGTTATAGCCACCGTAGAGAGCAGCTAAATATCCACCTACGAAGGTGCCACCAGGGAGCAGATACAGATAATTATACTCTTGAGGGTCTGGGTCGCTTGAACATGTCCAGCATTAACTGAGTCCAAAACCACCGGAATTGGAATAGAGCTGGTGCTATTAAGTTGTGCACCTCCTTGCATTGTGGTGGCAAAGAGCTTCATTCTAGTCATGTACTTTGATCACTTTCGCGTATCCTTGGCCACACAAGAGTCTGCAAGTCCCCACACTCCAAGGGTTCTGCACCAAGGGATTTGAACTGTTCCAAAGCAGCAGCTCTTGTATCAAATCCTCGCACAACTGCGCCCATCGACTTTGCTGCCCCCGCAGAAGCGAGCCCAGCAACGCCACCACCAACTATCAGGATCTTCGCAGGGGGAACTTTTCCAGCAGCTGTGATCTGCCCAGTGAAAAACCTCCCAAAATGATTCGCTGCTAAAACAACAGCCTTATAACCAGAGATGTTGGCCATGGAACTGAGAGCATCATAGCCCTGAGCTATTGTCACTCTTGGAACCTGGTCCATCGCCAGAACTGTGGTTTTTCTTTCAGAAAGTTTATTGAGCAAGTCTGGATTTTGGGCTGGGTAGATGAAGCTAATTAGAGTTCCTGATGGCTTTAAAAAGTCAGCTTCGTGAGCGCCTAACGTCGGGTTCACCATGGGGGCCCTCACTTTGACCACCAGATCAGAAGCCAGAACTTCCTTCATCCCTTGGATCTGGGCCCCTGCTGCTCTGTAGAGGTCATCTGGGAACTTGGAAGCTTCGCCTGCGCCTGATTCCACGACAACATTGAAGCCCTGCTTGACCAGGGCCTGGACCCCCGCAGGAGACAATGCAACTCGCTTCTCGTTTTGGAAAATCTCCTTGGGGACCCCAACTGTCAACTGCTAATATGGAATTCCTGGCTTTACCGGGGATTTACACCACAGTGCCTGGTGAGTACGAAGCGTTCGTACAAAGTCTCTCTTCCCAGGTAGAACCTTAGAGGACCCCAAGTTGCTAAGGAAAGGACATGAACAGCCAGCCACCACCGTCTTCAGTAGGCGCCATGCTGCTTTATGCTCCCAACGTTTCGGATCCCCAATTCCTTGAAGGTGGATTACTGGACCGGCAGGCGGGACAGATGGCGACCCCGGGCTGCGAGCAAACGCCACGTCGAGCTAGCAGACCCGGGGTTGGCCCGCGGCGTTGTGCCTCATGTACTCTGCGTTGATACCACTGCTT",
                               "GTTGAGCATCCCCAG|ATATGTCATGCACTG", "TTCGGTACTC"),
                              ("TACACGACGCCCTCTTCCGATCTATCGTTTTTAGCTTAAATGCATCAGCTTATCAGCGCGAAGCCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTGAATTTTTAGGGTCACTTATATATACTATCATATCATTACCTGCAAAAAGTGATATTTTGACTTCCTCTTTTCCAATTTGTATCCCCGTGATCAAATGGGACTTGGTTCCATAACCTGAACAACGCCAAAGAGCCAAAGAGCGAGTGCTCTCACCGGGGAACAAATGATATGAGTGGAACTAGAAAACGTAGGCTTGAGACAAAATAATCAAGCCAGTGACAGAAAGTGAGAGGCCCTTGGGAGTCCTGTGAGGAGGGTTAAGGAGTGTTATGGGTGACGGGACTCCAGGCTGCAGAACTGATGTCTCCAGGAAAGGGGAAAGCATCGCTGTCAGAAGACCCAGTGTTCGAAGCTCCCAGAAGGAGGAATATATAGTTGGCTCGGGTGGCAAGGGTCTGCTTGAGTCCTCATTTGTGTTTGGAATCTGTTTTCTTCAGTTGTGGGGCTAAAATGGAAGTTATTTGAAGATGACAGACATTCCTGGATTTTGTTTTTAAAAAGTCCAGCTTATTGTGATGGTATCAGAAGGACAGTGGGAACAGCGCGGAAAGCCACTTTTCCTAGACTATGGGGCTACAGGTTAGATGTACTCTGCGTTGATACCACTGCTT",
                               "GCTTAAATGCATCAG|CTGATCAGCGCGAAG", "ATCGTTTTTA"),
                              ("TACACGACGCTCTTCCGATCTAATACCACAGTCACTAACCTGCAAGAAGATCATGTGCAAGACT",
                               "GTCACTATACTGCAAG|AAGATCATGTGCAAG", "AATACCACA"),
                              ("TACACGACGCTCTTCCGATCTTTCGGTACTCGTTGAGCATCCCCAGATATGTCATGCACTGCAT",
                               "GTTGAGCATCCCCAG|ATATGTCATGCACTG", "TTCGGTACT")
                              ])
    def test_real_sequence(self, read_sequence, true_barcode, true_umi):
        """Test with real Visium HD sequence data."""
        # BC1 (16bp) and BC2 (15bp) whitelists extracted from test data
        bc1_whitelist = [
            "GTCACTATACTGCAAG",
            "GTTGAGCATCCCCAG",
            "GCTTAAATGCATCAG",
            "GTCTTGTGTGCGCACG",
            "GTCGGCAGATCTATCG",
            "GTATGCTGCTTCCTAG",
            "GCATCATATCCGTCAG",
            "GTCATCTGACATTCTG",
        ]
        bc2_whitelist = [
            "AAGATCATGTGCAAG",
            "ATATGTCATGCACTG",
            "CTGATCAGCGCGAAG",
            "TAGATGGCAGCCAG",
            "TCGATATCTGTGTCG",
            "TTGCGCATTTATAG",
            "TCTCACGAGAGCTG",
            "TCATTTGCTCTGATG",
        ]

        detector = VisiumHDBarcodeDetector([bc1_whitelist, bc2_whitelist])
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, TenXBarcodeDetectionResult)
        assert result.read_id == "test_read"
        assert result.is_valid()
        assert result.barcode == true_barcode
        assert result.UMI == true_umi


# =============================================================================
# Curio Detector Tests
# =============================================================================

class TestCurioBarcodeDetector:
    """Test Curio platform barcode detector."""

    def test_init_joint_barcodes(self):
        """Test initialization with joint barcode list."""
        detector = CurioBarcodeDetector(DUMMY_BARCODES_14)
        assert detector.barcode_indexer is not None
        assert detector.min_score == 13

    def test_init_split_barcodes(self):
        """Test initialization with separate left/right barcode lists."""
        barcode_tuple = (DUMMY_BARCODES_8, DUMMY_BARCODES_6)
        detector = CurioBarcodeDetector(barcode_tuple)
        # Should have 3*3 = 9 combined barcodes
        assert len(detector.barcode_indexer.seq_list) == 9

    def test_no_match_random_sequence(self):
        """Test that random sequence returns no valid barcode."""
        detector = CurioBarcodeDetector(DUMMY_BARCODES_14)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert isinstance(result, LinkerBarcodeDetectionResult)
        assert result.read_id == "test_read"
        assert not result.is_valid()


    @pytest.mark.parametrize("read_sequence, true_barcode, true_umi",
                             [("TACACGACGCTCTTCCGATCTTTTGACTTCTTCAGCGTTCCCGAGAGCAATTCCTTTTCTGTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT",
                               "GTTTGACTGCAATT", "CCTTTTCTG"),
                              ("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAATTAGTCTCTACATTGTCTCGGGAACGCTGAAGAAGCGATCTAGATCGGAAGAGCGTCGTGTA",
                               "AGATCGCTCAATGT", "AGAGACTAA"),
                              ("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAGGATTGAACCGCTTCTCGGGAACGCTGAAGAGTCACCGGAGTCGGAAGAGCGTCGTGTA",
                               "CCGGTGACAGCGGT", "TCAATCCTA"),
                              ("TACACGACGCTCTTCCGATCTTCATTCTGTCTTCAGCGTTCCCGAGACGGAGTCCCCCCTAATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTGATGTTAGAATATATTTTTATTGCTACATTTATATACAATTATAGCACCAACCCACACAGGAAGAAATGTACTGCATGGAGTTTCTGCAGATTCCAC",
                               "TCATTCTGCGGAGT", "CCCCCCTAA"),
                              ("GGCTTGCTGAGGGAGCTTATAACTTGCACCTAGAGGGTTTACCCACTTTGTGGATTTGATTTATCGAGCACCATAGCAACCAATCAAGGTGAAGACTCTAGGAGTTTATGAAAGAGGCTTATGTTTTCATTTTGAGTCAGACATTCTTTTCTCATTCTCAAATCTGTTTTAAACGCTCCAATTTTAAAAATGCCAATGAAAATTTTATAATGCTTCTGTAGTAACCATATGCAGTTTACTTTGAATTTAGGAAAACGATTTTGTATGATGAAATATTGTGCAGAATCTGTAAATAAGGTAGCTAAAAAATTAAAAAAAGTCTAATTAGAAATAAAAAAAAAAAAAAAATAAAAAAAAAACTTGGCTTTAGCACACTCTCGGGAACGCTGAAGAGATGGTGAAGATCGGAAGAGCGTCGTGTA",
                               "TCACCATCGTGGCT", "AAAGCCAAG"),
                              ("GAAAGTTTGAAAACAAAAAACTATAGTCTTACTGAAAGAAAACCATTGGTTTCAGGAAGGTGGGGATTCATTGGCCACAAAAGGGACTGAGGAAACTTTTTATGGGTAATGGAAATATTTTATATCTTGTGGTGGCACCAATTATACAACTGTATGAACACATTTGTCAAAATTCTAATCGTATTATACACAACATGAGTGACTTTAACTGTCTATAAATTATATCTCAATAAAATCCATCTTAAAAGATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGCTTGATTGAAATGTCTCGGGAACGCTGAAGAATACATGAAGATCGGAAGAGGGCGTCGTGTA",
                               "TCATGTATCATTTC", "AATCAAGCG"),
                              ("CAAATGCCTTGCTCCCATTCACGTCAATACCAAGAACCATGTTCTCCAGAGAATAAATTTAATTTATGACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATATTAATGACTCCCTGTCTCGGGAACGCTGAAGAAGTTAGCAAGATCGGAAGAGCGTCGTGTA",
                               "TGCTAACTCAGGGA", "GTCATTAATA")
                              ])
    def test_real_sequence(self, read_sequence, true_barcode, true_umi):
        # Test with real sequence data.

        barcodes = ["GTTTGACTGCAATT",
                    "AGATCGCTCAATGT",
                    "CCGGTGACAGCGGT",
                    "TCATTCTGCGGAGT",
                    "TCACCATCGTGGCT",
                    "TCATGTATCATTTC",
                    "TGCTAACTCAGGGA",
                    "GCCGAAGCCGGGGA",
                    "CAGCATTGCATTGC",
                    "TACAGGTAAATTCG",
                    "TCGGTGAGACCAGA",
                    "CATAGCAGCGAGTA",
                    "GGACTCCCGATTAT",
                    "CTTGGCTGTCGGAG"]
        detector = CurioBarcodeDetector(barcodes)
        result = detector.find_barcode_umi("test_read", read_sequence)

        assert isinstance(result, LinkerBarcodeDetectionResult)
        assert result.read_id == "test_read"
        # Random sequence should not match any barcode
        assert result.is_valid()
        assert result.barcode == true_barcode
        assert result.UMI == true_umi


class TestCurioIlluminaDetector:
    """Test Curio detector optimized for Illumina reads."""

    def test_init(self):
        """Test basic initialization."""
        detector = CurioIlluminaDetector(DUMMY_BARCODES_14)
        assert detector.barcode_indexer is not None
        assert detector.min_score == 14

    def test_no_match_random_sequence(self):
        """Test that random sequence returns no valid barcode."""
        detector = CurioIlluminaDetector(DUMMY_BARCODES_14)
        result = detector.find_barcode_umi("test_read", RANDOM_SEQUENCE)

        assert isinstance(result, LinkerBarcodeDetectionResult)
        assert result.read_id == "test_read"
        assert not result.is_valid()

    def test_real_sequence(self):
        """Test with real sequence data.

        TODO: Add real Illumina Curio read sequence.
        """
        pytest.skip("TODO: Add real test sequence from data")


if __name__ == '__main__':
    pytest.main([__file__, '-v'])
