import { describe, it, expect, vi } from 'vitest';
import { classifyStatus } from '../../src/main/ai/classifyStatus';
import type { InferenceProvider } from '../../src/main/ai/InferenceProvider';

function makeProvider(generateRaw?: (p: string) => Promise<string>): InferenceProvider {
  return {
    name: 'mock',
    generate: vi.fn(async () => {
      throw new Error('not used');
    }),
    healthCheck: vi.fn(async () => ({ ok: true })),
    ...(generateRaw !== undefined ? { generateRaw } : {})
  } as InferenceProvider;
}

describe('classifyStatus', () => {
  it('parses recommended status and rationale from valid AI response', async () => {
    const provider = makeProvider(
      vi.fn(async () => '{"recommended":"completed","rationale":"처리됨"}')
    );
    const r = await classifyStatus({
      provider,
      rawText: 't',
      summary: '',
      reason: '결재 끝'
    });
    expect(r.recommended).toBe('completed');
    expect(r.rationale).toBe('처리됨');
  });

  it('falls back to archived on parse failure (invalid JSON)', async () => {
    const provider = makeProvider(vi.fn(async () => 'not json'));
    const r = await classifyStatus({
      provider,
      rawText: 't',
      summary: '',
      reason: 'r'
    });
    expect(r.recommended).toBe('archived');
    expect(r.rationale).toMatch(/판단 실패|보관/);
  });

  it('falls back to archived on invalid status value', async () => {
    const provider = makeProvider(
      vi.fn(async () => '{"recommended":"unknown","rationale":"x"}')
    );
    const r = await classifyStatus({
      provider,
      rawText: 't',
      summary: '',
      reason: 'r'
    });
    expect(r.recommended).toBe('archived');
  });

  it('handles provider throw', async () => {
    const provider = makeProvider(
      vi.fn(async () => {
        throw new Error('network');
      })
    );
    const r = await classifyStatus({
      provider,
      rawText: 't',
      summary: '',
      reason: 'r'
    });
    expect(r.recommended).toBe('archived');
    expect(r.rationale).toMatch(/판단 실패|보관/);
  });

  it('falls back when provider lacks generateRaw method', async () => {
    const provider = makeProvider();
    const r = await classifyStatus({
      provider,
      rawText: 't',
      summary: '',
      reason: 'r'
    });
    expect(r.recommended).toBe('archived');
    expect(r.rationale).toMatch(/판단 실패|보관/);
  });

  it('substitutes empty inputs with placeholder text in prompt', async () => {
    const generateRaw = vi.fn(
      async (_p: string) => '{"recommended":"archived","rationale":"ok"}'
    );
    const provider = makeProvider(generateRaw);
    await classifyStatus({ provider, rawText: '', summary: '', reason: '' });
    const prompt = generateRaw.mock.calls[0]?.[0] ?? '';
    expect(prompt).toContain('(빈 메모)');
    expect(prompt).toContain('(요약 없음)');
    expect(prompt).toContain('(사유 없음)');
  });

  it('rationale defaults to empty string when missing/non-string', async () => {
    const provider = makeProvider(
      vi.fn(async () => '{"recommended":"completed"}')
    );
    const r = await classifyStatus({
      provider,
      rawText: 't',
      summary: '',
      reason: 'r'
    });
    expect(r.recommended).toBe('completed');
    expect(r.rationale).toBe('');
  });
});
