# geney/mirna/reference.py — miRNA reference panel management.
"""
Manages miRNA reference sequences for binding site analysis.

Three modes of operation:
  1. **Bundled panel**: ~150 high-confidence, broadly-expressed human miRNAs
     included with the package. Sufficient for most analyses.
  2. **Full miRBase**: Load from a local mature.fa download. Covers all ~2,600
     known human miRNAs. Download from https://mirbase.org/download/mature.fa
  3. **Custom panel**: User provides a dict or file of specific miRNAs.

Usage::

    from geney.mirna.reference import get_mirna_panel

    # Bundled (default — no download needed)
    seeds = get_mirna_panel()

    # Full miRBase
    seeds = get_mirna_panel(source="/path/to/mature.fa")

    # Tissue-specific (filter bundled by known tissue expression)
    seeds = get_mirna_panel(tissue="brain")

    # Custom
    seeds = get_mirna_panel(custom={"miR-21": "UAGCUUAUCAGACUGAUGUUGA"})
"""
from __future__ import annotations

import re
from pathlib import Path
from typing import Optional


# ============================================================================
# Bundled high-confidence human miRNA panel
# ============================================================================

# Top ~150 human miRNAs by expression level and functional annotation.
# Curated from miRBase v22.1 + TargetScan conserved families.
# These cover the majority of miRNA-mediated regulation in most tissues.
# Sequences are the mature strand (5p or 3p as annotated in miRBase).

BUNDLED_MIRNAS: dict[str, str] = {
    # --- let-7 family (tumor suppressors, broadly expressed) ---
    "hsa-let-7a-5p":    "UGAGGUAGUAGGUUGUAUAGUU",
    "hsa-let-7b-5p":    "UGAGGUAGUAGGUUGUGUGGUU",
    "hsa-let-7c-5p":    "UGAGGUAGUAGGUUGUAUGGUU",
    "hsa-let-7d-5p":    "AGAGGUAGUAGGUUGCAUAGUU",
    "hsa-let-7e-5p":    "UGAGGUAGGAGGUUGUAUAGUU",
    "hsa-let-7f-5p":    "UGAGGUAGUAGAUUGUAUAGUU",
    "hsa-let-7g-5p":    "UGAGGUAGUAGUUUGUACAGUU",
    "hsa-let-7i-5p":    "UGAGGUAGUAGUUUGUGCUGUU",
    # --- miR-1/206 family (muscle-specific) ---
    "hsa-miR-1-3p":     "UGGAAUGUAAAGAAGUAUGUAU",
    "hsa-miR-206":      "UGGAAUGUAAGGAAGUGUGUGG",
    # --- miR-9 (brain-enriched) ---
    "hsa-miR-9-5p":     "UCUUUGGUUAUCUAGCUGUAUGA",
    # --- miR-10 family ---
    "hsa-miR-10a-5p":   "UACCCUGUAGAUCCGAAUUUGUG",
    "hsa-miR-10b-5p":   "UACCCUGUAGAACCGAAUUUGUG",
    # --- miR-15/16 family (cell cycle) ---
    "hsa-miR-15a-5p":   "UAGCAGCACAUAAUGGUUUGUG",
    "hsa-miR-15b-5p":   "UAGCAGCACAUCAUGGUUUACA",
    "hsa-miR-16-5p":    "UAGCAGCACGUAAAUAUUGGCG",
    # --- miR-17~92 cluster (oncomir) ---
    "hsa-miR-17-5p":    "CAAAGUGCUUACAGUGCAGGUAG",
    "hsa-miR-18a-5p":   "UAAGGUGCAUCUAGUGCAGAUAG",
    "hsa-miR-19a-3p":   "UGUGCAAAUCUAUGCAAAACUGA",
    "hsa-miR-19b-3p":   "UGUGCAAAUCCAUGCAAAACUGA",
    "hsa-miR-20a-5p":   "UAAAGUGCUUAUAGUGCAGGUAG",
    "hsa-miR-92a-3p":   "UAUUGCACUUGUCCCGGCCUGU",
    # --- miR-21 (oncomir, ubiquitous) ---
    "hsa-miR-21-5p":    "UAGCUUAUCAGACUGAUGUUGA",
    # --- miR-22 ---
    "hsa-miR-22-3p":    "AAGCUGCCAGUUGAAGAACUGU",
    # --- miR-23/24/27 cluster ---
    "hsa-miR-23a-3p":   "AUCACAUUGCCAGGGAUUUCC",
    "hsa-miR-23b-3p":   "AUCACAUUGCCAGGGAUUACC",
    "hsa-miR-24-3p":    "UGGCUCAGUUCAGCAGGAACAG",
    "hsa-miR-27a-3p":   "UUCACAGUGGCUAAGUUCCGC",
    "hsa-miR-27b-3p":   "UUCACAGUGGCUAAGUUCUGC",
    # --- miR-25/93/106b cluster ---
    "hsa-miR-25-3p":    "CAUUGCACUUGUCUCGGUCUGA",
    "hsa-miR-93-5p":    "CAAAGUGCUGUUCGUGCAGGUAG",
    "hsa-miR-106b-5p":  "UAAAGUGCUGACAGUGCAGAU",
    # --- miR-26 (broadly expressed) ---
    "hsa-miR-26a-5p":   "UUCAAGUAAUCCAGGAUAGGCU",
    "hsa-miR-26b-5p":   "UUCAAGUAAUUCAGGAUAGGU",
    # --- miR-29 family (fibrosis, ECM) ---
    "hsa-miR-29a-3p":   "UAGCACCAUCUGAAAUCGGUUA",
    "hsa-miR-29b-3p":   "UAGCACCAUUUGAAAUCAGUGUU",
    "hsa-miR-29c-3p":   "UAGCACCAUUUGAAAUCGGUUA",
    # --- miR-30 family ---
    "hsa-miR-30a-5p":   "UGUAAACAUCCUCGACUGGAAG",
    "hsa-miR-30b-5p":   "UGUAAACAUCCUACACUCAGCU",
    "hsa-miR-30c-5p":   "UGUAAACAUCCUACACUCUCAGC",
    "hsa-miR-30d-5p":   "UGUAAACAUCCCCGACUGGAAG",
    "hsa-miR-30e-5p":   "UGUAAACAUCCUUGACUGGAAG",
    # --- miR-31 ---
    "hsa-miR-31-5p":    "AGGCAAGAUGCUGGCAUAGCUG",
    # --- miR-33 (lipid metabolism) ---
    "hsa-miR-33a-5p":   "GUGCAUUGUAGUUGCAUUGCA",
    # --- miR-34 family (p53-regulated) ---
    "hsa-miR-34a-5p":   "UGGCAGUGUCUUAGCUGGUUGU",
    "hsa-miR-34b-5p":   "UAGGCAGUGUCAUUAGCUGAUUG",
    "hsa-miR-34c-5p":   "AGGCAGUGUAGUUAGCUGAUUGC",
    # --- miR-96/182/183 cluster (sensory) ---
    "hsa-miR-96-5p":    "UUUGGCACUAGCACAUUUUUGCU",
    "hsa-miR-182-5p":   "UUUGGCAAUGGUAGAACUCACACU",
    "hsa-miR-183-5p":   "UAUGGCACUGGUAGAAUUCACU",
    # --- miR-100/99 ---
    "hsa-miR-100-5p":   "AACCCGUAGAUCCGAACUUGUG",
    "hsa-miR-99a-5p":   "AACCCGUAGAUCCGAUCUUGUG",
    # --- miR-101 ---
    "hsa-miR-101-3p":   "UACAGUACUGUGAUAACUGAA",
    # --- miR-103/107 ---
    "hsa-miR-103a-3p":  "AGCAGCAUUGUACAGGGCUAUGA",
    "hsa-miR-107":      "AGCAGCAUUGUACAGGGCUAUCA",
    # --- miR-122 (liver-specific) ---
    "hsa-miR-122-5p":   "UGGAGUGUGACAAUGGUGUUUG",
    # --- miR-124 (brain-specific) ---
    "hsa-miR-124-3p":   "UAAGGCACGCGGUGAAUGCC",
    # --- miR-125 family ---
    "hsa-miR-125a-5p":  "UCCCUGAGACCCUUUAACCUGUGA",
    "hsa-miR-125b-5p":  "UCCCUGAGACCCUAACUUGUGA",
    # --- miR-126 (endothelial) ---
    "hsa-miR-126-3p":   "UCGUACCGUGAGUAAUAAUGCG",
    # --- miR-128 (brain-enriched) ---
    "hsa-miR-128-3p":   "UCACAGUGAACCGGUCUCUUU",
    # --- miR-130/301 family ---
    "hsa-miR-130a-3p":  "CAGUGCAAUGUUAAAAGGGCAU",
    "hsa-miR-130b-3p":  "CAGUGCAAUGAUGAAAGGGCAU",
    # --- miR-132/212 ---
    "hsa-miR-132-3p":   "UAACAGUCUACAGCCAUGGUCG",
    # --- miR-133 (muscle) ---
    "hsa-miR-133a-3p":  "UUUGGUCCCCUUCAACCAGCUG",
    "hsa-miR-133b":     "UUUGGUCCCCUUCAACCAGCUA",
    # --- miR-134 ---
    "hsa-miR-134-5p":   "UGUGACUGGUUGACCAGAGGGG",
    # --- miR-135 ---
    "hsa-miR-135a-5p":  "UAUGGCUUUUUAUUCCUAUGUGA",
    # --- miR-137 (brain, epigenetics) ---
    "hsa-miR-137":      "UUAUUGCUUAAGAAUACGCGUAG",
    # --- miR-138 ---
    "hsa-miR-138-5p":   "AGCUGGUGUUGUGAAUCAGGCCG",
    # --- miR-139 ---
    "hsa-miR-139-5p":   "UCUACAGUGCACGUGUCU",
    # --- miR-140 ---
    "hsa-miR-140-5p":   "CAGUGGUUUUACCCUAUGGUAG",
    # --- miR-141/200c (EMT) ---
    "hsa-miR-141-3p":   "UAACACUGUCUGGUAAAGAUGG",
    "hsa-miR-200c-3p":  "UAAUACUGCCGGGUAAUGAUGGA",
    # --- miR-142 (hematopoietic) ---
    "hsa-miR-142-3p":   "UGUAGUGUUUCCUACUUUAUGGA",
    "hsa-miR-142-5p":   "CAUAAAGUAGAAAGCACUACU",
    # --- miR-143/145 (smooth muscle, tumor suppressor) ---
    "hsa-miR-143-3p":   "UGAGAUGAAGCACUGUAGCUC",
    "hsa-miR-145-5p":   "GUCCAGUUUUCCCAGGAAUCCCU",
    # --- miR-146 (immune) ---
    "hsa-miR-146a-5p":  "UGAGAACUGAAUUCCAUGGGUU",
    "hsa-miR-146b-5p":  "UGAGAACUGAAUUCCAUAGGCU",
    # --- miR-148/152 ---
    "hsa-miR-148a-3p":  "UCAGUGCACUACAGAACUUUGU",
    "hsa-miR-148b-3p":  "UCAGUGCAUCACAGAACUUUGU",
    "hsa-miR-152-3p":   "UCAGUGCAUGACAGAACUUGG",
    # --- miR-150 (immune) ---
    "hsa-miR-150-5p":   "UCUCCCAACCCUUGUACCAGUG",
    # --- miR-155 (immune, oncomir) ---
    "hsa-miR-155-5p":   "UUAAUGCUAAUUGUGAUAGGGGU",
    # --- miR-181 family (immune, development) ---
    "hsa-miR-181a-5p":  "AACAUUCAACGCUGUCGGUGAGU",
    "hsa-miR-181b-5p":  "AACAUUCAUUGCUGUCGGUGGGU",
    "hsa-miR-181c-5p":  "AACAUUCAACCUGUCGGUGAGU",
    "hsa-miR-181d-5p":  "AACAUUCAUUGUUGUCGGUGGGU",
    # --- miR-191 ---
    "hsa-miR-191-5p":   "CAACGGAAUCCCAAAAGCAGCUG",
    # --- miR-192/215 (p53, GI tract) ---
    "hsa-miR-192-5p":   "CUGACCUAUGAAUUGACAGCC",
    "hsa-miR-215-5p":   "AUGACCUAUGAAUUGACAGAC",
    # --- miR-193 ---
    "hsa-miR-193a-3p":  "AACUGGCCUACAAAGUCCCAGU",
    "hsa-miR-193b-3p":  "AACUGGCCCUCAAAGUCCCGCU",
    # --- miR-194 ---
    "hsa-miR-194-5p":   "UGUAACAGCAACUCCAUGUGGA",
    # --- miR-195 ---
    "hsa-miR-195-5p":   "UAGCAGCACAGAAAUAUUGGC",
    # --- miR-196 ---
    "hsa-miR-196a-5p":  "UAGGUAGUUUCAUGUUGUUGGG",
    # --- miR-197 ---
    "hsa-miR-197-3p":   "UUCACCACCUUCUCCACCCAGC",
    # --- miR-199 ---
    "hsa-miR-199a-3p":  "ACAGUAGUCUGCACAUUGGUUA",
    "hsa-miR-199a-5p":  "CCCAGUGUUCAGACUACCUGUUC",
    # --- miR-200 family (EMT regulators) ---
    "hsa-miR-200a-3p":  "UAACACUGUCUGGUAACGAUGU",
    "hsa-miR-200b-3p":  "UAAUACUGCCUGGUAAUGAUGA",
    # --- miR-203 (skin, EMT) ---
    "hsa-miR-203a-3p":  "GUGAAAUGUUUAGGACCACUAG",
    # --- miR-204/211 ---
    "hsa-miR-204-5p":   "UUCCCUUUGUCAUCCUAUGCCU",
    # --- miR-205 (epithelial) ---
    "hsa-miR-205-5p":   "UCCUUCAUUCCACCGGAGUCUG",
    # --- miR-208 (cardiac) ---
    "hsa-miR-208a-3p":  "AUAAGACGAGCAAAAAGCUUGU",
    # --- miR-210 (hypoxia) ---
    "hsa-miR-210-3p":   "CUGUGCGUGUGACAGCGGCUGA",
    # --- miR-214 ---
    "hsa-miR-214-3p":   "ACAGCAGGCACAGACAGGCAGU",
    # --- miR-216/217 ---
    "hsa-miR-217":      "UACUGCAUCAGGAACUGAUUGGA",
    # --- miR-218 ---
    "hsa-miR-218-5p":   "UUGUGCUUGAUCUAACCAUGU",
    # --- miR-221/222 (cell cycle, angiogenesis) ---
    "hsa-miR-221-3p":   "AGCUACAUUGUCUGCUGGGUUUC",
    "hsa-miR-222-3p":   "AGCUACAUCUGGCUACUGGGU",
    # --- miR-223 (myeloid) ---
    "hsa-miR-223-3p":   "UGUCAGUUUGUCAAAUACCCCA",
    # --- miR-301 ---
    "hsa-miR-301a-3p":  "CAGUGCAAUAGUAUUGUCAAAGC",
    # --- miR-302 cluster (pluripotency) ---
    "hsa-miR-302a-3p":  "UAAGUGCUUCCAUGUUUUGGUGA",
    "hsa-miR-302b-3p":  "UAAGUGCUUCCAUGUUUUAGUAG",
    # --- miR-320 ---
    "hsa-miR-320a":     "AAAAGCUGGGUUGAGAGGGCGA",
    # --- miR-335 ---
    "hsa-miR-335-5p":   "UCAAGAGCAAUAACGAAAAAUGU",
    # --- miR-338 ---
    "hsa-miR-338-3p":   "UCCAGCAUCAGUGAUUUUGUUG",
    # --- miR-340 ---
    "hsa-miR-340-5p":   "UUAUAAAGCAAUGAGACUGAUU",
    # --- miR-342 ---
    "hsa-miR-342-3p":   "UCUCACACAGAAAUCGCACCCGU",
    # --- miR-345 ---
    "hsa-miR-345-5p":   "GCUGACUCCUAGUCCAGGGCUC",
    # --- miR-370 ---
    "hsa-miR-370-3p":   "GCCUGCUGGGGUGGAACCUGGU",
    # --- miR-375 (pancreatic islet) ---
    "hsa-miR-375-3p":   "UUUGUUCGUUCGGCUCGCGUGA",
    # --- miR-378 ---
    "hsa-miR-378a-3p":  "ACUGGACUUGGAGUCAGAAGGC",
    # --- miR-424/503 ---
    "hsa-miR-424-5p":   "CAGCAGCAAUUCAUGUUUUGAA",
    # --- miR-451 (erythroid) ---
    "hsa-miR-451a":     "AAACCGUUACCAUUACUGAGUU",
    # --- miR-486 ---
    "hsa-miR-486-5p":   "UCCUGUACUGAGCUGCCCCGAG",
    # --- miR-497 ---
    "hsa-miR-497-5p":   "CAGCAGCACACUGUGGUUUGU",
    # --- miR-499 (cardiac) ---
    "hsa-miR-499a-5p":  "UUAAGACUUGCAGUGAUGUUU",
    # --- miR-505 ---
    "hsa-miR-505-3p":   "CGUCAACACUUGCUGGUUUCCU",
    # --- miR-590 ---
    "hsa-miR-590-3p":   "UAAUUUUAUGUAUAAGCUAGU",
    # --- miR-660 ---
    "hsa-miR-660-5p":   "UACCCAUUGCAUAUCGGAGUUG",
    # --- miR-873 ---
    "hsa-miR-873-5p":   "GCAGGAACUUGUGAGUCUCCU",
    # --- miR-4521 ---
    "hsa-miR-4521":     "GCUAAGGAAGUCCUGUGCUCAG",
}


# Tissue-enriched miRNA subsets (top expressed per tissue from literature)
TISSUE_PANELS: dict[str, list[str]] = {
    "brain": [
        "hsa-miR-9-5p", "hsa-miR-124-3p", "hsa-miR-128-3p", "hsa-miR-132-3p",
        "hsa-miR-134-5p", "hsa-miR-137", "hsa-miR-138-5p", "hsa-miR-181a-5p",
        "hsa-miR-181b-5p", "hsa-miR-125b-5p", "hsa-miR-26a-5p",
        "hsa-let-7a-5p", "hsa-let-7b-5p", "hsa-miR-21-5p",
    ],
    "liver": [
        "hsa-miR-122-5p", "hsa-miR-192-5p", "hsa-miR-194-5p", "hsa-miR-148a-3p",
        "hsa-miR-26a-5p", "hsa-miR-30a-5p", "hsa-miR-21-5p", "hsa-let-7a-5p",
        "hsa-let-7c-5p", "hsa-miR-29a-3p",
    ],
    "heart": [
        "hsa-miR-1-3p", "hsa-miR-133a-3p", "hsa-miR-133b", "hsa-miR-208a-3p",
        "hsa-miR-499a-5p", "hsa-miR-26a-5p", "hsa-miR-30a-5p", "hsa-let-7a-5p",
        "hsa-miR-21-5p", "hsa-miR-486-5p",
    ],
    "muscle": [
        "hsa-miR-1-3p", "hsa-miR-133a-3p", "hsa-miR-133b", "hsa-miR-206",
        "hsa-miR-486-5p", "hsa-miR-378a-3p", "hsa-miR-26a-5p",
    ],
    "immune": [
        "hsa-miR-155-5p", "hsa-miR-146a-5p", "hsa-miR-146b-5p",
        "hsa-miR-150-5p", "hsa-miR-142-3p", "hsa-miR-142-5p",
        "hsa-miR-223-3p", "hsa-miR-181a-5p", "hsa-miR-21-5p",
        "hsa-miR-451a", "hsa-miR-16-5p",
    ],
    "epithelial": [
        "hsa-miR-200a-3p", "hsa-miR-200b-3p", "hsa-miR-200c-3p",
        "hsa-miR-141-3p", "hsa-miR-205-5p", "hsa-miR-203a-3p",
        "hsa-miR-34a-5p", "hsa-miR-21-5p",
    ],
    "pancreas": [
        "hsa-miR-375-3p", "hsa-miR-217", "hsa-miR-192-5p",
        "hsa-miR-148a-3p", "hsa-miR-26a-5p", "hsa-miR-21-5p",
    ],
}


# ============================================================================
# Public API
# ============================================================================

def get_mirna_panel(
    source: str | Path | None = None,
    tissue: str | None = None,
    min_rpm: float = 10.0,
    custom: dict[str, str] | None = None,
    organism: str = "hsa",
    expression_data: dict | None = None,
) -> dict[str, str]:
    """Get a miRNA seed panel for binding site analysis.

    Args:
        source: Path to a FASTA file (e.g. miRBase mature.fa). If None,
            uses the bundled panel.
        tissue: Filter to miRNAs expressed in this tissue. Uses expression
            data from the miRNA tissue atlas. When combined with ``source``,
            filters the full miRBase FASTA to tissue-expressed miRNAs.
            Available tissues: brain, heart, liver, lung, kidney, muscle,
            skin, blood, breast, colon, stomach, pancreas, prostate, ovary,
            testis, thyroid, adrenal, spleen, bone_marrow, placenta, adipose,
            esophagus, bladder, cervix, eye.
        min_rpm: Minimum expression (RPM) to consider a miRNA expressed
            in the target tissue (default 10). Only used with ``tissue``.
        custom: Custom dict of {name: sequence}. Overrides all other options.
        organism: Organism prefix for FASTA filtering (default "hsa").
        expression_data: Custom expression matrix {mirna: {tissue: rpm}}.
            If None, uses the bundled atlas.

    Returns:
        Dict of {mirna_name: mature_sequence}.
    """
    if custom is not None:
        return custom

    if source is not None:
        panel = load_mirna_fasta(source, organism=organism)
    else:
        # Try bundled mature.fa first (full miRBase), fall back to curated panel
        _bundled_fasta = Path(__file__).parent / "data" / "mature.fa"
        if _bundled_fasta.exists():
            panel = load_mirna_fasta(_bundled_fasta, organism=organism)
        else:
            panel = dict(BUNDLED_MIRNAS)

    if tissue is not None:
        from .expression import filter_by_expression
        panel = filter_by_expression(
            panel, tissue=tissue, min_rpm=min_rpm,
            expression_data=expression_data,
        )
        # If expression filtering removed everything (no data for that tissue),
        # fall back to the hardcoded tissue panels as a safety net
        if not panel and tissue.lower() in TISSUE_PANELS:
            keep = set(TISSUE_PANELS[tissue.lower()])
            panel = {k: v for k, v in BUNDLED_MIRNAS.items() if k in keep}

    return panel


def load_mirna_fasta(path: str | Path, organism: str = "hsa") -> dict[str, str]:
    """Load miRNA sequences from a FASTA file (miRBase format).

    Filters to the specified organism prefix (e.g. "hsa" for human).

    Args:
        path: Path to FASTA file (e.g. mature.fa from miRBase).
        organism: Organism prefix to filter (default "hsa").

    Returns:
        Dict of {mirna_name: sequence}.
    """
    path = Path(path)
    if not path.exists():
        raise FileNotFoundError(f"miRNA FASTA not found: {path}")

    panel: dict[str, str] = {}
    current_name = None

    with open(path) as f:
        for line in f:
            line = line.strip()
            if line.startswith(">"):
                # Parse FASTA header: >hsa-miR-21-5p MIMAT0000076 ...
                parts = line[1:].split()
                name = parts[0]
                if name.startswith(f"{organism}-"):
                    current_name = name
                else:
                    current_name = None
            elif current_name is not None and line:
                panel[current_name] = line.upper().replace("T", "U")

    return panel


def list_tissues() -> list[str]:
    """Return available tissue panel names."""
    return sorted(TISSUE_PANELS.keys())
