/**
 * Sequence Detection — detects inefficient multi-call patterns.
 */

import type { HintRule, HintContext } from '../hint-engine';

function lastToolWas(ctx: HintContext, name: string): boolean {
  return ctx.recentCalls.length > 0 && ctx.recentCalls[0].toolName === name;
}

/**
 * True when the most recent call's args carried a non-'none' `returnAfterState`.
 * Such calls already inlined a fresh page snapshot in their response, which is
 * a stronger signal than a follow-up read_page would be. See issue #845.
 */
function lastCallCarriedSnapshot(ctx: HintContext): boolean {
  if (ctx.recentCalls.length === 0) return false;
  const ras = ctx.recentCalls[0].args?.returnAfterState;
  return ras === 'ax' || ras === 'dom';
}

export const sequenceDetectionRules: HintRule[] = [
  {
    name: 'post-scroll-click',
    priority: 299, // Just before existing sequence rules (300-304)
    maxSeverity: 'warning',
    match(ctx) {
      if (ctx.toolName !== 'computer') return null;

      // Check if current call is a coordinate click
      if (!/Clicked at/.test(ctx.resultText)) return null;

      // Only check the most recent call for explicit scroll actions
      if (ctx.recentCalls.length === 0) return null;
      const prev = ctx.recentCalls[0];

      if (
        prev.toolName === 'computer' &&
        (prev.args?.action === 'scroll' || prev.args?.action === 'scroll_to')
      ) {
        return (
          'Hint: Previous action caused scroll — coordinates from before the scroll may be stale. ' +
          'Use read_page to get fresh element positions, or use ref-based click.'
        );
      }

      return null;
    },
  },
  {
    name: 'navigate-to-login',
    priority: 150,  // Between error-recovery (100-108) and pagination (190)
    // No maxSeverity cap — genuine auth detection, critical escalation is appropriate
    match(ctx) {
      if (ctx.toolName !== 'navigate') return null;
      if (ctx.isError) return null;  // isError paths already carry inline guidance
      // Check for the structured authRedirect field from navigate response,
      // not broad regex matching which causes false positives on pages
      // containing "auth" keywords (e.g., Cloudflare Turnstile, OAuth docs).
      if (/"authRedirect"\s*:\s*true/i.test(ctx.resultText)) {
        return 'Hint: Authentication required — login page detected. ' +
          'The user must be logged in via their Chrome profile. ' +
          'STOP trying to authenticate programmatically. ' +
          'Ask the user to log in manually in Chrome, then retry.';
      }
      return null;
    },
  },
  {
    name: 'navigate-then-screenshot',
    priority: 302,
    maxSeverity: 'info',
    match(ctx) {
      if (ctx.toolName !== 'computer') return null;
      if (!ctx.resultText.includes('screenshot')) return null;
      if (!lastToolWas(ctx, 'navigate')) return null;
      return 'Hint: Page may not be loaded. Add wait_for before screenshot.';
    },
  },
  {
    name: 'modal-close-failure',
    priority: 303,
    maxSeverity: 'warning',
    match(ctx) {
      if (ctx.toolName !== 'find' && ctx.toolName !== 'read_page') return null;
      if (!lastToolWas(ctx, 'interact')) return null;
      // If the prior interact already inlined a snapshot via returnAfterState,
      // the agent has already seen the post-action DOM and the follow-up
      // read_page is redundant — not a sign of a stuck modal. See #845.
      if (lastCallCarriedSnapshot(ctx)) return null;
      if (/modal|overlay|dialog|backdrop|popup|drawer/i.test(ctx.resultText)) {
        return 'Hint: Modal may still be open. Try Escape key via computer(action:"key", text:"Escape") or javascript_tool to remove overlay.';
      }
      return null;
    },
  },
  {
    name: 'navigate-to-demo',
    priority: 304,
    maxSeverity: 'info',
    match(ctx) {
      if (ctx.toolName !== 'navigate') return null;
      if (ctx.isError) return null;
      if (/demo\.|staging\.|sandbox\.|test\.|localhost|127\.0\.0\.1/i.test(ctx.resultText)) {
        return 'Hint: URL appears to be a non-production environment (demo/staging). Verify this is the intended target.';
      }
      return null;
    },
  },
];
