# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Licensed under the MIT License

"""
Training Corpus Domain Taxonomy

Controlled vocabulary for co-op LLM training data classification.

Philosophy
----------
Mirrors the organizational intent of the Dewey Decimal System — every topic has
one canonical home in a two-level hierarchy (domain.subdomain) — but uses semantic
string keys rather than numeric codes so that the taxonomy is human-readable,
LLM-benchmark-aligned, and extensible to task-specific categories (reasoning,
code, tool_use) that libraries never needed to classify.

DDC crosswalk numbers are stored as metadata on each domain for academic reference
and interoperability, but are never used as primary keys.

Structure
---------
  domain          — 10 top-level classes  (string key, e.g. "stem")
    subdomain     — 3-8 per domain        (dotted key, e.g. "stem.math")
      topic       — unlimited, free text  (e.g. "integration by parts")

Instruction Types
-----------------
15 canonical types covering the full space of instruction-tuning tasks.
A single training document can produce multiple pairs with different types.
This is how you get instruction diversity without multiplying content.
"""

from __future__ import annotations

from typing import Optional

# ── Domain taxonomy ──────────────────────────────────────────────────────────

DOMAIN_TAXONOMY: dict[str, dict] = {
    "stem": {
        "label": "Science, Technology, Engineering & Math",
        "ddc": "500–699",
        "description": "Formal sciences, natural sciences, and applied engineering.",
        "subdomains": {
            "math": "Mathematics — algebra, calculus, statistics, proofs",
            "physics": "Physics — mechanics, electromagnetism, quantum",
            "chemistry": "Chemistry — organic, inorganic, biochemistry",
            "biology": "Biology — genetics, ecology, cell biology",
            "earth_science": "Earth science, geology, climate, astronomy",
            "engineering": "Engineering disciplines — civil, electrical, mechanical",
            "data_science": "Statistics, data analysis, machine learning theory",
        },
    },
    "code": {
        "label": "Programming & Software Engineering",
        "ddc": "005",
        "description": "Practical programming, algorithms, and software craft.",
        "subdomains": {
            "algorithms": "Algorithms, data structures, complexity",
            "python": "Python language and ecosystem",
            "javascript": "JavaScript, TypeScript, Node, browser APIs",
            "systems": "Systems programming, C/C++/Rust, OS concepts",
            "web": "Web development — HTML, CSS, HTTP, APIs",
            "databases": "SQL, NoSQL, query optimization, schema design",
            "devops": "CI/CD, containers, infrastructure, shell scripting",
            "debugging": "Debugging, testing, code review, refactoring",
        },
    },
    "reasoning": {
        "label": "Reasoning & Problem Solving",
        "ddc": "160",
        "description": "Cognitive tasks that train the model to think, not just recall.",
        "subdomains": {
            "logic": "Formal logic, argument structure, fallacies",
            "planning": "Multi-step planning, goal decomposition, strategy",
            "math_word": "Mathematical word problems, applied arithmetic",
            "causal": "Cause-and-effect, counterfactuals, hypotheticals",
            "ethical": "Ethical dilemmas, moral reasoning, applied ethics",
        },
    },
    "humanities": {
        "label": "Humanities",
        "ddc": "100–499, 800–999",
        "description": "History, philosophy, literature, arts, and language.",
        "subdomains": {
            "history": "World and regional history, historiography",
            "philosophy": "Epistemology, metaphysics, political philosophy",
            "literature": "Literary analysis, genre, narrative craft",
            "linguistics": "Grammar, syntax, phonology, language change",
            "art_history": "Art movements, artists, criticism, visual culture",
            "religion": "World religions, theology, mythology, comparative study",
        },
    },
    "social_sciences": {
        "label": "Social Sciences",
        "ddc": "300",
        "description": "Human behavior, institutions, and society.",
        "subdomains": {
            "economics": "Micro/macroeconomics, trade, development",
            "psychology": "Cognitive, clinical, developmental, social psychology",
            "sociology": "Social structures, inequality, culture, institutions",
            "political_science": "Government, policy, international relations",
            "education": "Pedagogy, curriculum, learning science",
            "media": "Journalism, communication theory, digital media",
        },
    },
    "professional": {
        "label": "Professional Practice",
        "ddc": "340–660",
        "description": "Domain knowledge for specific professional roles.",
        "subdomains": {
            "legal": "Law, contracts, compliance, litigation",
            "medical": "Clinical medicine, pharmacology, diagnosis",
            "finance": "Accounting, investment, corporate finance, tax",
            "business": "Strategy, operations, marketing, management",
            "nonprofit": "Grant writing, donor relations, program management",
            "healthcare_admin": "Healthcare systems, billing, regulation",
        },
    },
    "practical": {
        "label": "Practical Skills & Daily Life",
        "ddc": "640–699",
        "description": "Applied knowledge for everyday tasks and personal domains.",
        "subdomains": {
            "cooking": "Recipes, technique, nutrition, food science",
            "health_wellness": "Fitness, mental health, preventive care",
            "home": "Home repair, gardening, organization",
            "personal_finance": "Budgeting, saving, debt, insurance",
            "travel": "Trip planning, geography, cultural norms",
            "crafts": "Making, DIY, textiles, woodworking",
            "system_administration": "Software installation, system setup, configuration, package management",
        },
    },
    "creative": {
        "label": "Creative Arts",
        "ddc": "700–799",
        "description": "Art-making, creative writing, performance, and design.",
        "subdomains": {
            "visual_art": "Drawing, painting, sculpture, graphic design",
            "music": "Theory, composition, performance, production",
            "writing": "Creative writing, fiction, poetry, screenwriting",
            "film": "Cinematography, editing, directing, photography",
            "performance": "Theater, dance, improvisation, public speaking",
        },
    },
    "language": {
        "label": "Language & Translation",
        "ddc": "400",
        "description": "Language learning, translation, and writing craft.",
        "subdomains": {
            "grammar": "Grammar rules, syntax, punctuation",
            "translation": "Translation technique, localization",
            "writing_style": "Style, rhetoric, clarity, tone",
            "second_language": "Language acquisition, ESL, foreign language",
        },
    },
    "general": {
        "label": "General / Reference",
        "ddc": "000",
        "description": "Cross-domain reference, factual Q&A, and uncategorized content.",
        "subdomains": {
            "reference": "Factual lookup, definitions, encyclopedic",
            "instructions": "General how-to not fitting another domain",
            "qa": "Open-ended Q&A, trivia, general knowledge",
        },
    },
}

# ── Instruction type taxonomy ────────────────────────────────────────────────

INSTRUCTION_TYPES: dict[str, str] = {
    "how_to": "Step-by-step procedure to accomplish a goal",
    "explain": "Conceptual explanation of an idea, term, or process",
    "compare": "Compare or contrast two or more things",
    "troubleshoot": "Diagnose a problem and recommend fixes",
    "summarize": "Condense longer material into key points",
    "classify": "Categorize, label, or sort items",
    "critique": "Evaluate and provide structured feedback",
    "generate": "Create original content (text, code, plan, etc.)",
    "translate": "Convert between languages or between formats",
    "math": "Mathematical computation, derivation, or proof",
    "code": "Write, explain, review, or debug code",
    "qa": "Direct factual question with a precise answer",
    "roleplay": "Scenario or persona-based interaction",
    "plan": "Create a structured plan, outline, or strategy",
    "extract": "Extract specific information from provided text",
}

# ── Controlled enums ─────────────────────────────────────────────────────────

DIFFICULTY_LEVELS = ("beginner", "intermediate", "expert")
AUDIENCE_TYPES = ("general", "professional", "specialist", "student")
PAIR_TYPES = ("document", "instruction", "preference")

# ── Validation ───────────────────────────────────────────────────────────────


def validate_domain(domain: str, subdomain: str = "") -> tuple[bool, str]:
    """
    Validate a domain/subdomain pair against the taxonomy.

    Returns (valid: bool, message: str).
    """
    if domain not in DOMAIN_TAXONOMY:
        known = ", ".join(sorted(DOMAIN_TAXONOMY))
        return False, f"Unknown domain '{domain}'. Known: {known}"

    if subdomain:
        subs = DOMAIN_TAXONOMY[domain]["subdomains"]
        if subdomain not in subs:
            known = ", ".join(sorted(subs))
            return False, f"Unknown subdomain '{domain}.{subdomain}'. Known: {known}"

    return True, "ok"


def validate_instruction_type(itype: str) -> bool:
    return itype in INSTRUCTION_TYPES


def resolve_path_from_domain(base_dir, domain: str, subdomain: str = "") -> "Path":
    """Return the canonical training directory path for a domain/subdomain."""
    from pathlib import Path

    path = Path(base_dir) / "training" / domain
    if subdomain:
        path = path / subdomain
    return path


def list_taxonomy() -> str:
    """Return a formatted taxonomy listing for display to the user."""
    lines = ["Co-op Training Corpus Taxonomy\n"]
    for domain, info in DOMAIN_TAXONOMY.items():
        lines.append(f"  {domain}  —  {info['label']}  (DDC {info['ddc']})")
        for sub, desc in info["subdomains"].items():
            lines.append(f"    .{sub}  —  {desc}")
        lines.append("")
    lines.append("Instruction types:")
    for itype, desc in INSTRUCTION_TYPES.items():
        lines.append(f"  {itype}  —  {desc}")
    return "\n".join(lines)


def suggest_domain(topic: str) -> Optional[str]:
    """
    Heuristic domain suggestion from a topic string.

    Checks for keyword overlap between topic words and subdomain descriptions.
    Returns 'domain.subdomain' or None if no strong match.
    """
    topic_words = set(topic.lower().split())
    best_score = 0
    best_key: Optional[str] = None

    for domain, info in DOMAIN_TAXONOMY.items():
        for sub, desc in info["subdomains"].items():
            desc_words = set(desc.lower().replace(",", " ").split())
            overlap = len(topic_words & desc_words)
            if overlap > best_score:
                best_score = overlap
                best_key = f"{domain}.{sub}"

    return best_key if best_score >= 1 else None
