// #region TranslationPreviewComponentTest:Module [TYPE Function]
// @PURPOSE: Contract-focused unit tests for TranslationPreview.svelte component.
// @LAYER UI
// @RELATION DEPENDS_ON -> [EXT:spec:TranslationPreview:Component]

import { describe, it, expect, vi, beforeEach } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';

const COMPONENT_PATH = path.resolve(
  process.cwd(),
  'src/lib/components/translate/TranslationPreview.svelte'
);

// #region TestComponentFileExists:Class [TYPE Function]
// @PURPOSE: Verify the TranslationPreview component file exists.
describe('TranslationPreview Component', () => {
  // #region test_component_file_exists:Function [TYPE Function]
  // @PURPOSE: Verify component file exists and has required contracts
  it('contains required UX tags and contract annotations', () => {
    const source = fs.readFileSync(COMPONENT_PATH, 'utf-8');

    expect(source).toContain('@UX_STATE idle');
    expect(source).toContain('@UX_STATE loading');
    expect(source).toContain('@UX_STATE preview_loaded');
    expect(source).toContain('@UX_STATE preview_error');
    expect(source).toContain('@UX_STATE accepted');
    expect(source).toContain('@UX_STATE stale_config');
    expect(source).toContain('@UX_FEEDBACK');
    expect(source).toContain('@UX_RECOVERY');
    expect(source).toContain('fetchPreview');
    expect(source).toContain('approveRow');
    expect(source).toContain('editRow');
    expect(source).toContain('rejectRow');
    expect(source).toContain('acceptPreview');
  });
  // #endregion test_component_file_exists:Function
});

// #region TranslateApiTests:Class [TYPE Function]
// @PURPOSE: Unit tests for translate API preview functions.
describe('Translate API Preview Functions', () => {
  // Hoisted mock functions so vi.mock() factories (also hoisted) can reference them.
  const mockPostApi = vi.hoisted(() => vi.fn());
  const mockRequestApi = vi.hoisted(() => vi.fn());
  const mockFetchApi = vi.hoisted(() => vi.fn());

  vi.mock('$lib/api.js', () => ({
    api: {
      postApi: mockPostApi,
      requestApi: mockRequestApi,
      fetchApi: mockFetchApi,
    }
  }));

  vi.mock('$lib/toasts', () => ({ addToast: vi.fn() }));

  beforeEach(() => {
    vi.resetModules();
    vi.clearAllMocks();
  });

  // #region test_fetchPreview:Function [TYPE Function]
  // @PURPOSE: Verify fetchPreview calls postApi with correct endpoint and payload.
  it('fetchPreview calls postApi with correct args', async () => {
    mockPostApi.mockResolvedValue({
      id: 'session-1',
      job_id: 'job-123',
      status: 'ACTIVE',
      records: [
        { id: 'r1', source_sql: 'Hello', target_sql: 'Привет', status: 'PENDING' }
      ],
      cost_estimate: {
        sample_size: 1,
        sample_total_tokens: 100,
        sample_cost: 0.0002
      }
    });

    const { fetchPreview } = await import('$lib/api/translate.js');
    const result = await fetchPreview('job-123', 5);

    expect(mockPostApi).toHaveBeenCalledWith('/translate/jobs/job-123/preview', { sample_size: 5 });
    expect(result.records).toHaveLength(1);
    expect(result.records[0].source_sql).toBe('Hello');
    expect(result.cost_estimate.sample_cost).toBe(0.0002);
  });
  // #endregion test_fetchPreview:Function

  // #region test_approveRow:Function [TYPE Function]
  // @PURPOSE: Verify approveRow calls requestApi with correct action.
  it('approveRow calls requestApi with approve action', async () => {
    mockRequestApi.mockResolvedValue({
      id: 'r1',
      status: 'APPROVED'
    });

    const { approveRow } = await import('$lib/api/translate.js');
    const result = await approveRow('job-123', 'r1');

    expect(mockRequestApi).toHaveBeenCalledWith(
      '/translate/jobs/job-123/preview/rows/r1',
      'PUT',
      { action: 'approve' }
    );
    expect(result.status).toBe('APPROVED');
  });
  // #endregion test_approveRow:Function

  // #region test_editRow:Function [TYPE Function]
  // @PURPOSE: Verify editRow calls requestApi with edit action and translation.
  it('editRow calls requestApi with edit action', async () => {
    mockRequestApi.mockResolvedValue({
      id: 'r1',
      target_sql: 'Edited translation',
      status: 'APPROVED'
    });

    const { editRow } = await import('$lib/api/translate.js');
    const result = await editRow('job-123', 'r1', 'Edited translation');

    expect(mockRequestApi).toHaveBeenCalledWith(
      '/translate/jobs/job-123/preview/rows/r1',
      'PUT',
      { action: 'edit', translation: 'Edited translation' }
    );
    expect(result.target_sql).toBe('Edited translation');
  });
  // #endregion test_editRow:Function

  // #region test_rejectRow:Function [TYPE Function]
  // @PURPOSE: Verify rejectRow calls requestApi with reject action.
  it('rejectRow calls requestApi with reject action', async () => {
    mockRequestApi.mockResolvedValue({
      id: 'r1',
      status: 'REJECTED'
    });

    const { rejectRow } = await import('$lib/api/translate.js');
    const result = await rejectRow('job-123', 'r1');

    expect(mockRequestApi).toHaveBeenCalledWith(
      '/translate/jobs/job-123/preview/rows/r1',
      'PUT',
      { action: 'reject' }
    );
    expect(result.status).toBe('REJECTED');
  });
  // #endregion test_rejectRow:Function

  // #region test_acceptPreview:Function [TYPE Function]
  // @PURPOSE: Verify acceptPreview calls postApi with correct endpoint.
  it('acceptPreview calls postApi with correct endpoint', async () => {
    mockPostApi.mockResolvedValue({
      id: 'session-1',
      job_id: 'job-123',
      status: 'APPLIED',
      records: [{ id: 'r1', status: 'APPROVED' }]
    });

    const { acceptPreview } = await import('$lib/api/translate.js');
    const result = await acceptPreview('job-123');

    expect(mockPostApi).toHaveBeenCalledWith('/translate/jobs/job-123/preview/accept', {});
    expect(result.status).toBe('APPLIED');
  });
  // #endregion test_acceptPreview:Function

  // #region test_fetchPreviewRecords:Function [TYPE Function]
  // @PURPOSE: Verify fetchPreviewRecords calls fetchApi with correct endpoint.
  it('fetchPreviewRecords calls fetchApi with correct endpoint', async () => {
    mockFetchApi.mockResolvedValue([
      { id: 'r1', source_sql: 'Hello', target_sql: 'Привет', status: 'APPROVED' }
    ]);

    const { fetchPreviewRecords } = await import('$lib/api/translate.js');
    const result = await fetchPreviewRecords('session-1');

    expect(mockFetchApi).toHaveBeenCalledWith('/translate/preview/session-1/records');
    expect(result).toHaveLength(1);
    expect(result[0].status).toBe('APPROVED');
  });
  // #endregion test_fetchPreviewRecords:Function

  // #region test_normalizeTranslateError:Function [TYPE Function]
  // @PURPOSE: Verify API errors are normalized consistently.
  it('normalizes API errors for preview functions', async () => {
    const error = new Error('API unavailable');
    mockPostApi.mockRejectedValue(error);

    const { fetchPreview } = await import('$lib/api/translate.js');

    await expect(fetchPreview('job-123')).rejects.toThrow();
  });
  // #endregion test_normalizeTranslateError:Function
});
// #endregion TranslateApiTests:Class

// #endregion TranslationPreviewComponentTest:Module
