import type { CandidataImagen, EvaluacionVision } from './tipos';
import { calcularScore, esAprobable, seleccionarParaGuardar, UMBRAL_GUARDAR } from './puntaje';

const ev = (o: Partial<EvaluacionVision> = {}): EvaluacionVision => ({
  coincide: 0.9,
  fondo_blanco: true,
  marca_agua: false,
  calidad: 0.8,
  ...o,
});
const cand = (vision?: EvaluacionVision, extra: Partial<CandidataImagen> = {}): CandidataImagen => ({
  url: `https://x/${Math.random()}`,
  dominio: 'x',
  titulo: '',
  ancho: 800,
  alto: 800,
  prefiltro: 0,
  vision,
  score: vision ? calcularScore(vision) : undefined,
  ...extra,
});

describe('calcularScore', () => {
  it('pondera coincidencia 60 %, fondo 25 %, calidad 15 % y castiga marca de agua', () => {
    expect(calcularScore(ev())).toBeCloseTo(0.9 * 0.6 + 0.25 + 0.8 * 0.15, 5);
    expect(calcularScore(ev({ marca_agua: true }))).toBeCloseTo(0.9 * 0.6 + 0.25 + 0.8 * 0.15 - 0.5, 5);
    expect(calcularScore(ev({ fondo_blanco: false }))).toBeCloseTo(0.9 * 0.6 + 0.8 * 0.15, 5);
  });
  it('acota el resultado a [0, 1]', () => {
    expect(calcularScore(ev({ coincide: 0, calidad: 0, fondo_blanco: false, marca_agua: true }))).toBe(0);
    expect(calcularScore(ev({ coincide: 1, calidad: 1 }))).toBe(1);
  });
});

describe('esAprobable', () => {
  it('exige coincide ≥ 0,7, fondo blanco y sin marca de agua', () => {
    expect(esAprobable(ev())).toBe(true);
    expect(esAprobable(ev({ coincide: 0.69 }))).toBe(false);
    expect(esAprobable(ev({ fondo_blanco: false }))).toBe(false);
    expect(esAprobable(ev({ marca_agua: true }))).toBe(false);
  });
  it('el logo del fabricante no cuenta: solo marca_agua=true rechaza', () => {
    expect(esAprobable(ev({ nota: 'logo Samsung visible' }))).toBe(true);
  });
});

describe('seleccionarParaGuardar', () => {
  it('descarta sin visión, descartadas y bajo el umbral; ordena por score; corta en 5', () => {
    const buenas = [0.95, 0.9, 0.85, 0.8, 0.75, 0.7].map((c) => cand(ev({ coincide: c })));
    const baja = cand(ev({ coincide: 0.1, fondo_blanco: false, calidad: 0.1 }));
    const sinVision = cand(undefined);
    const descartada = cand(ev(), { descarte: 'duplicada' });
    const res = seleccionarParaGuardar([baja, sinVision, buenas[3], descartada, buenas[0], buenas[5], buenas[1], buenas[2], buenas[4]]);
    expect(res).toHaveLength(5);
    expect(res.map((c) => c.vision!.coincide)).toEqual([0.95, 0.9, 0.85, 0.8, 0.75]);
    expect(res.every((c) => (c.score ?? 0) >= UMBRAL_GUARDAR)).toBe(true);
  });
});
