from __future__ import annotations

import os
import time
from typing import Any, Callable, Dict, Optional


_PROCESS_SESSION_ID = os.environ.get("OASYCE_SESSION_ID") or (
    f"session-{int(time.time())}-{os.getpid()}"
)


def resolve_agent_id(default: str = "oasyce") -> str:
    return str(os.environ.get("OASYCE_AGENT_ID") or default or "oasyce").strip()


def resolve_session_id(default: Optional[str] = None) -> str:
    return str(default or os.environ.get("OASYCE_SESSION_ID") or _PROCESS_SESSION_ID).strip()


def _principal_summary(account_status: Dict[str, Any]) -> Dict[str, Any]:
    principal = dict(account_status.get("principal") or {})
    if principal:
        return principal
    account_id = str(account_status.get("account_address") or "").strip()
    delegate_id = str(account_status.get("device_id") or "").strip()
    return {
        "id": account_id,
        "carrier_type": "owner_account",
        "carrier_id": account_id,
        "delegate_type": "trusted_device",
        "delegate_id": delegate_id,
        "bridge_model": True,
    }


def build_runtime_identity(
    *,
    account_status: Dict[str, Any],
    default_agent_id: str = "oasyce",
    session_id: Optional[str] = None,
    source: str = "",
    include_session: bool = True,
) -> Dict[str, Any]:
    principal = _principal_summary(account_status)
    account_id = str(account_status.get("account_address") or "").strip()
    delegate_id = str(account_status.get("device_id") or "").strip()
    payload: Dict[str, Any] = {
        "principal": principal,
        "account": {
            "id": account_id,
            "type": "owner_account",
            "mode": str(account_status.get("account_mode") or "").strip(),
            "origin": str(account_status.get("account_origin") or "").strip(),
        },
        "delegate": {
            "id": delegate_id,
            "type": "trusted_device",
            "authorization_status": str(
                account_status.get("device_authorization_status") or ""
            ).strip(),
            "can_sign": bool(account_status.get("can_sign")),
        },
    }
    if include_session:
        payload["session"] = {
            "id": resolve_session_id(session_id),
            "agent_id": resolve_agent_id(default_agent_id),
            "source": source or default_agent_id,
        }
    return payload


def build_runtime_actor_trace(
    *,
    account_status: Dict[str, Any],
    default_agent_id: str = "oasyce",
    session_id: Optional[str] = None,
    source: str = "",
) -> Dict[str, Any]:
    runtime_identity = build_runtime_identity(
        account_status=account_status,
        default_agent_id=default_agent_id,
        session_id=session_id,
        source=source,
        include_session=True,
    )
    account = dict(runtime_identity.get("account") or {})
    delegate = dict(runtime_identity.get("delegate") or {})
    session = dict(runtime_identity.get("session") or {})
    return {
        "principal": dict(runtime_identity.get("principal") or {}),
        "account": account,
        "delegate": delegate,
        "session": session,
        "owner_account": str(account.get("id") or "").strip(),
        "device_id": str(delegate.get("id") or "").strip(),
        "agent_id": str(session.get("agent_id") or "").strip(),
        "session_id": str(session.get("id") or "").strip(),
        "source": str(session.get("source") or "").strip(),
    }


def normalize_runtime_actor(actor: Any) -> Optional[Dict[str, Any]]:
    if not isinstance(actor, dict):
        return None
    principal = dict(actor.get("principal") or {})
    account = dict(actor.get("account") or {})
    delegate = dict(actor.get("delegate") or {})
    session = dict(actor.get("session") or {})
    owner_account = str(actor.get("owner_account") or account.get("id") or "").strip()
    device_id = str(actor.get("device_id") or delegate.get("id") or "").strip()
    agent_id = str(actor.get("agent_id") or session.get("agent_id") or "").strip()
    session_id = str(actor.get("session_id") or session.get("id") or "").strip()
    source = str(actor.get("source") or session.get("source") or "").strip()
    principal_id = str(principal.get("id") or owner_account).strip()
    principal = {
        "id": principal_id,
        "carrier_type": str(principal.get("carrier_type") or "owner_account").strip(),
        "carrier_id": str(principal.get("carrier_id") or owner_account).strip(),
        "delegate_type": str(principal.get("delegate_type") or "trusted_device").strip(),
        "delegate_id": str(principal.get("delegate_id") or device_id).strip(),
        "bridge_model": bool(principal.get("bridge_model", bool(owner_account or device_id))),
    }
    account = {
        "id": owner_account,
        "type": str(account.get("type") or "owner_account").strip(),
        "mode": str(account.get("mode") or "").strip(),
        "origin": str(account.get("origin") or "").strip(),
    }
    delegate = {
        "id": device_id,
        "type": str(delegate.get("type") or "trusted_device").strip(),
        "authorization_status": str(delegate.get("authorization_status") or "").strip(),
        "can_sign": bool(delegate.get("can_sign")),
    }
    session = {
        "id": session_id,
        "agent_id": agent_id,
        "source": source,
    }
    if not any(
        (
            principal.get("id"),
            account.get("id"),
            delegate.get("id"),
            session.get("id"),
            session.get("agent_id"),
        )
    ):
        return None
    return {
        "principal": principal,
        "account": account,
        "delegate": delegate,
        "session": session,
        "owner_account": owner_account,
        "device_id": device_id,
        "agent_id": agent_id,
        "session_id": session_id,
        "source": source,
    }


def resolve_runtime_identity(
    *,
    status_reader: Optional[Callable[[], Dict[str, Any]]] = None,
    default_agent_id: str = "oasyce",
    session_id: Optional[str] = None,
    source: str = "",
    include_session: bool = True,
) -> Dict[str, Any]:
    if status_reader is None:
        from oasyce.account_state import build_account_status

        status_reader = build_account_status
    try:
        account_status = dict(status_reader() or {})
    except Exception:
        account_status = {}
    return build_runtime_identity(
        account_status=account_status,
        default_agent_id=default_agent_id,
        session_id=session_id,
        source=source,
        include_session=include_session,
    )


def resolve_runtime_actor_trace(
    *,
    status_reader: Optional[Callable[[], Dict[str, Any]]] = None,
    default_agent_id: str = "oasyce",
    session_id: Optional[str] = None,
    source: str = "",
) -> Dict[str, Any]:
    if status_reader is None:
        from oasyce.account_state import build_account_status

        status_reader = build_account_status
    try:
        account_status = dict(status_reader() or {})
    except Exception:
        account_status = {}
    return build_runtime_actor_trace(
        account_status=account_status,
        default_agent_id=default_agent_id,
        session_id=session_id,
        source=source,
    )
