/**
 * @fileoverview Status mapping utilities.
 *
 * Translates OpenClaw Gateway session statuses and timestamps
 * into the AgentStatus enum and elapsed-time strings used by AgentCardData.
 */

import { AgentStatus, AgentLifecycleStatus, OpenClawSession, AGENT_ROLES } from '../models/types';

/**
 * Map an OpenClaw session status to an AgentStatus for the UI.
 *
 * Mapping logic:
 *   - "running" or "streaming" with no tokens yet → ACTIVE (agent processing turn)
 *   - "streaming" with output tokens → THINKING (LLM call in flight)
 *   - "done" → IDLE (agent finished, waiting for next input)
 *   - "error" → ERROR
 *   - "aborted" → IDLE (abort = intentional stop, not an error)
 *   - null/undefined → IDLE (no active session = idle)
 */
export function mapSessionStatusToAgentStatus(sessionStatus?: string | null): AgentStatus {
  switch (sessionStatus) {
    case 'running':
      return 'active';
    case 'streaming':
      return 'thinking';
    case 'done':
      return 'idle';
    case 'error':
      return 'error';
    case 'aborted':
      return 'idle';
    default:
      return 'idle';
  }
}

/**
 * Determine lifecycle status for an agent that may not have an active session.
 * If no session exists, the agent is considered "offline".
 */
export function determineLifecycleStatus(
  session?: OpenClawSession | null
): AgentLifecycleStatus {
  if (!session) return 'offline';
  return mapSessionStatusToAgentStatus(session.status);
}

/**
 * Convert an OpenClaw session to the lifecycle status used by the UI.
 * Offline agents are presented as "idle" to the UI.
 */
export function lifecycleToUiStatus(lifecycle: AgentLifecycleStatus): AgentStatus {
  return lifecycle === 'offline' ? 'idle' : lifecycle;
}

/**
 * Format elapsed time from a session's startedAt timestamp.
 * Returns a human-readable string like "04m 12s" or "1h 23m".
 *
 * If the session hasn't started or is done, returns undefined.
 */
export function formatElapsedTime(
  session?: OpenClawSession | null,
  nowMs?: number
): string | undefined {
  if (!session?.startedAt) return undefined;
  const endTime = session.endedAt || nowMs || Date.now();
  const elapsedMs = endTime - session.startedAt;
  if (elapsedMs < 0) return undefined;

  const totalSeconds = Math.floor(elapsedMs / 1000);
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;

  if (hours > 0) {
    return `${hours}h ${String(minutes).padStart(2, '0')}m`;
  }
  return `${String(minutes).padStart(2, '0')}m ${String(seconds).padStart(2, '0')}s`;
}

/**
 * Extract the channel name from a session key.
 * Session key format: "agent:<agentId>:<channel>:<kind>:<peerId>"
 * Or from the session's channel/origin fields.
 */
export function extractChannelFromSession(session: OpenClawSession): string {
  // Prefer explicit channel field
  if (session.channel && session.channel !== 'heartbeat') {
    return session.channel;
  }
  // Fall back to origin provider
  if (session.origin?.provider) {
    return session.origin.provider;
  }
  // Parse session key: "agent:otto:telegram:direct:8787451565"
  const parts = session.key.split(':');
  if (parts.length >= 3 && parts[0] === 'agent') {
    return parts[2];
  }
  return 'unknown';
}

/**
 * Extract the agent ID from a session key.
 * Session key format: "agent:<agentId>:..."
 */
export function extractAgentIdFromSessionKey(sessionKey: string): string {
  const parts = sessionKey.split(':');
  if (parts[0] === 'agent' && parts.length >= 2) {
    return parts[1];
  }
  return sessionKey;
}

/**
 * Get the role description for an agent ID.
 * Falls back to AGENT_ROLES map, then to a generic string.
 */
export function getAgentRole(agentId: string): string {
  return AGENT_ROLES[agentId] || `${agentId} Agent`;
}

/**
 * Estimate task progress based on session state.
 *
 * OpenClaw doesn't natively expose a 0–100 progress percentage.
 * We derive an approximation:
 *   - "running" session → 10–50% (early in the task, we don't know)
 *   - "streaming" → 60–90% (LLM is responding)
 *   - "done" → 100%
 *   - "error" → whatever progress was made before the error
 *
 * This is intentionally coarse. A future enhancement could parse
 * sub-agent progress or tool call completion ratios.
 */
export function estimateTaskProgress(session?: OpenClawSession | null): number | undefined {
  if (!session) return undefined;

  switch (session.status) {
    case 'running':
      return 25; // processing, early stage
    case 'streaming':
      return 75; // LLM responding
    case 'done':
      return 100;
    case 'error':
      return undefined; // unknown how far it got
    case 'aborted':
      return undefined;
    default:
      return undefined;
  }
}

/**
 * Derive a current-task description from session metadata.
 * Uses the session label (for cron sessions) or constructs a generic description.
 */
export function deriveCurrentTask(session?: OpenClawSession | null): string | undefined {
  if (!session) return undefined;

  // Cron sessions have a label
  if (session.label) return session.label;

  // Sessions with displayName that isn't generic
  if (session.displayName && session.displayName !== 'direct' && session.displayName !== 'heartbeat') {
    return session.displayName;
  }

  // Active sessions get a generic description
  if (session.status === 'running' || session.status === 'streaming') {
    return 'Processing task...';
  }

  return undefined;
}