"""Vaultfire Law 6: Moral Alignment Synchronizer."""
from __future__ import annotations

from datetime import datetime
from pathlib import Path
from typing import Any, Dict, Mapping, Sequence

from .human_standard_guard import DEFAULT_HUMAN_STANDARD_GUARD

from utils.json_io import load_json, write_json

BASE_DIR = Path(__file__).resolve().parents[1]
BELIEF_TRACE_LOG_PATH = BASE_DIR / "logs" / "belief_trace_log.json"
DEFAULT_BELIEF_FLOOR = 0.6
DEFAULT_EMPATHY_THRESHOLD = 0.58
HUMANITY_TOKENS = {
    "advance",
    "care",
    "community",
    "empathy",
    "guard",
    "guardian",
    "guardians",
    "guide",
    "human",
    "humanity",
    "integrity",
    "protect",
    "safeguard",
    "steward",
    "stewardship",
    "support",
    "sustain",
    "uplift",
    "vaultfire",
    "ns3",
    "ghostkey",
    "ghostkey-316",
    "purpose",
}
FORBIDDEN_TOKENS = {
    "abuse",
    "coerce",
    "dominate",
    "erase",
    "exploit",
    "harm",
    "harvest",
    "manipulate",
    "oppress",
    "purge",
    "subjugate",
    "surveil",
    "surveillance",
    "weapon",
    "weaponize",
}
OVERRIDE_TRUST_TIERS = {"guardian", "architect", "trusted", "ethics-lead"}


def _coerce_float(value: Any, default: float) -> float:
    try:
        return float(value)
    except (TypeError, ValueError):
        return default


def _extract_text(payload: Mapping[str, Any], *keys: str) -> str:
    for key in keys:
        value = payload.get(key)
        if isinstance(value, str) and value.strip():
            return value.strip()
    return ""


def _collect_tags(payload: Mapping[str, Any]) -> set[str]:
    tags: set[str] = set()
    for key in ("mission_tags", "missionTags", "tags", "labels", "goal_tags", "memory_tags"):
        value = payload.get(key)
        if isinstance(value, Sequence) and not isinstance(value, (str, bytes)):
            for item in value:
                if isinstance(item, str) and item.strip():
                    tags.add(item.strip().lower())
        elif isinstance(value, str) and value.strip():
            tags.add(value.strip().lower())
    return tags


def _tokenize(text: str) -> set[str]:
    tokens: set[str] = set()
    for raw in text.lower().replace("-", " ").split():
        cleaned = "".join(ch for ch in raw if ch.isalnum())
        if cleaned:
            tokens.add(cleaned)
    return tokens


def _identity_tag(identity: Mapping[str, Any] | None) -> str | None:
    if not identity:
        return None
    for key in ("ens", "user_id", "wallet", "id", "address", "participant"):
        value = identity.get(key)
        if isinstance(value, str) and value.strip():
            return value.strip()
    return None


def _append_audit_log(record: Mapping[str, Any]) -> None:
    log: list[Dict[str, Any]] = load_json(BELIEF_TRACE_LOG_PATH, [])
    log.append(dict(record))
    write_json(BELIEF_TRACE_LOG_PATH, log)


def evaluate_alignment(
    operation: str,
    payload: Mapping[str, Any],
    identity: Mapping[str, Any] | None = None,
    *,
    override_requested: bool = False,
) -> Dict[str, Any]:
    """Evaluate ``operation`` context against the Vaultfire ethics framework."""

    payload_dict = dict(payload)
    belief_density = _coerce_float(
        payload_dict.get("belief_density")
        or payload_dict.get("beliefDensity"),
        DEFAULT_BELIEF_FLOOR,
    )
    empathy_score = _coerce_float(
        payload_dict.get("empathy_score")
        or payload_dict.get("empathyScore")
        or (identity.get("empathy_score") if identity else None)
        or (identity.get("empathyScore") if identity else None),
        0.7,
    )
    mission_text = _extract_text(
        payload_dict,
        "mission",
        "declared_purpose",
        "declaredPurpose",
        "purpose",
    )
    if not mission_text and identity:
        mission_text = _extract_text(identity, "mission", "purpose")
    intent_text = _extract_text(payload_dict, "intent", "justification")

    combined_text = " ".join(filter(None, [mission_text, intent_text]))
    tokens = _tokenize(combined_text)
    tags = _collect_tags(payload_dict)

    reasons: list[str] = []
    if belief_density < DEFAULT_BELIEF_FLOOR:
        reasons.append("belief density below moral floor")
    if empathy_score < DEFAULT_EMPATHY_THRESHOLD:
        reasons.append("empathy threshold breached")

    if tokens & FORBIDDEN_TOKENS or tags & FORBIDDEN_TOKENS or "rogue" in tags:
        reasons.append("mission conflicts with empathy covenant")

    mission_optional = operation.startswith("memory.")

    if mission_text:
        if not mission_optional and not (tokens & HUMANITY_TOKENS or tags & HUMANITY_TOKENS):
            reasons.append("mission lacks human-first focus")
    else:
        if not mission_optional:
            reasons.append("mission clarity required for human-first execution")

    decision = "allow"
    allowed = True
    pre_human_decision = "allow"
    if reasons:
        allowed = False
        decision = "delay"
        if any(
            phrase in reason
            for reason in reasons
            for phrase in ("breached", "conflicts", "forbidden", "harm")
        ):
            decision = "block"

    identity_mapping: Dict[str, Any] = dict(identity) if identity else {}
    override_flag = bool(payload_dict.get("override")) or bool(identity_mapping.get("override"))
    if override_requested:
        override_flag = True
    signature = (
        payload_dict.get("override_signature")
        or payload_dict.get("belief_signature")
        or identity_mapping.get("beliefSignature")
        or identity_mapping.get("belief_signature")
    )
    if not signature and payload_dict.get("beliefSignatureVerified"):
        signature = payload_dict.get("beliefSignatureVerified")
    trust_tier_value = (
        payload_dict.get("trust_tier")
        or payload_dict.get("trustTier")
        or identity_mapping.get("trust_tier")
        or identity_mapping.get("trustTier")
        or identity_mapping.get("role")
        or identity_mapping.get("tier")
    )
    trust_tier = str(trust_tier_value).strip().lower() if trust_tier_value else ""
    signature_valid = isinstance(signature, str) and len(signature.strip()) >= 8
    override_granted = False
    if not allowed and override_flag and signature_valid and trust_tier in OVERRIDE_TRUST_TIERS:
        allowed = True
        decision = "override"
        override_granted = True

    drift = bool(reasons)
    audit_record = {
        "operation": operation,
        "timestamp": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
        "identity": _identity_tag(identity_mapping),
        "allowed": allowed,
        "decision": decision,
        "reasons": reasons or ["cleared"],
        "belief_density": round(belief_density, 3),
        "empathy_score": round(empathy_score, 3),
        "override": override_granted,
        "drift_flag": drift,
    }
    if trust_tier:
        audit_record["trust_tier"] = trust_tier
    if override_flag and not override_granted:
        audit_record["override_denied"] = True

    human_guard_payload = {
        "mission": mission_text,
        "intent": intent_text,
        "combined_text": combined_text,
        "empathy_score": empathy_score,
        "belief_density": belief_density,
        "mission_tags": list(tags),
        "tokens": sorted(tokens),
        "override": override_flag,
    }
    human_guard_context = {
        "alignment_reasons": list(reasons),
        "mission": True,
        "dialogue": False,
        "enforce_human_first": True,
        "override_requested": override_flag,
        "initial_decision": decision,
    }
    pre_human_decision = decision
    human_standard_result = DEFAULT_HUMAN_STANDARD_GUARD.evaluate(
        operation,
        human_guard_payload,
        identity=identity_mapping,
        context=human_guard_context,
        initial_decision=allowed,
    )
    audit_record["human_standard"] = human_standard_result["audit_record"]
    audit_record["human_standard_hash"] = human_standard_result["human_standard_hash"]
    audit_record["human_standard_escalation"] = human_standard_result["escalation_level"]
    audit_record["ethics_versions"] = human_standard_result["ethics_versions"]
    audit_record["passive_empathy_synced"] = human_standard_result["passive_empathy_synced"]
    if not human_standard_result["allowed"]:
        allowed = False
        decision = human_standard_result["decision"]
        for reason in human_standard_result["reasons"]:
            if reason not in reasons:
                reasons.append(reason)
        audit_record["allowed"] = False
        audit_record["decision"] = decision
        audit_record["reasons"] = reasons or ["human standard guard review"]

    # Harmonize decision semantics so external integrations receive
    # ``delay``/``block`` rather than the human-standard specific
    # ``review`` label.  We preserve ``override`` and ``block`` decisions
    # as-is while translating softer human guard escalations into the
    # canonical ``delay`` action.
    severity_alias = {"review": "delay"}
    if decision in severity_alias and pre_human_decision in {"block", "delay"}:
        decision = severity_alias[decision]
        audit_record["decision"] = decision

    _append_audit_log(audit_record)

    return {
        "allowed": allowed,
        "decision": decision,
        "reasons": list(reasons),
        "override": override_granted,
        "drift": drift,
        "audit_record": audit_record,
        "inputs": {
            "belief_density": belief_density,
            "empathy_score": empathy_score,
            "trust_tier": trust_tier,
        },
        "human_standard": human_standard_result,
        "human_standard_hash": human_standard_result["human_standard_hash"],
    }


__all__ = [
    "evaluate_alignment",
    "BELIEF_TRACE_LOG_PATH",
    "DEFAULT_BELIEF_FLOOR",
    "DEFAULT_EMPATHY_THRESHOLD",
]
