/**
 * Context Hygiene — "The Fresh Start Rule"
 * 
 * Detects when an agent's context window is bloated and forces
 * a clean checkpoint + restart instead of degraded operation.
 * 
 * Reference: Nate B Jones — "5 Management Skills for AI Agent Builders"
 * Skill #2: Know When to Start Fresh
 */

export interface SessionState {
  sessionId: string;
  agentId: string;
  startedAt: Date;
  tokenCount: number;
  taskCount: number;
  lastCheckpointAt: Date | null;
  checkpointCount: number;
}

export interface ContextCheck {
  healthy: boolean;
  tokensUsed: number;
  tokenBudget: number;
  utilizationPercent: number;
  sessionAgeMinutes: number;
  action: 'continue' | 'checkpoint_and_restart' | 'force_restart';
  reason?: string;
}

/** Standing Order 4.1: Context budget of 80,000 tokens */
const TOKEN_BUDGET = 80_000;
/** Standing Order 4.2: 75% threshold triggers checkpoint */
const CHECKPOINT_THRESHOLD = 0.75;
/** Standing Order 4.3: Max session duration 30 minutes */
const MAX_SESSION_MINUTES = 30;
/** Emergency threshold — force immediate restart */
const EMERGENCY_THRESHOLD = 0.95;

/**
 * Check if the current session needs a context refresh.
 * 
 * Standing Order 4.2: "When context exceeds 60,000 tokens (75%),
 * summarize progress, create a checkpoint, start a new scoped session."
 */
export function checkContextHealth(session: SessionState): ContextCheck {
  const utilizationPercent = (session.tokenCount / TOKEN_BUDGET) * 100;
  const sessionAgeMinutes = (Date.now() - session.startedAt.getTime()) / 60_000;

  // Emergency: context is nearly full
  if (session.tokenCount >= TOKEN_BUDGET * EMERGENCY_THRESHOLD) {
    return {
      healthy: false,
      tokensUsed: session.tokenCount,
      tokenBudget: TOKEN_BUDGET,
      utilizationPercent,
      sessionAgeMinutes,
      action: 'force_restart',
      reason: `Context at ${utilizationPercent.toFixed(0)}% capacity — force restart to prevent degradation`,
    };
  }

  // Warning: checkpoint threshold reached
  if (session.tokenCount >= TOKEN_BUDGET * CHECKPOINT_THRESHOLD) {
    return {
      healthy: false,
      tokensUsed: session.tokenCount,
      tokenBudget: TOKEN_BUDGET,
      utilizationPercent,
      sessionAgeMinutes,
      action: 'checkpoint_and_restart',
      reason: `Context at ${utilizationPercent.toFixed(0)}% — checkpoint and start fresh session`,
    };
  }

  // Time-based limit
  if (sessionAgeMinutes > MAX_SESSION_MINUTES) {
    return {
      healthy: false,
      tokensUsed: session.tokenCount,
      tokenBudget: TOKEN_BUDGET,
      utilizationPercent,
      sessionAgeMinutes,
      action: 'checkpoint_and_restart',
      reason: `Session running for ${sessionAgeMinutes.toFixed(0)} minutes (max ${MAX_SESSION_MINUTES}) — time to checkpoint`,
    };
  }

  return {
    healthy: true,
    tokensUsed: session.tokenCount,
    tokenBudget: TOKEN_BUDGET,
    utilizationPercent,
    sessionAgeMinutes,
    action: 'continue',
  };
}

/**
 * Generate a session summary for handoff to a fresh context.
 * This ensures the new session has enough info to continue.
 */
export function generateSessionSummary(session: SessionState & {
  completedTasks: string[];
  pendingTasks: string[];
  keyDecisions: string[];
  warnings: string[];
}): string {
  return [
    '=== SESSION HANDOFF SUMMARY ===',
    `Session: ${session.sessionId}`,
    `Agent: ${session.agentId}`,
    `Duration: ${((Date.now() - session.startedAt.getTime()) / 60_000).toFixed(1)} minutes`,
    `Tokens used: ${session.tokenCount.toLocaleString()} / ${TOKEN_BUDGET.toLocaleString()}`,
    `Checkpoints: ${session.checkpointCount}`,
    '',
    '--- Completed Tasks ---',
    ...session.completedTasks.map(t => `✅ ${t}`),
    '',
    '--- Pending Tasks ---',
    ...session.pendingTasks.map(t => `⏳ ${t}`),
    '',
    '--- Key Decisions ---',
    ...session.keyDecisions.map(d => `📌 ${d}`),
    '',
    ...(session.warnings.length > 0
      ? ['--- Warnings ---', ...session.warnings.map(w => `⚠️ ${w}`)]
      : []),
    '',
    '=== END SUMMARY ===',
  ].join('\n');
}

/**
 * Estimate token count for a message or payload.
 * Uses a rough 4 chars = 1 token approximation.
 */
export function estimateTokens(text: string): number {
  return Math.ceil(text.length / 4);
}
