#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""Consolidation Late Stages Runner: stages 6c, 11-21 + log assembly.

Extracted from consolidation_daemon.py. Called by run_all_stages().
"""
import logging
import time

log = logging.getLogger("pulse.daemons.consolidation.consolidation_late_stages")

from pulse.core.paths import get_state_dir
from pulse.core.brain_utils import HIPPOCAMPUS_DIR, save_json, now_iso as _now_iso

CONSOLIDATION_LOG = get_state_dir() / "consolidation_log.json"
_STAGE_PROGRESS_FILE = HIPPOCAMPUS_DIR / 'Evidence' / 'Metrics' / 'consolidation_stages.json'

def _save_stage_progress(stage_results: dict):
    """Item 99: Persist per-stage timing data for monitoring."""
    try:
        _STAGE_PROGRESS_FILE.parent.mkdir(parents=True, exist_ok=True)
        save_json(_STAGE_PROGRESS_FILE, {'timestamp': _now_iso(), 'stages': stage_results})
    except Exception: pass

def run_late_stages(verbose: bool = False, early: dict = None) -> dict:
    """Run consolidation stages 11-21 and assemble the full log."""
    if early is None: early = {}
    start = early.get('start', time.time())
    
    # Stage 6c: Cross-Reference Builder (Sprint 2 Wiring)
    print("[CONSOLIDATION] Stage 6c: Cross-References")
    try:
        from pulse.brain.index.cross_ref_builder import build_cross_refs
        index_result = build_cross_refs()
    except Exception as e:
        index_result = {"status": "error", "error": str(e)}

    # Stages 11-15: (Causal, Goal, Prospective, Sentinels, Autonomy)
    from pulse.daemons.consolidation.consolidation_mid_stages import run_mid_stages
    mid_results = run_mid_stages(verbose=verbose)

    # Stage 16: Pattern Evolution (Phase 6E — auto-generate regex)
    print("[CONSOLIDATION] Stage 16: Pattern Evolution")
    try:
        from pulse.brain.monitoring.pattern_evolution import evolve_patterns
        evolution_result = evolve_patterns(verbose=verbose)
        new_p = evolution_result.get("new_patterns", [])
        if isinstance(new_p, list) and len(new_p) > 0:
            from pulse.daemons.consolidation.approval_gate import check_approval
            check_approval("pattern_evolution", new_p)
    except Exception as e:
        evolution_result = {"status": "error", "error": str(e)}

    # Stage 17: Associative Replay (Phase 6A — dreaming)
    print("[CONSOLIDATION] Stage 17: Associative Replay")
    try:
        from pulse.daemons.synthesis.learning.associative_replay import run_replay
        replay_result = run_replay(verbose=verbose)
    except Exception as e:
        replay_result = {"status": "error", "error": str(e)}

    # Stage 18: Deep Consolidation
    print("[CONSOLIDATION] Stage 18: Deep Consolidation")
    try:
        from pulse.daemons.consolidation.consolidation_stages import stage_deep_consolidation
        deep_result = stage_deep_consolidation(verbose=verbose)
    except Exception as e:
        deep_result = {"status": "error", "error": str(e)}

    # Stage 19: Session-Based Replay
    print("[CONSOLIDATION] Stage 19: Session Replay")
    try:
        from pulse.daemons.consolidation.session_replay import run_session_replay
        session_replay_result = run_session_replay(verbose=verbose)
    except Exception as e:
        session_replay_result = {"status": "error", "error": str(e)}

    # Stage 20: Conflict Monitor
    print("[CONSOLIDATION] Stage 20: Conflict Monitor")
    try:
        from pulse.daemons.synthesis.core.conflict_monitor import scan_for_conflicts
        conflict_result = scan_for_conflicts(verbose=verbose)
    except Exception as e:
        conflict_result = {"status": "error", "error": str(e)}

    # Stage 21: Spaced Retrieval
    print("[CONSOLIDATION] Stage 21: Spaced Retrieval")
    try:
        from pulse.daemons.consolidation.retrieval_scheduler import schedule_reviews
        spaced_result = schedule_reviews(verbose=verbose)
    except Exception as e:
        spaced_result = {"status": "error", "error": str(e)}

    # Stage 22: Neocortical Semantic Extraction
    print("[CONSOLIDATION] Stage 22: Neocortical Semantic Extraction")
    try:
        from pulse.daemons.consolidation.stages.stage_neocortical_extraction import stage_neocortical_extraction
        neo_result = stage_neocortical_extraction(verbose=verbose)
    except Exception as e:
        neo_result = {"status": "error", "error": str(e)}

    elapsed = round(time.time() - start, 2)
    _save_stage_progress({"stage_6c_cross_refs": index_result, "stage_11_21": "ok"})

    full_log = {
        "timestamp": _now_iso(), "elapsed_seconds": elapsed,
        "stage_1_dedup": early.get('dedup_result'),
        "stage_2_mining": {"sequences_found": len(early.get('sequences', [])), "cross_patterns_found": len(early.get('cross_patterns', []))},
        "stage_2b_procedures": {"registered": early.get('proc_count', 0)},
        "stage_2c_ltd_decay": early.get('ltd_result'),
        "stage_2d_reconsolidation": early.get('recon_result'),
        "stage_2e_transfer": early.get('transfer_result'),
        "stage_2f_cross_region": early.get('cross_region_result'),
        "stage_3_schemas": early.get('schema_result'),
        "stage_3b_sequence_schemas": early.get('seq_schema_result'),
        "stage_3c_micro_patterns": early.get('micro_pattern_result'),
        "stage_3d_meta_schemas": early.get('meta_schema_result'),
        "stage_4_graph": early.get('graph_result'),
        "stage_4b_promote_patterns": early.get('promote_result'),
        "stage_4c_abstraction": early.get('abstraction_result'),
        "stage_5_metacognition": early.get('meta_result'),
        "stage_6_hierarchical_prune": early.get('prune_result'),
        "stage_7_brain_health": early.get('health_result'),
        "stage_8_truth_verification": early.get('truth_result'),
        "stage_9_decision_consolidation": early.get('decision_result'),
        "stage_6b_search_index": early.get('index_result'),
        "stage_6c_cross_refs": index_result,
        "stage_10_metamemory": early.get('metamemory_result'),
        "stage_10b_homeostasis": early.get('homeostasis_result'),
        **mid_results,
        "stage_16_pattern_evolution": evolution_result,
        "stage_17_replay": replay_result,
        "stage_18_deep_consolidation": deep_result,
        "stage_19_session_replay": session_replay_result,
        "stage_20_conflict_monitor": conflict_result,
        "stage_21_spaced_retrieval": spaced_result,
        "stage_22_neocortical": neo_result,
    }

    CONSOLIDATION_LOG.parent.mkdir(parents=True, exist_ok=True)
    save_json(CONSOLIDATION_LOG, full_log)
    print(f"\n[CONSOLIDATION] Complete in {elapsed}s")

    try:
        from pulse.brain.metacognition.metamemory_tracking import reset_consolidation_debt
        reset_consolidation_debt()
    except Exception: pass

    try:
        from pulse.brain.monitoring.brain_self_assessment import get_brain_health_report
        health = get_brain_health_report()
        import json as _json
        (get_state_dir() / "brain_health.json").write_text(_json.dumps(health, indent=2), encoding="utf-8")
    except Exception: pass

    return full_log
