#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""SQLite-first writers for data that was previously JSON-only.

P47 Phase 1-4: Replace save_json() calls with SQLite upserts.
Each function writes to SQLite first, with JSON as optional debug export.
"""
import json
import hashlib
import logging
from datetime import datetime, timezone

log = logging.getLogger("pulse.sqlite_writers")


def _now():
    return datetime.now(timezone.utc).isoformat()


def _fp(text):
    return hashlib.md5(text[:200].encode("utf-8", errors="replace")).hexdigest()[:12]


def upsert_schema(name, description, domain="general", confidence=0.5,
                  schema_type="heuristic", source="consolidation", evidence_links=None,
                  metadata=None):
    """Write a schema to SQLite schemas table. Replaces save_json(SCHEMAS_FILE)."""
    try:
        from pulse.core.brain_db import get_conn
        conn = get_conn()
        sid = f"SCH-{_fp(name)}"
        now = _now()
        conn.execute(
            "INSERT OR REPLACE INTO schemas "
            "(id, name, description, domain, confidence, type, source, evidence_links, created, metadata, source_type) "
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            (sid, name[:200], (description or "")[:2000], domain, confidence,
             schema_type, source, json.dumps(evidence_links or []),
             now, json.dumps(metadata or {}), "CONFIRMED"))
        # Also update FTS
        conn.execute("DELETE FROM knowledge_fts WHERE item_id=? AND table_name='schemas'", (sid,))
        conn.execute(
            "INSERT INTO knowledge_fts (item_id, content, title, domain, agent, table_name) "
            "VALUES (?, ?, ?, ?, ?, 'schemas')",
            (sid, (description or "")[:2000], name[:200], domain, source))
        conn.commit()
        return sid
    except Exception as e:
        log.warning("upsert_schema failed: %s", e)
        return None


def bulk_upsert_schemas(schemas_list, source="consolidation"):
    """Bulk write schemas from a list of dicts (replaces save_json on schemas_data)."""
    count = 0
    for s in schemas_list:
        if not isinstance(s, dict):
            continue
        name = s.get("name", "")
        if not name:
            continue
        result = upsert_schema(
            name=name,
            description=s.get("description", ""),
            domain=s.get("domain", "general"),
            confidence=float(s.get("confidence", 0.5)),
            schema_type=s.get("type", "heuristic"),
            source=source,
            evidence_links=s.get("evidence_links", []),
            metadata=s.get("metadata", {}),
        )
        if result:
            count += 1
    return count


def upsert_procedure(name, description, steps, domain="general",
                     confidence=0.5, source="procedure_daemon"):
    """Write a procedure to SQLite procedures table. Replaces procedural_log.json writes."""
    try:
        from pulse.core.brain_db import get_conn
        conn = get_conn()
        pid = f"PROC-{_fp(name)}"
        now = _now()
        # Try update first (increment executions)
        res = conn.execute(
            "UPDATE procedures SET executions=executions+1, description=?, steps=?, "
            "confidence=MAX(confidence, ?), metadata=? WHERE id=?",
            ((description or "")[:2000], json.dumps(steps or []),
             confidence, json.dumps({"last_seen": now}), pid))
        if res.rowcount == 0:
            conn.execute(
                "INSERT OR IGNORE INTO procedures "
                "(id, name, description, steps, domain, confidence, executions, "
                "successes, failures_count, source, created, metadata) "
                "VALUES (?, ?, ?, ?, ?, ?, 1, 0, 0, ?, ?, ?)",
                (pid, name[:200], (description or "")[:2000], json.dumps(steps or []),
                 domain, confidence, source, now, json.dumps({})))
        conn.commit()
        return pid
    except Exception as e:
        log.warning("upsert_procedure failed: %s", e)
        return None


def bulk_upsert_procedures(procedures_list, source="consolidation"):
    """Bulk write procedures from a list of dicts."""
    count = 0
    for p in procedures_list:
        if not isinstance(p, dict):
            continue
        name = p.get("name", "")
        if not name:
            continue
        result = upsert_procedure(
            name=name,
            description=p.get("description", ""),
            steps=p.get("steps", []),
            domain=p.get("domain", "general"),
            confidence=float(p.get("confidence", 0.5)),
            source=source,
        )
        if result:
            count += 1
    return count


def upsert_anti_pattern(description, rule="", reason="", domain="general",
                        severity="medium", source="anti_pattern_builder",
                        evidence_count=1, keywords=None):
    """Write an anti-pattern to SQLite. Replaces anti_patterns_active.json writes."""
    try:
        from pulse.core.brain_db import get_conn
        conn = get_conn()
        apid = f"AP-{_fp(description)}"
        now = _now()
        # Upsert: increment evidence if exists
        res = conn.execute(
            "UPDATE anti_patterns SET evidence_count=evidence_count+1, "
            "rule=COALESCE(NULLIF(?, ''), rule), reason=COALESCE(NULLIF(?, ''), reason), "
            "metadata=? WHERE id=?",
            (rule, reason, json.dumps({"last_seen": now}), apid))
        if res.rowcount == 0:
            conn.execute(
                "INSERT OR IGNORE INTO anti_patterns "
                "(id, description, rule, reason, domain, keywords, severity, "
                "evidence_count, status, source, created, metadata, validity, "
                "access_count, confidence, source_type) "
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?, '{}', 'valid', 0, 0.7, 'OBSERVED')",
                (apid, description[:500], rule[:500], reason[:500], domain,
                 json.dumps(keywords or []), severity, evidence_count, source, now))
            # FTS
            conn.execute(
                "INSERT INTO knowledge_fts (item_id, content, title, domain, agent, table_name) "
                "VALUES (?, ?, ?, ?, ?, 'anti_patterns')",
                (apid, description[:500], (rule or description)[:80], domain, source))
        conn.commit()
        return apid
    except Exception as e:
        log.warning("upsert_anti_pattern failed: %s", e)
        return None
