import test from 'node:test';
import assert from 'node:assert/strict';
import { analyzePhoto } from '../src/vision-service.js';

test('sends a bounded structured request to the configured provider and validates its response', async () => {
  let captured;
  const fetchImpl = async (url, options) => {
    captured = { url, options };
    return {
      ok: true,
      json: async () => ({ choices: [{ message: { content: JSON.stringify({
        isStool: true, bristolType: 4, color: 'brown', confidence: 0.81,
        imageQuality: 'good', observations: 'Smooth and formed.'
      }) } }] }),
    };
  };
  const result = await analyzePhoto({
    payload: { imageDataUrl: 'data:image/jpeg;base64,YQ==', consent: true },
    fetchImpl,
    config: { baseUrl: 'http://127.0.0.1:8645/v1', apiKey: 'secret', model: 'vision-model' },
  });
  assert.equal(result.status, 'suggestion');
  assert.equal(result.bristolType, 4);
  assert.equal(captured.url, 'http://127.0.0.1:8645/v1/chat/completions');
  assert.equal(captured.options.headers.authorization, 'Bearer secret');
  assert.doesNotMatch(JSON.stringify(result), /secret/);
});

test('fails closed when the provider is unavailable or malformed', async () => {
  await assert.rejects(() => analyzePhoto({
    payload: { imageDataUrl: 'data:image/jpeg;base64,YQ==', consent: true },
    fetchImpl: async () => ({ ok: false, status: 503, text: async () => 'upstream detail' }),
    config: { baseUrl: 'http://localhost/v1', apiKey: 'x', model: 'm' },
  }), /temporarily unavailable/i);
  await assert.rejects(() => analyzePhoto({
    payload: { imageDataUrl: 'data:image/jpeg;base64,YQ==', consent: true },
    fetchImpl: async () => ({ ok: true, json: async () => ({ choices: [] }) }),
    config: { baseUrl: 'http://localhost/v1', apiKey: 'x', model: 'm' },
  }), /invalid/i);
});

test('requires an http(s) provider URL and never accepts credentials from the browser payload', async () => {
  await assert.rejects(() => analyzePhoto({
    payload: { imageDataUrl: 'data:image/jpeg;base64,YQ==', consent: true, apiKey: 'browser-secret' },
    fetchImpl: async () => { throw new Error('must not call'); },
    config: { baseUrl: 'file:///tmp/provider', apiKey: 'server-secret', model: 'm' },
  }), /provider URL/i);
});
