#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""
Consolidation Daemon: Cross-session pattern mining + schema promotion.

Main orchestration loop. Stages are in consolidation_stages.py (Law 7 split).

Six stages:
  1. Dedup: Run existing pulse_dedup logic (text similarity merging)
  2. Pattern Mining: Find recurring sequences across past 7 days
  3. Schema Promotion: Promote high-confidence patterns to schemas.json
  4. Graph Update: Rebuild knowledge graph from current brain state
  5. Metacognitive Audit: Flag vague/unused/contradicted items
  6. Hierarchical Prune: Miller's Law 4±1 enforcement (Q8 Neural Hardening)

Runs every 6 hours via orchestrator.

Dependencies: Python stdlib + brain_utils (internal)
"""
import io
import os
import sys
import time
from datetime import datetime, timezone
from pathlib import Path

if os.name == 'nt' and __name__ == '__main__':
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')

SCRIPT_DIR = Path(__file__).resolve().parent
ROOT_DIR = SCRIPT_DIR.parent.parent.parent

# When run directly, ensure pulse package is importable
if str(ROOT_DIR) not in sys.path:
    sys.path.insert(0, str(ROOT_DIR))

from pulse.core.brain_utils import HIPPOCAMPUS_DIR, save_json, now_iso as _now_iso
from pulse.daemons.consolidation.consolidation_stages import (
    stage_dedup,
    stage_pattern_mining,
    stage_schema_promotion,
    stage_schema_promotion_from_sequences,
    register_discovered_procedures,
    stage_ltd_decay,
    stage_graph_update,
    stage_reconsolidation,
    stage_cross_domain_transfer,
    stage_metacognitive_audit,
    stage_hierarchical_prune,
)

CONSOLIDATION_LOG = HIPPOCAMPUS_DIR / "Evidence" / "Metrics" / "consolidation_log.json"


# === MAIN CONSOLIDATION ===

def run_consolidation(verbose=False):
    """Run full 4-stage consolidation pipeline.

    Orchestrates all consolidation stages from consolidation_stages.py.
    Logs results to consolidation_log.json.
    """
    print("[CONSOLIDATION] Starting 4-stage consolidation...")
    start = time.time()

    # Stage 1: Dedup
    print("[CONSOLIDATION] Stage 1: Deduplication")
    dedup_result = stage_dedup(verbose=verbose)

    # Stage 2: Pattern Mining
    print("[CONSOLIDATION] Stage 2: Pattern Mining")
    mining_result = stage_pattern_mining(verbose=verbose)

    # Stage 2b: Register discovered procedures (Fix 4)
    sequences = mining_result.get("sequences", [])
    print("[CONSOLIDATION] Stage 2b: Register Discovered Procedures")
    proc_count = register_discovered_procedures(sequences, verbose=verbose)

    # Verify procedure persistence
    proc_log = HIPPOCAMPUS_DIR / "Evidence" / "Metrics" / "procedural_log.json"
    if proc_log.exists():
        from pulse.core.brain_utils import load_json
        proc_data = load_json(proc_log)
        actual_count = len(proc_data) if isinstance(proc_data, list) else 0
        if verbose:
            print(f"  [PROCEDURES] Verified: {actual_count} procedures on disk")
    elif proc_count > 0:
        print(f"  [PROCEDURES] WARNING: registered {proc_count} but procedural_log.json missing!")

    # Stage 2c: LTD Decay (flag unretrieved old items)
    print("[CONSOLIDATION] Stage 2c: LTD Decay")
    ltd_result = stage_ltd_decay(verbose=verbose)

    # Stage 2d: Auto-reconsolidation (U6: merge similar entries)
    print("[CONSOLIDATION] Stage 2d: Reconsolidation")
    recon_result = stage_reconsolidation(verbose=verbose)

    # Stage 2e: Cross-Domain Transfer Detection
    print("[CONSOLIDATION] Stage 2e: Cross-Domain Transfer")
    transfer_result = stage_cross_domain_transfer(verbose=verbose)

    # Stage 3: Schema Promotion (cross-patterns)
    print("[CONSOLIDATION] Stage 3: Schema Promotion")
    cross_patterns = mining_result.get("cross_patterns", [])
    schema_result = stage_schema_promotion(cross_patterns, verbose=verbose)

    # Stage 3b: Sequence -> Schema Promotion (Fix 2)
    print("[CONSOLIDATION] Stage 3b: Sequence Schema Promotion")
    seq_schema_result = stage_schema_promotion_from_sequences(sequences, verbose=verbose)

    # Stage 4: Knowledge Graph Update (Phase 7)
    print("[CONSOLIDATION] Stage 4: Knowledge Graph Update")
    graph_result = stage_graph_update(verbose=verbose)

    # Stage 5: Metacognitive Audit (U9: brain quality check)
    print("[CONSOLIDATION] Stage 5: Metacognitive Audit")
    meta_result = stage_metacognitive_audit(verbose=verbose)

    # Stage 6: Hierarchical Prune (Miller's Law — Q8 Neural Hardening)
    print("[CONSOLIDATION] Stage 6: Hierarchical Prune")
    prune_result = stage_hierarchical_prune(verbose=verbose)

    # Stage 6b: Rebuild search index (hybrid fast-path for brain_search)
    print("[CONSOLIDATION] Stage 6b: Rebuild Search Index")
    try:
        from pulse.brain.search_index import build_index
        index_result = build_index(verbose=verbose)
    except Exception as e:
        index_result = {"status": "error", "error": str(e)}

    elapsed = round(time.time() - start, 2)

    # Write consolidation log
    log = {
        "timestamp": _now_iso(),
        "elapsed_seconds": elapsed,
        "stage_1_dedup": dedup_result,
        "stage_2_mining": {
            "sequences_found": len(sequences),
            "cross_patterns_found": len(cross_patterns),
        },
        "stage_2b_procedures": {"registered": proc_count},
        "stage_2c_ltd_decay": ltd_result,
        "stage_2d_reconsolidation": recon_result,
        "stage_2e_transfer": transfer_result,
        "stage_3_schemas": schema_result,
        "stage_3b_sequence_schemas": seq_schema_result,
        "stage_4_graph": graph_result,
        "stage_5_metacognition": meta_result,
        "stage_6_hierarchical_prune": prune_result,
        "stage_6b_search_index": index_result,
    }

    CONSOLIDATION_LOG.parent.mkdir(parents=True, exist_ok=True)
    save_json(CONSOLIDATION_LOG, log)

    print(f"\n[CONSOLIDATION] Complete in {elapsed}s")
    print(f"  Dedup merged: {dedup_result.get('merged', 0)}")
    print(f"  Patterns found: {mining_result.get('total_found', 0)}")
    print(f"  Schemas: {schema_result.get('new_schemas', 0)} new, "
          f"{schema_result.get('total_schemas', 0)} total")

    return log


if __name__ == "__main__":
    v = "--verbose" in sys.argv or "-v" in sys.argv
    run_consolidation(verbose=v)
