/**
 * Regression tests for the per-model size validator in imageTool.
 *
 * Motivation: an agent hit "Width 1536 out of range" when requesting
 * 1536x1024 on gpt-image-1.5 (where that size IS valid) — because the
 * validator was hardcoded to Flux constraints and didn't know the
 * effective model. It also rejected `size: "auto"` despite the docs
 * saying it's valid, and failed to remap the `portrait` preset when
 * the tool auto-switched to gpt-image-1.5 (transparency=true).
 *
 * These tests lock the fixed behaviour end-to-end:
 *   - Valid gpt-image-1.5 sizes accepted.
 *   - Flux out-of-range errors still fire for Flux.
 *   - Errors name the model + list valid sizes + hint at recovery.
 *   - The transparency/sourceImage auto-switch runs BEFORE validation.
 *   - Presets remap per model.
 *   - _translateImageError produces actionable text for moderation,
 *     size, and auth errors.
 */

import { describe, test, expect } from '@jest/globals';
import {
  resolveEffectiveImageModel,
  _getModelSizeRule,
  _translateImageError,
} from '../imageTool.js';

// ── resolveEffectiveImageModel ──────────────────────────────────────────

describe('resolveEffectiveImageModel', () => {
  test('returns explicit model when set', () => {
    expect(resolveEffectiveImageModel({ model: 'gpt-image-1.5' })).toBe('gpt-image-1.5');
    expect(resolveEffectiveImageModel({ model: 'Flux-1.1-pro' })).toBe('flux-1.1-pro');
  });

  test('auto-switches to gpt-image-1.5 when transparency=true', () => {
    expect(resolveEffectiveImageModel({ transparency: true })).toBe('gpt-image-1.5');
  });

  test('auto-switches to gpt-image-1.5 when sourceImage is provided', () => {
    expect(resolveEffectiveImageModel({ sourceImage: '/tmp/x.png' })).toBe('gpt-image-1.5');
  });

  test('returns "" when nothing forces a model (downstream will resolve)', () => {
    expect(resolveEffectiveImageModel({})).toBe('');
  });

  test('explicit "auto" is treated as "defer to downstream"', () => {
    expect(resolveEffectiveImageModel({ model: 'auto' })).toBe('');
  });
});

// ── _getModelSizeRule ───────────────────────────────────────────────────

describe('_getModelSizeRule', () => {
  test('gpt-image-1.5 gets the enum rule', () => {
    const { rule } = _getModelSizeRule('gpt-image-1.5');
    expect(rule.kind).toBe('enum');
    expect(rule.values).toContain('1024x1024');
    expect(rule.values).toContain('1024x1536');
    expect(rule.values).toContain('1536x1024');
    expect(rule.values).toContain('auto');
  });

  test('substring match — "gpt-image-1.5-preview" still picks enum', () => {
    const { rule } = _getModelSizeRule('gpt-image-1.5-preview');
    expect(rule.kind).toBe('enum');
  });

  test('flux variants get the range rule', () => {
    const { rule } = _getModelSizeRule('flux-1.1-pro');
    expect(rule.kind).toBe('range');
    expect(rule.min).toBe(256);
    expect(rule.max).toBe(1440);
    expect(rule.increment).toBe(32);
  });

  test('unknown model falls back to default (range)', () => {
    const { rule, modelKey } = _getModelSizeRule('completely-unknown-model');
    expect(rule.kind).toBe('range');
    expect(modelKey).toBe('default');
  });
});

// ── _translateImageError ────────────────────────────────────────────────

describe('_translateImageError', () => {
  test('moderation error — rewrites with rephrasing hint', () => {
    const msg = _translateImageError(
      new Error('HTTP 400: Bad Request - content_policy violation'),
      { prompt: 'blood', model: 'gpt-image-1.5' }
    );
    expect(msg).toMatch(/content moderation/i);
    expect(msg).toMatch(/Rephrase/i);
    expect(msg).toContain('gpt-image-1.5');
    // Original text preserved for auditability
    expect(msg).toContain('content_policy violation');
  });

  test('size error — lists valid sizes for gpt-image-1.5', () => {
    const msg = _translateImageError(
      new Error('Invalid image size: must be one of 1024x1024, 1024x1536, 1536x1024'),
      { size: '1280x720', transparency: true }
    );
    expect(msg).toMatch(/size "1280x720" not accepted/);
    expect(msg).toContain('gpt-image-1.5');
    expect(msg).toContain('1024x1024');
    expect(msg).toContain('1024x1536');
    expect(msg).toContain('1536x1024');
  });

  test('size error — Flux: range hint', () => {
    const msg = _translateImageError(
      new Error('out of range'),
      { size: '2000x2000', model: 'flux-1.1-pro' }
    );
    expect(msg).toMatch(/flux/);
    expect(msg).toMatch(/256-1440/);
    expect(msg).toMatch(/multiples of 32/);
  });

  test('auth error — flags non-retryability', () => {
    const msg = _translateImageError(new Error('401 Unauthorized'), { model: 'gpt-image-1.5' });
    expect(msg).toMatch(/authentication/i);
    expect(msg).toMatch(/Retrying.*will likely fail/i);
  });

  test('unknown error — still includes model + size context', () => {
    const msg = _translateImageError(new Error('network wobble'), { model: 'flux-1.1-pro', size: '1024x1024' });
    expect(msg).toContain('flux-1.1-pro');
    expect(msg).toContain('1024x1024');
    expect(msg).toContain('network wobble');
  });
});
