"""
Example: Historical Writing Systems Domain

Demonstrates how to implement a complete BRS domain for tracking
the evolution and relationships between writing systems.
"""
from __future__ import annotations

import datetime
from pathlib import Path
from typing import List, Tuple

from ..core import Node, Edge, Evidence, Pattern, WorldBundle, TimeRange
from ..storage import CASStore
from ..inference import best_path_to_any_root
from ..domains.registry import register, SmokeTestResult


# =============================================================================
# Domain Constants
# =============================================================================

DOMAIN_ID = "writing"

# Root writing systems (proto-scripts)
WRITING_ROOTS = [
    "PROTO_SINAITIC",
    "PROTO_CUNEIFORM",
    "CHINESE_ORACLE",
    "MAYAN_PROTO",
    "INDUS_SCRIPT",
]

# Expected ancestry relationships
EXPECTED_ANCESTRIES = {
    "ARABIC": "PROTO_SINAITIC",
    "HEBREW": "PROTO_SINAITIC",
    "GREEK": "PROTO_SINAITIC",
    "LATIN": "PROTO_SINAITIC",
    "DEVANAGARI": "PROTO_SINAITIC",
    "THAI": "PROTO_SINAITIC",
    "HANGUL": None,  # Independent invention
    "JAPANESE_KANA": "CHINESE_ORACLE",
}


# =============================================================================
# Seed Data Functions
# =============================================================================

def create_writing_nodes() -> List[Node]:
    """Create sample writing system nodes."""
    return [
        Node(
            id="PROTO_SINAITIC",
            name="Proto-Sinaitic",
            node_type="proto_alphabet",
            properties={"script_type": "abjad", "direction": "RTL"},
            first_attested=TimeRange(-1800, -1500),
            regions=("Sinai", "Levant"),
        ),
        Node(
            id="PHOENICIAN",
            name="Phoenician",
            node_type="alphabet",
            properties={"script_type": "abjad", "direction": "RTL"},
            first_attested=TimeRange(-1050, -1000),
            regions=("Levant", "Mediterranean"),
        ),
        Node(
            id="ARAMAIC",
            name="Aramaic",
            node_type="alphabet",
            properties={"script_type": "abjad", "direction": "RTL"},
            first_attested=TimeRange(-900, -800),
            regions=("Mesopotamia", "Levant"),
        ),
        Node(
            id="ARABIC",
            name="Arabic",
            node_type="alphabet",
            properties={"script_type": "abjad", "direction": "RTL"},
            first_attested=TimeRange(400, 600),
            regions=("Arabia", "Middle East"),
        ),
        Node(
            id="HEBREW",
            name="Hebrew",
            node_type="alphabet",
            properties={"script_type": "abjad", "direction": "RTL"},
            first_attested=TimeRange(-1000, -900),
            regions=("Levant",),
        ),
        Node(
            id="GREEK",
            name="Greek",
            node_type="alphabet",
            properties={"script_type": "alphabet", "direction": "LTR"},
            first_attested=TimeRange(-800, -700),
            regions=("Greece", "Mediterranean"),
        ),
        Node(
            id="LATIN",
            name="Latin",
            node_type="alphabet",
            properties={"script_type": "alphabet", "direction": "LTR"},
            first_attested=TimeRange(-700, -600),
            regions=("Italy", "Roman Empire"),
        ),
        Node(
            id="BRAHMI",
            name="Brahmi",
            node_type="abugida",
            properties={"script_type": "abugida", "direction": "LTR"},
            first_attested=TimeRange(-300, -200),
            regions=("India",),
        ),
        Node(
            id="DEVANAGARI",
            name="Devanagari",
            node_type="abugida",
            properties={"script_type": "abugida", "direction": "LTR"},
            first_attested=TimeRange(700, 900),
            regions=("India", "Nepal"),
        ),
        Node(
            id="THAI",
            name="Thai",
            node_type="abugida",
            properties={"script_type": "abugida", "direction": "LTR"},
            first_attested=TimeRange(1200, 1300),
            regions=("Thailand",),
        ),
        Node(
            id="CHINESE_ORACLE",
            name="Oracle Bone Script",
            node_type="logography",
            properties={"script_type": "logography", "direction": "TTB"},
            first_attested=TimeRange(-1200, -1000),
            regions=("China",),
        ),
        Node(
            id="JAPANESE_KANA",
            name="Japanese Kana",
            node_type="syllabary",
            properties={"script_type": "syllabary", "direction": "LTR"},
            first_attested=TimeRange(800, 900),
            regions=("Japan",),
        ),
        Node(
            id="HANGUL",
            name="Hangul",
            node_type="featural",
            properties={"script_type": "featural", "direction": "LTR"},
            first_attested=TimeRange(1443, 1446),
            regions=("Korea",),
            notes="Designed by King Sejong, independent invention",
        ),
    ]


def create_writing_edges() -> List[Edge]:
    """Create sample derivation edges."""
    return [
        Edge(id="E_PS_PH", parent_id="PROTO_SINAITIC", child_id="PHOENICIAN",
             relation="direct_descent", tier=0, confidence=0.9),
        Edge(id="E_PH_AR", parent_id="PHOENICIAN", child_id="ARAMAIC",
             relation="direct_descent", tier=0, confidence=0.95),
        Edge(id="E_AR_ARB", parent_id="ARAMAIC", child_id="ARABIC",
             relation="derived_via", tier=1, confidence=0.85),
        Edge(id="E_PH_HEB", parent_id="PHOENICIAN", child_id="HEBREW",
             relation="direct_descent", tier=0, confidence=0.9),
        Edge(id="E_PH_GR", parent_id="PHOENICIAN", child_id="GREEK",
             relation="direct_descent", tier=0, confidence=0.95),
        Edge(id="E_GR_LAT", parent_id="GREEK", child_id="LATIN",
             relation="direct_descent", tier=0, confidence=0.95),
        Edge(id="E_AR_BR", parent_id="ARAMAIC", child_id="BRAHMI",
             relation="influence", tier=2, confidence=0.7),
        Edge(id="E_BR_DEV", parent_id="BRAHMI", child_id="DEVANAGARI",
             relation="direct_descent", tier=0, confidence=0.9),
        Edge(id="E_BR_TH", parent_id="BRAHMI", child_id="THAI",
             relation="derived_via", tier=1, confidence=0.85),
        Edge(id="E_CH_JP", parent_id="CHINESE_ORACLE", child_id="JAPANESE_KANA",
             relation="derived_via", tier=1, confidence=0.9),
    ]


def create_writing_patterns() -> List[Pattern]:
    """Create sample patterns (invariants and operators)."""
    return [
        Pattern(
            id="PAT_CONSONANT_CORE",
            name="Consonant-Core Principle",
            summary="Writing systems derived from Semitic scripts retain consonantal skeleton",
            invariants=(
                "Root morphemes encoded as consonant sequences",
                "Vowels optional or marked diacritically",
            ),
            operators=("consonant_extraction", "vowel_omission"),
        ),
        Pattern(
            id="PAT_DIRECTION_INHERITANCE",
            name="Direction Inheritance",
            summary="Writing direction tends to be preserved across derivation",
            invariants=(
                "RTL ancestors produce RTL descendants by default",
                "Direction flip requires significant cultural pressure",
            ),
            operators=("direction_preservation", "direction_flip"),
        ),
        Pattern(
            id="PAT_SIMPLIFICATION",
            name="Graphemic Simplification",
            summary="Scripts tend toward reduced stroke counts over time",
            invariants=(
                "Average strokes per character decrease in descendants",
                "Ligatures emerge to reduce writing effort",
            ),
            operators=("stroke_reduction", "ligature_formation"),
        ),
    ]


def seed_writing_domain(store: CASStore, world_label: str = "green") -> str:
    """
    Seed the writing domain with sample data.

    Args:
        store: Storage backend
        world_label: Version label for the world

    Returns:
        Hash of the created world
    """
    node_ids = []
    edge_ids = []
    pattern_ids = []

    # Store nodes
    for node in create_writing_nodes():
        h = store.put_object("Node", node)
        store.upsert_node(node.id, node.name, h)
        node_ids.append(node.id)

    # Store edges
    for edge in create_writing_edges():
        h = store.put_object("Edge", edge)
        store.upsert_edge(
            edge.id, edge.parent_id, edge.child_id,
            edge.relation, edge.tier, edge.confidence, h
        )
        edge_ids.append(edge.id)

    # Store patterns
    for pattern in create_writing_patterns():
        h = store.put_object("Pattern", pattern)
        pattern_ids.append(pattern.id)

    # Create world bundle
    world = WorldBundle(
        domain_id=DOMAIN_ID,
        version_label=world_label,
        node_ids=tuple(node_ids),
        edge_ids=tuple(edge_ids),
        evidence_ids=(),
        pattern_ids=tuple(pattern_ids),
        created_utc=datetime.datetime.utcnow().isoformat() + "Z",
        notes="Writing systems domain - seeded",
    )

    return store.put_world(world)


# =============================================================================
# Smoke Tests
# =============================================================================

def run_smoke(store: CASStore, domain_id: str, world_label: str) -> SmokeTestResult:
    """
    Writing domain smoke tests.

    Verifies:
    1. Key ancestry paths exist
    2. Independent scripts don't have false connections
    """
    msgs: List[str] = []
    tests = 0
    fails = 0

    # Test ancestry paths
    for script, expected_root in EXPECTED_ANCESTRIES.items():
        tests += 1
        try:
            result = best_path_to_any_root(store, script, WRITING_ROOTS)
            if expected_root is None:
                # Should NOT find a path
                if result is not None:
                    fails += 1
                    msgs.append(f"FAIL: {script} should be independent but found path to {result.root}")
                else:
                    msgs.append(f"OK: {script} is independent (no path to roots)")
            else:
                # Should find a path
                if result is None:
                    fails += 1
                    msgs.append(f"FAIL: {script} should connect to {expected_root} but no path found")
                else:
                    msgs.append(f"OK: {script} -> {result.root}")
        except Exception as e:
            # Node might not exist - that's okay for smoke tests
            msgs.append(f"SKIP: {script} not found in store")

    return (tests, fails, msgs)


def run_regression(store: CASStore, domain_id: str, world_label: str) -> SmokeTestResult:
    """Extended regression tests for writing domain."""
    # Start with smoke tests
    tests, fails, msgs = run_smoke(store, domain_id, world_label)

    # Add additional checks
    tests += 1
    try:
        world = store.get_world(domain_id, world_label)["json"]
        if len(world.get("pattern_ids", [])) < 2:
            fails += 1
            msgs.append("FAIL: World should have at least 2 patterns")
        else:
            msgs.append("OK: World has sufficient patterns")
    except Exception as e:
        fails += 1
        msgs.append(f"FAIL: Could not load world: {e}")

    return (tests, fails, msgs)


# Register smoke tests
SMOKE_LEVELS = {
    "smoke": run_smoke,
    "regression": run_regression,
    "deep": run_regression,  # Placeholder for more expensive tests
}


# =============================================================================
# Usage Example
# =============================================================================

def example_usage():
    """Demonstrate domain usage."""
    from pathlib import Path
    import tempfile

    # Create temporary storage
    with tempfile.TemporaryDirectory() as tmpdir:
        store = CASStore(Path(tmpdir))

        # Seed the domain
        world_hash = seed_writing_domain(store)
        print(f"Created writing world: {world_hash[:12]}...")

        # Run smoke tests
        tests, fails, msgs = run_smoke(store, DOMAIN_ID, "green")
        print(f"\nSmoke tests: {tests} run, {fails} failed")
        for msg in msgs:
            print(f"  {msg}")

        # Query ancestry
        result = best_path_to_any_root(store, "THAI", WRITING_ROOTS)
        if result:
            print(f"\nThai ancestry:")
            print(result.explanation)

        store.close()


if __name__ == "__main__":
    example_usage()
