import { describe, expect, it } from 'vitest';
import { classifySyncResult, errorSummary } from './sync-result';

describe('classifySyncResult', () => {
  const baseResult = {
    scheduleCount: 10,
    syncedItems: 50,
    skippedNoMapping: 0,
    failedBatchCount: 0,
    failedItems: 0,
    errors: [] as string[],
  };

  it('returns success when no failures', () => {
    const result = classifySyncResult(baseResult);
    expect(result.hasFailure).toBe(false);
    expect(result.level).toBe('success');
    expect(result.message).toContain('同步完成');
    expect(result.message).toContain('50');
  });

  it('returns warning when partial failure (some synced, some failed)', () => {
    const result = classifySyncResult({
      ...baseResult,
      syncedItems: 30,
      failedBatchCount: 2,
      failedItems: 20,
      errors: ['err1', 'err2'],
    });
    expect(result.hasFailure).toBe(true);
    expect(result.level).toBe('warning');
    expect(result.message).toContain('部分失败');
    expect(result.message).toContain('30');
    expect(result.message).toContain('20');
  });

  it('returns error when total failure (nothing synced)', () => {
    const result = classifySyncResult({
      ...baseResult,
      syncedItems: 0,
      failedBatchCount: 1,
      failedItems: 50,
      errors: ['全部失败'],
    });
    expect(result.hasFailure).toBe(true);
    expect(result.level).toBe('error');
    expect(result.message).toContain('全部写入失败');
    expect(result.message).toContain('50');
  });

  it('classifies attendance group failure as failure, not success', () => {
    const result = classifySyncResult({
      ...baseResult,
      syncedItems: 45,
      failedBatchCount: 1,
      failedItems: 5,
      errors: ['考勤组 排课_强化班 创建/更新失败: permission denied'],
    });
    expect(result.hasFailure).toBe(true);
    expect(result.level).toBe('warning');
    expect(result.message).toContain('部分失败');
    // must NOT be success level
    expect(result.level).not.toBe('success');
  });

  it('returns error when all shifts failed (errors present, nothing synced)', () => {
    const result = classifySyncResult({
      ...baseResult,
      syncedItems: 0,
      failedBatchCount: 2,
      failedItems: 10,
      errors: [
        '创建班次 排课_09:00-11:00 失败: permission denied',
        '创建班次 排课_14:00-16:00 失败: permission denied',
      ],
    });
    expect(result.hasFailure).toBe(true);
    expect(result.level).toBe('error');
    expect(result.message).toContain('全部写入失败');
  });

  it('returns warning when errors-only with some syncedItems (no failedBatchCount)', () => {
    // Edge case: errors from shift creation that don't bump failedBatchCount
    // but do leave errors[] non-empty, yet some items synced from other classes
    const result = classifySyncResult({
      ...baseResult,
      syncedItems: 30,
      failedBatchCount: 0,
      failedItems: 0,
      errors: ['创建班次 排课_09:00-11:00 失败: network error'],
    });
    expect(result.hasFailure).toBe(true);
    expect(result.level).toBe('warning');
    expect(result.message).toContain('部分失败');
  });

  it('returns error when errors-only with zero syncedItems (no failedBatchCount)', () => {
    const result = classifySyncResult({
      ...baseResult,
      syncedItems: 0,
      failedBatchCount: 0,
      failedItems: 0,
      errors: ['创建班次 排课_09:00-11:00 失败: permission denied'],
    });
    expect(result.hasFailure).toBe(true);
    expect(result.level).toBe('error');
    expect(result.message).toContain('全部写入失败');
  });
});

describe('errorSummary', () => {
  it('returns all errors when 5 or fewer', () => {
    const errors = ['e1', 'e2', 'e3'];
    expect(errorSummary(errors)).toEqual(['e1', 'e2', 'e3']);
  });

  it('returns first 5 when more than 5', () => {
    const errors = ['e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7'];
    expect(errorSummary(errors)).toEqual(['e1', 'e2', 'e3', 'e4', 'e5']);
  });

  it('returns empty for empty errors', () => {
    expect(errorSummary([])).toEqual([]);
  });
});
