"""Phase 5D: Graduated Autonomy — trust ladder with promotion/demotion logic."""
import json
from datetime import datetime, timezone
from pathlib import Path
from pulse.core.paths import get_state_dir
from pulse.core import event_bus
from pulse.core.brain_io import _acquire

AUTONOMY_FILE = get_state_dir() / "autonomy_state.json"

LEVEL_NAMES = {0: "Witness", 1: "Apprentice", 2: "Journeyman", 3: "Artisan", 4: "Steward"}

PROMOTION_REQUIREMENTS = {
    0: {"successful_tasks": 20, "regressions": 0, "days": 7},
    1: {"successful_tasks": 50, "oracle_accuracy": 0.6, "days": 14},
    2: {"successful_tasks": 100, "demotions": 0, "days": 30},
    3: {"successful_tasks": 200, "human_audit": True, "days": 60},
}


def _load_state() -> dict:
    if not AUTONOMY_FILE.exists():
        return _default_state()
    try:
        return json.loads(AUTONOMY_FILE.read_text(encoding="utf-8"))
    except Exception:
        return _default_state()


def _save_state(state: dict):
    AUTONOMY_FILE.parent.mkdir(parents=True, exist_ok=True)
    with _acquire(AUTONOMY_FILE):
        AUTONOMY_FILE.write_text(json.dumps(state, indent=2), encoding="utf-8")


def _default_state() -> dict:
    return {
        "trust_level": 0,
        "current_level_name": "Witness",
        "promoted_at": datetime.now(timezone.utc).isoformat(),
        "history": [{"level": 0, "date": datetime.now(timezone.utc).isoformat(), "reason": "bootstrap"}],
        "metrics": {
            "successful_tasks": 0,
            "failed_tasks": 0,
            "regressions": 0,
            "demotions": 0,
            "consecutive_failures": 0,
        },
    }


def get_trust_level() -> int:
    """Return current trust level (0-4)."""
    return _load_state()["trust_level"]


def record_task_outcome(success: bool, regression: bool = False):
    """Record task outcome for promotion tracking."""
    state = _load_state()
    if success:
        state["metrics"]["successful_tasks"] += 1
        state["metrics"]["consecutive_failures"] = 0
    else:
        state["metrics"]["failed_tasks"] += 1
        state["metrics"]["consecutive_failures"] += 1
    if regression:
        state["metrics"]["regressions"] += 1
    _save_state(state)

    # Check demotion triggers
    if regression or state["metrics"]["consecutive_failures"] >= 3:
        _demote(state, "regression" if regression else "consecutive_failures")


def check_promotion() -> bool:
    """Check if promotion criteria met. Called by consolidation."""
    state = _load_state()
    level = state["trust_level"]
    if level >= 4:
        return False

    reqs = PROMOTION_REQUIREMENTS.get(level, {})
    metrics = state["metrics"]
    promoted_at = datetime.fromisoformat(state["promoted_at"])
    days_at_level = (datetime.now(timezone.utc) - promoted_at).days

    # Check all requirements
    if days_at_level < reqs.get("days", 0):
        return False
    if metrics["successful_tasks"] < reqs.get("successful_tasks", 0):
        return False
    if reqs.get("regressions") is not None and metrics["regressions"] > reqs["regressions"]:
        return False
    if reqs.get("human_audit") and not state.get("human_audit_passed"):
        return False

    # Promote
    state["trust_level"] = level + 1
    state["current_level_name"] = LEVEL_NAMES[level + 1]
    state["promoted_at"] = datetime.now(timezone.utc).isoformat()
    state["history"].append({
        "level": level + 1,
        "date": datetime.now(timezone.utc).isoformat(),
        "reason": "promotion",
    })
    state["metrics"]["regressions"] = 0
    state["metrics"]["consecutive_failures"] = 0
    _save_state(state)
    event_bus.publish(
        "autonomy.promoted", "autonomy_state",
        {"new_level": level + 1, "name": LEVEL_NAMES[level + 1]},
    )
    return True


def _demote(state: dict, reason: str):
    """Drop trust level by 1."""
    if state["trust_level"] <= 0:
        return
    state["trust_level"] -= 1
    state["current_level_name"] = LEVEL_NAMES[state["trust_level"]]
    state["metrics"]["demotions"] = state["metrics"].get("demotions", 0) + 1
    state["metrics"]["consecutive_failures"] = 0
    state["promoted_at"] = datetime.now(timezone.utc).isoformat()
    state["history"].append({
        "level": state["trust_level"],
        "date": datetime.now(timezone.utc).isoformat(),
        "reason": f"demotion:{reason}",
    })
    _save_state(state)
    event_bus.publish(
        "autonomy.demoted", "autonomy_state",
        {"new_level": state["trust_level"], "reason": reason},
    )
