import test from 'node:test';
import assert from 'node:assert/strict';

import {
  bucketForBristolType,
  buildTimmySummary,
  detectUrgentFlags,
  detectUrgentText,
  exportLedger,
  hasUrgentLedgerContext,
  photoQualityMessage,
  sanitizeEntry,
} from '../src/domain.js';

test('maps Bristol types to clinically grounded buckets', () => {
  assert.equal(bucketForBristolType(1), 'constipation');
  assert.equal(bucketForBristolType(2), 'constipation');
  assert.equal(bucketForBristolType(3), 'typical');
  assert.equal(bucketForBristolType(4), 'typical');
  assert.equal(bucketForBristolType(5), 'loose');
  assert.equal(bucketForBristolType(7), 'loose');
  assert.equal(bucketForBristolType(0), 'unknown');
});

test('escalates reported blood, black stool, severe pain, vomiting, fever, or inability to pass gas', () => {
  const result = detectUrgentFlags({
    blood: true,
    blackOrDarkRed: false,
    severePain: true,
    vomiting: false,
    fever: false,
    cannotPassGas: false,
  });
  assert.equal(result.urgent, true);
  assert.deepEqual(result.flags, ['blood', 'severePain']);
  assert.match(result.message, /medical care/i);
});

test('does not invent reassurance when no urgent flags are reported', () => {
  const result = detectUrgentFlags({});
  assert.equal(result.urgent, false);
  assert.deepEqual(result.flags, []);
  assert.match(result.message, /not a diagnosis/i);
});

test('detects common urgent symptom language without matching unrelated blood wording', () => {
  for (const message of [
    'I have rectal bleeding',
    'There is blood in my stool',
    'My stool is black',
    'I have severe stomach pain',
    'I am throwing up and have a fever',
    'I am unable to pass gas',
  ]) assert.equal(detectUrgentText(message).urgent, true, message);
  assert.equal(detectUrgentText('My blood pressure was checked').urgent, false);
});

test('detects urgent flags or language in confirmed ledger context', () => {
  assert.equal(hasUrgentLedgerContext([{ symptoms: { cannotPassGas: true }, note: '' }]), true);
  assert.equal(hasUrgentLedgerContext([{ symptoms: {}, note: 'I have rectal bleeding' }]), true);
  assert.equal(hasUrgentLedgerContext([{ symptoms: {}, note: 'ordinary entry' }]), false);
});

test('Timmy summary reports patterns without clearing food or diagnosing disease', () => {
  const entries = [
    { bristolType: 3, occurredAt: '2026-08-15T08:00:00.000Z' },
    { bristolType: 4, occurredAt: '2026-08-16T08:00:00.000Z' },
    { bristolType: 6, occurredAt: '2026-08-17T08:00:00.000Z' },
  ];
  const summary = buildTimmySummary(entries);
  assert.match(summary, /3 logs/);
  assert.match(summary, /2 typical/);
  assert.doesNotMatch(summary, /safe|diagnos|Taco Bell|clear/i);
});

test('sanitizes a user entry to the MVP data contract', () => {
  const entry = sanitizeEntry({
    id: 'abc',
    occurredAt: '2026-08-17T12:00:00.000Z',
    bristolType: 4,
    color: 'brown',
    urgency: 2,
    discomfort: 1,
    note: 'After lunch',
    photoDataUrl: 'data:image/jpeg;base64,abc',
    unexpected: 'drop me',
  });
  assert.deepEqual(Object.keys(entry).sort(), [
    'bristolType', 'color', 'discomfort', 'id', 'note', 'occurredAt',
    'photoDataUrl', 'symptoms', 'urgency'
  ].sort());
  assert.equal(entry.unexpected, undefined);
});

test('photo quality guidance is deterministic and does not claim visual diagnosis', () => {
  assert.match(photoQualityMessage({ width: 300, height: 300, brightness: 0.5 }), /closer/i);
  assert.match(photoQualityMessage({ width: 1200, height: 900, brightness: 0.02 }), /light/i);
  assert.match(photoQualityMessage({ width: 1200, height: 900, brightness: 0.5 }), /review/i);
  assert.doesNotMatch(photoQualityMessage({ width: 1200, height: 900, brightness: 0.5 }), /type [1-7]|disease|diagnos/i);
});

test('export ledger is portable JSON with version and entries', () => {
  const text = exportLedger([{ id: 'a', bristolType: 4 }], '2026-08-18T00:00:00.000Z');
  const parsed = JSON.parse(text);
  assert.equal(parsed.schemaVersion, 1);
  assert.equal(parsed.exportedAt, '2026-08-18T00:00:00.000Z');
  assert.equal(parsed.entries.length, 1);
});
