/**
 * OCR Service Unit Tests
 * TDD: Test-Driven Development
 */

import { describe, it, expect } from '@jest/globals';
import { OCRService } from '../../../src/services/ocr.service';

describe('OCRService', () => {
  describe('shouldCreateDocument', () => {
    const defaultThreshold = 0.3;

    it('should create document when confidence > threshold', () => {
      // @ralph 这个测试是否清晰描述了决策逻辑？
      const result = OCRService.shouldCreateDocument(0.8, defaultThreshold);
      expect(result).toBe(true);
    });

    it('should not create document when confidence < threshold', () => {
      // @ralph 边界条件是否正确处理？
      const result = OCRService.shouldCreateDocument(0.2, defaultThreshold);
      expect(result).toBe(false);
    });

    it('should handle threshold boundary (>=)', () => {
      // @ralph 边界值处理是否明确？
      expect(OCRService.shouldCreateDocument(0.3, 0.3)).toBe(true);
      expect(OCRService.shouldCreateDocument(0.31, 0.3)).toBe(true);
      expect(OCRService.shouldCreateDocument(0.29, 0.3)).toBe(false);
    });

    it('should handle perfect confidence', () => {
      // @ralph 最佳情况是否考虑？
      const result = OCRService.shouldCreateDocument(1.0, defaultThreshold);
      expect(result).toBe(true);
    });

    it('should handle zero confidence', () => {
      // @ralph 最坏情况是否考虑？
      const result = OCRService.shouldCreateDocument(0.0, defaultThreshold);
      expect(result).toBe(false);
    });

    it('should handle negative confidence', () => {
      // @ralph 异常值是否处理？
      const result = OCRService.shouldCreateDocument(-0.1, defaultThreshold);
      expect(result).toBe(false);
    });

    it('should handle confidence > 1 (invalid)', () => {
      // @ralph 非法值是否处理？
      const result = OCRService.shouldCreateDocument(1.5, defaultThreshold);
      expect(result).toBe(false); // Should return false for invalid input
    });
  });

  describe('processingStatus', () => {
    it('should return pending for new upload', () => {
      // @ralph 初始状态是否正确？
      const status = OCRService.getInitialStatus();
      expect(status).toBe('pending');
    });

    it('should process image with provider', async () => {
      // @ralph 处理流程是否正确？
      const mockOCR = jest.fn().mockResolvedValue({ text: 'test', confidence: 0.9 });
      const result = await OCRService.process('image-id', mockOCR);

      expect(result.text).toBe('test');
      expect(result.confidence).toBe(0.9);
      expect(result.shouldCreateDocument).toBe(true);
    });
  });

  describe('error handling', () => {
    it('should handle OCR provider failure', async () => {
      // @ralph 失败处理是否完善？
      const mockOCR = jest.fn().mockRejectedValue(new Error('OCR failed'));

      await expect(OCRService.process('image-id', mockOCR)).rejects.toThrow('OCR failed');
    });

    it('should handle timeout', async () => {
      // @ralph 超时是否处理？
      const mockOCR = jest.fn().mockImplementation(() =>
        new Promise((resolve) => setTimeout(resolve, 10000))
      );

      await expect(
        OCRService.process('image-id', mockOCR, { timeout: 100 })
      ).rejects.toThrow('timeout');
    });

    it('should handle empty result', async () => {
      // @ralph 空结果是否处理？
      const mockOCR = jest.fn().mockResolvedValue({ text: '', confidence: 0 });

      const result = await OCRService.process('image-id', mockOCR);
      expect(result.text).toBe('');
      expect(result.shouldCreateDocument).toBe(false);
    });
  });

  describe('confidence validation', () => {
    it('should validate confidence range', () => {
      // @ralph 范围检查是否完整？
      expect(OCRService.isValidConfidence(0.5)).toBe(true);
      expect(OCRService.isValidConfidence(0)).toBe(true);
      expect(OCRService.isValidConfidence(1)).toBe(true);
      expect(OCRService.isValidConfidence(-0.1)).toBe(false);
      expect(OCRService.isValidConfidence(1.1)).toBe(false);
      expect(OCRService.isValidConfidence(NaN)).toBe(false);
    });
  });

  describe('retry logic', () => {
    it('should retry on transient failure', async () => {
      // @ralph 重试逻辑是否合理？
      const mockOCR = jest.fn()
        .mockRejectedValueOnce(new Error('network error'))
        .mockResolvedValueOnce({ text: 'retry success', confidence: 0.8 });

      const result = await OCRService.process('image-id', mockOCR, { retries: 1 });

      expect(mockOCR).toHaveBeenCalledTimes(2);
      expect(result.text).toBe('retry success');
    });

    it('should not retry on permanent failure', async () => {
      // @ralph 错误类型是否区分？
      const mockOCR = jest.fn()
        .mockRejectedValue(new Error('invalid image format'));

      await expect(
        OCRService.process('image-id', mockOCR, { retries: 2 })
      ).rejects.toThrow('invalid image format');
      expect(mockOCR).toHaveBeenCalledTimes(1); // No retry
    });

    it('should respect max retry limit', async () => {
      // @ralph 重试次数是否限制？
      const mockOCR = jest.fn()
        .mockRejectedValue(new Error('network error'));

      await expect(
        OCRService.process('image-id', mockOCR, { retries: 2 })
      ).rejects.toThrow('network error');
      expect(mockOCR).toHaveBeenCalledTimes(3); // initial + 2 retries
    });
  });
});
