/**
 * AI agent registry - picks implementation based on GOOGLE_API_KEY availability.
 *
 * When GOOGLE_API_KEY is present in the runtime env, real Gemini 2.0 Flash
 * agents are used. When the key is absent (local dev without credentials),
 * stub agents are returned as a safe fallback so the app still boots.
 *
 * Usage:
 *   const agents = getAiAgents(env);
 *   const result = await agents.imageApproval.reviewUploadedImage({ ... });
 */

import type { ImageApprovalAgent } from './types.js';
import type { ReviewRemovalPrescoringAgent } from './types.js';
import type { VendorViolationFlagAgent } from './types.js';
import type { SupportAgent } from './types.js';
import { StubImageApprovalAgent } from './stubs/image-approval.js';
import { StubReviewRemovalPrescoringAgent } from './stubs/review-removal-prescoring.js';
import { StubVendorViolationFlagAgent } from './stubs/vendor-violation-flag.js';
import { GeminiImageApprovalAgent } from './agents/image-approval.js';
import { GeminiReviewRemovalPrescoringAgent } from './agents/review-removal-prescoring.js';
import { GeminiVendorViolationFlagAgent } from './agents/vendor-violation-flag.js';
import { GeminiSupportAgent } from './agents/support/agent.js';
import { geminiProvider } from './providers/gemini.js';
import { requireConfiguredLlmModel } from './model-config.js';

// ─── Error thrown when support agent is requested but key is missing ──────────

/**
 * Thrown by callers that explicitly require the support agent but find it absent.
 * Callers should handle this by degrading to human escalation.
 */
export class SupportAgentUnavailableError extends Error {
  constructor() {
    super(
      'SupportAgent is unavailable: GOOGLE_API_KEY is not set. ' +
        'Degrade by escalating to human review.',
    );
    this.name = 'SupportAgentUnavailableError';
  }
}

export interface AiAgents {
  imageApproval: ImageApprovalAgent;
  reviewRemoval: ReviewRemovalPrescoringAgent;
  vendorViolation: VendorViolationFlagAgent;
  /** Present only when GOOGLE_API_KEY is set. */
  support?: SupportAgent;
}

export interface Env {
  GOOGLE_API_KEY?: string;
  /** @deprecated Use GOOGLE_API_KEY. AI_BACKEND is no longer consulted. */
  AI_BACKEND?: string;
}

/**
 * Returns real Gemini-backed agents when GOOGLE_API_KEY is present,
 * otherwise falls back to stubs (conservative safe defaults).
 *
 * @param env   - Runtime environment bindings (must have GOOGLE_API_KEY for real agents)
 * @param model - Gemini model ID, e.g. "gemini-2.0-flash-preview". Loaded from
 *                system_config.llm_model at call time.
 *
 * Set the key via: pnpm cf:secret GOOGLE_API_KEY
 */
export function getAiAgents(env: Env, model: string): AiAgents {
  if (env.GOOGLE_API_KEY) {
    model = requireConfiguredLlmModel(model, 'AI registry');
    const creds = { apiKey: env.GOOGLE_API_KEY };
    return {
      imageApproval: new GeminiImageApprovalAgent(geminiProvider, creds, model),
      reviewRemoval: new GeminiReviewRemovalPrescoringAgent(geminiProvider, creds, model),
      vendorViolation: new GeminiVendorViolationFlagAgent(geminiProvider, creds, model),
      support: new GeminiSupportAgent(geminiProvider, creds, model),
    };
  }

  // No API key — fall back to stubs for image/review/violation (safe conservative defaults).
  // Support agent has NO stub — it is simply absent. Callers that need it must handle
  // absence via SupportAgentUnavailableError (see above).
  return {
    imageApproval: new StubImageApprovalAgent(),
    reviewRemoval: new StubReviewRemovalPrescoringAgent(),
    vendorViolation: new StubVendorViolationFlagAgent(),
    // support: intentionally absent — no stub
  };
}
