#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Stages 2/3: Pattern mining and schema promotion."""
from pathlib import Path

from pulse.core.brain_utils import (
    HIPPOCAMPUS_DIR, PATTERNS_DIR, load_json_dict, save_json,
    now_iso as _now_iso,
)


def stage_pattern_mining(verbose=False):
    """Stage 2: Mine patterns from past 7 days."""
    from pulse.daemons.consolidation.consolidation_helpers import (
        extract_event_sequences, mine_cross_session_patterns,
    )
    sequences = extract_event_sequences(days=7, verbose=verbose)
    cross_patterns = mine_cross_session_patterns(days=7, verbose=verbose)
    return {
        "status": "ok",
        "sequences": sequences,
        "cross_patterns": cross_patterns,
        "total_found": len(sequences) + len(cross_patterns),
    }


def stage_schema_promotion(cross_patterns, verbose=False):
    """Promote high-confidence cross-session patterns to schemas.json."""
    from pulse.daemons.consolidation.consolidation_helpers import promote_cross_patterns_to_schemas
    return promote_cross_patterns_to_schemas(cross_patterns, verbose=verbose)


def stage_schema_promotion_from_sequences(sequences, verbose=False):
    """Promote event sequences with 5+ occurrences to schemas.json."""
    from pulse.daemons.consolidation.consolidation_helpers import promote_sequences_to_schemas
    return promote_sequences_to_schemas(sequences, verbose=verbose)


def stage_cross_domain_transfer(verbose=False):
    """Stage 2e: Detect patterns appearing across 2+ evidence domains."""
    from pulse.core.brain_analysis import detect_cross_domain_patterns
    evidence_dir = HIPPOCAMPUS_DIR / "Evidence"
    transfers = detect_cross_domain_patterns(evidence_dir)
    if not transfers:
        if verbose:
            print("  [TRANSFER] No cross-domain patterns found")
        return {"status": "ok", "transfers": 0, "promoted": 0}
    schemas_file = PATTERNS_DIR / "schemas.json"
    schemas_data = load_json_dict(schemas_file)
    schemas = schemas_data.get("schemas", [])
    existing = {s.get("name", "").lower() for s in schemas}
    promoted = 0
    for t in transfers:
        if not t.get("universal"):
            continue
        name = f"Cross-domain: {t['pattern'][:50]}"
        if name.lower() in existing:
            continue
        schemas.append({
            "name": name, "confidence": 0.65, "evidence_count": t["count"],
            "domains": t["domains"], "type": "cross_domain_transfer",
            "created": _now_iso(),
        })
        existing.add(name.lower())
        promoted += 1
        if verbose:
            print(f"  [TRANSFER] {name} ({t['count']} domains)")
    if promoted:
        schemas_data["schemas"] = schemas
        schemas_data["last_updated"] = _now_iso()
        # P47: SQLite-first write
        try:
            from pulse.brain.sqlite_writers import bulk_upsert_schemas
            bulk_upsert_schemas(schemas, source="cross_domain_transfer")
        except Exception:
            pass
        save_json(schemas_file, schemas_data)  # debug export
    if verbose:
        print(f"  [TRANSFER] {len(transfers)} cross-domain, {promoted} promoted")
    return {"status": "ok", "transfers": len(transfers), "promoted": promoted}


def stage_2f_cross_region_mining(verbose=False):
    """Stage 2f: Mine patterns across lessons and failures (last 3 days)."""
    try:
        from pulse.core.brain_db import get_conn
        from datetime import datetime, timezone, timedelta
        conn = get_conn()
        three_days_ago = (datetime.now(timezone.utc) - timedelta(days=3)).isoformat()
        res = conn.execute("""
            SELECT l.id, f.id, l.domain
            FROM lessons l
            JOIN failures f ON l.domain = f.domain
            WHERE l.timestamp >= ? AND f.timestamp >= ?
        """, (three_days_ago, three_days_ago))
        pairs = res.fetchall()
        if verbose:
            print(f"  [2F] Mined {len(pairs)} cross-region pairs.")
        return {"mined_cross_patterns": len(pairs)}
    except ImportError:
        if verbose:
            print("  [2F] SQLite DAL not fully loaded")
        return {"status": "skipped"}
    except Exception as e:
        if verbose:
            print(f"  [2F] Error: {e}")
        return {"error": str(e)}


def _stage_schema_distortion_audit(verbose=False):
    """Item 44: Flag schemas whose confidence has drifted >0.3 from baseline (0.5)."""
    result = {"status": "ok", "checked": 0, "flagged": 0}
    try:
        from pulse.core.brain_db import get_conn
        conn = get_conn()
        distorted = conn.execute(
            "SELECT id, name, confidence FROM schemas WHERE ABS(confidence - 0.5) > 0.3"
        ).fetchall()
        result["checked"] = len(distorted)
        for schema in distorted:
            try:
                conn.execute(
                    "UPDATE schemas SET metadata = json_set(COALESCE(metadata, '{}'), '$.distortion_flag', 1) WHERE id = ?",
                    (schema["id"],)
                )
                result["flagged"] += 1
                if verbose:
                    print(f"  [DISTORTION] Schema {schema['name']} conf={schema['confidence']} flagged")
            except Exception:
                pass
        conn.commit()
    except Exception:
        pass  # fail-open
    if verbose:
        print(f"  [DISTORTION] Checked {result['checked']} schemas, flagged {result['flagged']}")
    return result
stage_schema_distortion_audit = _stage_schema_distortion_audit


def _stage_episodic_graduation(verbose=False):
    """Item 81: Graduate frequently-accessed episodic items to semantic facts."""
    result = {'status': 'ok', 'candidates': 0, 'graduated': 0}
    try:
        from pulse.core.brain_db import get_conn
        from pulse.brain.persistence.fact_store import _check_graduation
        conn = get_conn()
        candidates = conn.execute(
            'SELECT id, content, confidence, access_count, domain FROM facts '
            'WHERE type = "episodic" AND access_count >= 5 AND confidence >= 0.7 '
            'LIMIT 20'
        ).fetchall()
        result['candidates'] = len(candidates)
        for row in candidates:
            try:
                if _check_graduation(dict(row)):
                    result['graduated'] += 1
                    if verbose:
                        snippet = str(dict(row).get('content', ''))[:60]
                        print('  [GRAD] episodic->semantic: ' + snippet)
            except Exception:
                pass
    except Exception:
        pass  # fail-open
    if verbose:
        print('  [GRAD] candidates=' + str(result['candidates']) +
              ', graduated=' + str(result['graduated']))
    return result
stage_episodic_graduation = _stage_episodic_graduation
