"""Machine-readable input-format specification and downloadable templates."""
from __future__ import annotations

FORMAT_SPEC = {
    "files": [
        {
            "key": "proteins", "title": "Proteins", "required": True,
            "formats": ["FASTA (.fa, .fasta, .faa)", "TSV / CSV / semicolon / whitespace table"],
            "summary": "One row per protein: an identifier and its amino-acid sequence.",
            "columns": [
                {"name": "protein_id", "required": True, "type": "text",
                 "rules": ["Unique within the file", "Must match the identifiers used in the pair file exactly"]},
                {"name": "sequence", "required": True, "type": "amino-acid letters",
                 "rules": ["One-letter codes; case is ignored", "Non-standard residues (X, U, B, Z) are reported, then removed before descriptor computation",
                           "Sequences longer than 1,022 residues are counted (ESM-2 context limit)"]},
                {"name": "species", "required": False, "type": "text",
                 "rules": ["Optional; enables species diagnostics", "Alternatively upload a separate species file or put OS=<organism> in FASTA headers"]},
            ],
            "example": "protein_id\tsequence\nP53049\tMSTQKLSEGAAVLEDR…\nQ08949\tMADLNKKREWQ…",
            "templates": ["proteins.tsv", "proteins.fasta"],
        },
        {
            "key": "pairs", "title": "Pairs", "required": True,
            "formats": ["TSV / CSV / semicolon / whitespace table"],
            "summary": "One row per protein pair, with an optional label.",
            "columns": [
                {"name": "protein_a", "required": True, "type": "identifier", "rules": ["Pairs are undirected; order does not matter"]},
                {"name": "protein_b", "required": True, "type": "identifier", "rules": ["Self-pairs (A–A) are removed and reported"]},
                {"name": "label", "required": False, "type": "1 / 0",
                 "rules": ["1 = observed interaction, 0 = supplied (constructed) negative",
                           "Also accepted: true/false, yes/no, positive/negative, 1.0/0.0",
                           "Without a label column every pair is a positive and the framework builds all negatives"]},
            ],
            "example": "protein_a\tprotein_b\tlabel\nP53049\tP09435\t1\nP38089\tQ08949\t1\nP40484\tQ04792\t0",
            "templates": ["pairs.tsv", "pairs_positive_only.tsv"],
        },
        {
            "key": "species", "title": "Species map", "required": False,
            "formats": ["TSV / CSV table"],
            "summary": "Organism of each protein, for multi-species datasets.",
            "columns": [
                {"name": "protein_id", "required": True, "type": "identifier", "rules": []},
                {"name": "species", "required": True, "type": "text",
                 "rules": ["Any consistent label (e.g. ecoli, 'Homo sapiens', 9606)", "Blank, 'unknown' or 'unresolved' are excluded from species analyses"]},
            ],
            "example": "protein_id\tspecies\nP37647\tecoli\nQ9XW40\tcelegans",
            "templates": ["species.tsv"],
        },
        {
            "key": "clusters", "title": "Sequence clusters", "required": False,
            "formats": ["TSV with header protein_id, cluster_id", "headerless MMseqs2 easy-cluster output (representative, member)"],
            "summary": "Adds a cluster-disjoint split (R3-C) in which no sequence cluster spans train and test.",
            "columns": [{"name": "protein_id", "required": True, "type": "identifier", "rules": []},
                        {"name": "cluster_id", "required": True, "type": "text", "rules": []}],
            "example": "protein_id\tcluster_id\nP53049\tC1\nQ08949\tC1",
            "templates": ["clusters.tsv"],
        },
        {
            "key": "embeddings", "title": "Protein embeddings", "required": False,
            "formats": [".csv / .tsv (protein_id then numeric columns)", ".npz (arrays ids, X)", ".h5 (datasets protein_id, mean)"],
            "summary": "A pre-computed per-protein representation (e.g. ESM-2) evaluated alongside AAC+CTD. The server does not compute embeddings.",
            "columns": [{"name": "protein_id", "required": True, "type": "identifier", "rules": ["Every protein must have a vector"]},
                        {"name": "dim_1 … dim_d", "required": True, "type": "number", "rules": []}],
            "example": "protein_id,d0,d1,d2\nP53049,0.12,-0.40,0.08",
            "templates": ["embeddings.csv"],
        },
    ],
    "limits": {},
}

_P = [("P00001", "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEKAVQVKVKALPDAQFEVVHSLAKWKRQTLGQHDFSAGEGLYTHMKALRPDEDRLSPLHSVYVDQWDWERVMGDGERQFSTLKSTVEAIWAGIKATEAAVSEEFGLAPFLPDQIHFVHSQELLSRYPDLDAKGRERAIAKDLGAVFLVGIGGKLSDGHRHDVRAPDYDDWAIGLNVTALEHHHHHH"),
      ("P00002", "MSLLTEVETPIRNEWGCRCNDSSDPLVVAASIIGILHLILWILDRLFFKCIYRFFEHGLKRGPSTEGVPESMREEYRKEQQSAVDADDSHFVSIELE"),
      ("P00003", "MAHHHHHHVGTGSNDDDDKSPDLGTDDDDKAMADIGSENLYFQGMSKGEELFTGVVPILVELDGDVNGHKFSVSGEGEGDATYGKLTLKFICTTGKLPVPWPTLVTTLTYGVQCFSRYPDHMKQHDFFKSAMPEGYVQERTIFFKDDGNYKTRAEVKFEGDTLVNRIELKGIDFKEDGNILGHKLEYNYNSHNVYIMADKQKNGIKVNFKIRHNIEDGSVQLADHYQQNTPIGDGPVLLPDNHYLSTQSALSKDPNEKRDHMVLLEFVTAAGITHGMDELYK"),
      ("P00004", "MGSSHHHHHHSSGLVPRGSHMASMTGGQQMGRGSEFELRRQACGRTRAPPPPPLRSGC"),
      ("P00005", "MDSKGSSQKGSRLLLLLVVSNLLLCQGVVSTPVCPNGPGNCQVSLRDLFDRAVMVSHYIHDLSSEMFNEFDKRYAQGKGFITMALNSCHTSSLPTPEDKEQAQQTHHEVLMSLILGLLRSWNDPLYHLVTEVRGMKGAPDAILSRAIEIEEENKRLLEGMEMIFGQVIPGAKETEPYPVWSGLPSLQTKDEDARYSAFYNLLHCLRRDSSKIDTYLKLLNCRIIYNNNC")]


def template(name: str) -> tuple[str, str] | None:
    """-> (content, media type)."""
    tsv = "text/tab-separated-values"
    if name == "proteins.tsv":
        return "protein_id\tsequence\n" + "".join(f"{i}\t{s}\n" for i, s in _P), tsv
    if name == "proteins.fasta":
        return "".join(f">{i} OS=Example organism\n{s}\n" for i, s in _P), "text/plain"
    if name == "pairs.tsv":
        return "protein_a\tprotein_b\tlabel\nP00001\tP00002\t1\nP00002\tP00003\t1\nP00003\tP00005\t1\nP00001\tP00004\t0\nP00004\tP00005\t0\n", tsv
    if name == "pairs_positive_only.tsv":
        return "protein_a\tprotein_b\nP00001\tP00002\nP00002\tP00003\nP00003\tP00005\n", tsv
    if name == "species.tsv":
        return "protein_id\tspecies\nP00001\torganism_a\nP00002\torganism_a\nP00003\torganism_a\nP00004\torganism_b\nP00005\torganism_b\n", tsv
    if name == "clusters.tsv":
        return "protein_id\tcluster_id\nP00001\tC1\nP00002\tC2\nP00003\tC1\nP00004\tC3\nP00005\tC4\n", tsv
    if name == "embeddings.csv":
        rows = "".join(f"{i},{0.1 * k:.2f},{-0.05 * k:.2f},{0.02 * k:.2f}\n" for k, (i, _) in enumerate(_P, 1))
        return "protein_id,d0,d1,d2\n" + rows, "text/csv"
    return None
