from __future__ import annotations

from .models import (
    DesktopPassiveState,
    TimelineEvent,
    LineageNode,
    Warning,
    ModalState,
)



def build_visual_trust_ux(state: DesktopPassiveState | None) -> dict[str, object]:
    """
    Returns a dict with all visual trust UX data for rendering:
    - Pairing modal/page
    - Trust status card
    - Continuity timeline (append-only)
    - Lineage graph (read-only)
    - Human approval modals/dialogs
    - Warning system (all severities)
    """
    if state is None:
        return {
            "pairing_modal": {"visible": True, "state": "init", "error": None},
            "trust_status_card": {
                "paired_status": "Not paired",
                "trust_status": "Pending Trust",
                "revoked_warning": False,
                "reconnect_state": "Idle",
                "workspace_continuity_badges": [],
                "last_heartbeat_time": None,
                "trust_generation": 0,
                "reconnect_generation": 0,
                "warning_severity": None,
            },
            "timeline": [],
            "lineage_graph": [],
            "warnings": [],
            "active_modal": None,
            "passive_only": True,
        }

    trust_status = str(state.trust_status or "paired")
    reconnect_state = "Reconnecting" if trust_status == "reconnecting" else "Connected"
    if trust_status in {"revoked", "pair_required"}:
        reconnect_state = "Blocked"

    # Trust status card
    trust_status_card = {
        "paired_status": "Paired" if trust_status not in {"pair_required"} else "Pairing Required",
        "trust_status": trust_status,
        "revoked_warning": trust_status == "revoked",
        "reconnect_state": reconnect_state,
        "workspace_continuity_badges": list(state.continuity_badges),
        "last_heartbeat_time": state.last_heartbeat_ts,
        "trust_generation": state.trust_generation,
        "reconnect_generation": state.reconnect_generation,
        "warning_severity": max((w.severity for w in state.warnings if not w.acknowledged), default=None, key=_severity_rank),
    }

    # Pairing modal/page state
    pairing_modal = None
    if trust_status in {"pair_required", "pending"}:
        pairing_modal = {"visible": True, "state": trust_status, "error": state.last_error}
    elif trust_status == "revoked":
        pairing_modal = {"visible": False, "state": "revoked", "error": state.last_error}
    else:
        pairing_modal = {"visible": False, "state": "paired", "error": None}

    # Timeline (append-only)
    timeline = [
        {
            "timestamp": e.timestamp,
            "event_type": e.event_type,
            "detail": e.detail,
        }
        for e in getattr(state, "timeline", [])
    ]

    # Lineage graph (read-only)
    lineage_graph = [
        {
            "node_id": n.node_id,
            "parent_id": n.parent_id,
            "status": n.status,
            "is_original": n.is_original,
            "is_current": n.is_current,
            "revoked_at": n.revoked_at,
            "restored_at": n.restored_at,
        }
        for n in getattr(state, "lineage", [])
    ]

    # Warnings (all severities)
    warnings = [
        {
            "warning_id": w.warning_id,
            "severity": w.severity,
            "type": w.type,
            "message": w.message,
            "acknowledged": w.acknowledged,
            "timestamp": w.timestamp,
        }
        for w in getattr(state, "warnings", [])
    ]

    # Modal/dialog state (explicit confirmations)
    active_modal = None
    if state.active_modal:
        active_modal = {
            "modal_type": state.active_modal.modal_type,
            "visible": state.active_modal.visible,
            "context": state.active_modal.context,
        }

    # 3C.3E Transport Hardening Status
    session_state = None
    if state.session_lifecycle:
        session_state = {
            "state": state.session_lifecycle.state,
            "entered_at": state.session_lifecycle.entered_at,
            "last_transition_reason": state.session_lifecycle.last_transition_reason,
            "reconnect_attempts": state.session_lifecycle.reconnect_attempts,
            "offline_since": state.session_lifecycle.offline_since,
        }

    # Connectivity and degraded mode
    is_offline = state.offline_recovery.is_offline
    degraded_mode = state.transport_metrics.degraded_mode_active or state.transport_metrics.transport_instability_detected
    connectivity_state = "offline" if is_offline else ("degraded" if degraded_mode else "connected")

    # Transport health indicators
    transport_health = {
        "connectivity_state": connectivity_state,
        "degraded_mode_active": degraded_mode,
        "heartbeat_success_count": state.transport_metrics.heartbeat_success_count,
        "heartbeat_failure_count": state.transport_metrics.heartbeat_failure_count,
        "last_heartbeat_latency_ms": state.transport_metrics.last_heartbeat_latency_ms,
        "avg_heartbeat_latency_ms": state.transport_metrics.heartbeat_latency_ms_avg,
        "reconnect_count": state.transport_metrics.reconnect_count,
        "last_transport_error": state.transport_metrics.last_transport_error,
        "transport_instability_detected": state.transport_metrics.transport_instability_detected,
        "offline_periods": state.transport_metrics.offline_periods,
        "total_offline_sec": state.transport_metrics.total_offline_sec,
    }

    # Offline recovery state
    offline_recovery = {
        "is_offline": state.offline_recovery.is_offline,
        "offline_started_at": state.offline_recovery.offline_started_at,
        "pending_heartbeats": state.offline_recovery.pending_heartbeats,
        "recovery_in_progress": state.offline_recovery.recovery_in_progress,
        "stale_recovery_warning_shown": state.offline_recovery.stale_recovery_warning_shown,
    }

    # Operational diagnostics
    diagnostics = None
    if state.diagnostics:
        diagnostics = {
            "session_uptime_sec": state.diagnostics.session_uptime_sec,
            "trust_token_expires_in_sec": state.diagnostics.trust_token_expires_in_sec,
            "last_server_contact_at": state.diagnostics.last_server_contact_at,
            "server_clock_skew_sec": state.diagnostics.server_clock_skew_sec,
            "warnings_aggregated": state.diagnostics.warnings_aggregated,
        }

    # Warning escalation status
    escalations = [
        {
            "warning_type": e.warning_type,
            "occurrence_count": e.occurrence_count,
            "severity_level": e.severity_level,
            "escalated_at": e.escalated_at,
        }
        for e in getattr(state, "warning_escalations", [])
    ]

    return {
        "pairing_modal": pairing_modal,
        "trust_status_card": trust_status_card,
        # Backward-compatible aliases for older tests/UI consumers.
        "trust_status": trust_status,
        "revoked_warning": trust_status_card["revoked_warning"],
        "workspace_continuity_badges": list(state.continuity_badges),
        "timeline": timeline,
        "lineage_graph": lineage_graph,
        "warnings": warnings,
        "active_modal": active_modal,
        "session_lifecycle": session_state,
        "transport_health": transport_health,
        "offline_recovery": offline_recovery,
        "diagnostics": diagnostics,
        "warning_escalations": escalations,
        "connectivity_state": connectivity_state,
        "degraded_mode_active": degraded_mode,
        "passive_only": True,
    }


def _severity_rank(severity: str) -> int:
    # For sorting: info < low < medium < high < critical
    order = {"info": 0, "low": 1, "medium": 2, "high": 3, "critical": 4}
    return order.get(severity, 0)
