// #region DatasetReviewApiTest [C:3] [TYPE Module] [SEMANTICS test, dataset-review, api, session, conflict, version]
// @BRIEF Unit tests for dataset review API helpers — optimistic-lock headers, conflict detection, version extraction, DTO normalization.
// @RELATION DEPENDS_ON -> [DatasetReviewApi]
// @TEST_EDGE: null_version -> buildDatasetReviewRequestOptions returns empty object for null/undefined
// @TEST_EDGE: non_409_status -> isDatasetReviewConflictError returns false for non-409 statuses
// @TEST_EDGE: flat_detail -> normalizeDatasetReviewDetail passes through objects with session_id but no session wrapper

import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock the $lib/api dependency
vi.mock('$lib/api', () => ({
	requestApi: vi.fn(),
}));

describe('buildDatasetReviewRequestOptions', () => {
	it('returns empty object for null sessionVersion', async () => {
		const { buildDatasetReviewRequestOptions } = await import('../datasetReview.ts');
		expect(buildDatasetReviewRequestOptions(null)).toEqual({});
	});

	it('returns empty object for undefined sessionVersion', async () => {
		const { buildDatasetReviewRequestOptions } = await import('../datasetReview.ts');
		expect(buildDatasetReviewRequestOptions(undefined)).toEqual({});
	});

	it('returns empty object for empty string sessionVersion', async () => {
		const { buildDatasetReviewRequestOptions } = await import('../datasetReview.ts');
		expect(buildDatasetReviewRequestOptions('')).toEqual({});
	});

	it('returns headers with X-Session-Version for numeric version', async () => {
		const { buildDatasetReviewRequestOptions } = await import('../datasetReview.ts');
		const result = buildDatasetReviewRequestOptions(5);
		expect(result).toEqual({ headers: { 'X-Session-Version': '5' } });
	});

	it('returns headers with X-Session-Version for string version', async () => {
		const { buildDatasetReviewRequestOptions } = await import('../datasetReview.ts');
		const result = buildDatasetReviewRequestOptions('v2');
		expect(result).toEqual({ headers: { 'X-Session-Version': 'v2' } });
	});
});

describe('requestDatasetReviewApi', () => {
	beforeEach(() => {
		vi.resetModules();
	});

	it('calls requestApi without version headers when sessionVersion is null', async () => {
		const { requestApi } = await import('$lib/api');
		vi.mocked(requestApi).mockResolvedValue({});

		const { requestDatasetReviewApi } = await import('../datasetReview.ts');
		await requestDatasetReviewApi('/endpoint', 'GET', null, null);

		expect(requestApi).toHaveBeenCalledWith('/endpoint', 'GET', null);
	});

	it('passes requestOptions when sessionVersion is provided', async () => {
		const { requestApi } = await import('$lib/api');
		vi.mocked(requestApi).mockResolvedValue({});

		const { requestDatasetReviewApi } = await import('../datasetReview.ts');
		await requestDatasetReviewApi('/endpoint', 'PATCH', { key: 'val' }, 3);

		expect(requestApi).toHaveBeenCalledWith('/endpoint', 'PATCH', { key: 'val' }, { headers: { 'X-Session-Version': '3' } });
	});
});

describe('isDatasetReviewConflictError', () => {
	it('returns true for status 409', async () => {
		const { isDatasetReviewConflictError } = await import('../datasetReview.ts');
		expect(isDatasetReviewConflictError({ status: 409 })).toBe(true);
	});

	it('returns false for status 404', async () => {
		const { isDatasetReviewConflictError } = await import('../datasetReview.ts');
		expect(isDatasetReviewConflictError({ status: 404 })).toBe(false);
	});

	it('returns false for null error', async () => {
		const { isDatasetReviewConflictError } = await import('../datasetReview.ts');
		expect(isDatasetReviewConflictError(null)).toBe(false);
	});

	it('returns false for undefined error', async () => {
		const { isDatasetReviewConflictError } = await import('../datasetReview.ts');
		expect(isDatasetReviewConflictError(undefined)).toBe(false);
	});
});

describe('getDatasetReviewConflictMessage', () => {
	it('returns error message when present', async () => {
		const { getDatasetReviewConflictMessage } = await import('../datasetReview.ts');
		expect(getDatasetReviewConflictMessage({ message: 'Version mismatch' })).toBe('Version mismatch');
	});

	it('returns default message when error has no message', async () => {
		const { getDatasetReviewConflictMessage } = await import('../datasetReview.ts');
		const msg = getDatasetReviewConflictMessage({});
		expect(msg).toBe('This review session changed in another action. Reload the latest session state and retry the update.');
	});

	it('returns default message for null', async () => {
		const { getDatasetReviewConflictMessage } = await import('../datasetReview.ts');
		const msg = getDatasetReviewConflictMessage(null);
		expect(msg).toBe('This review session changed in another action. Reload the latest session state and retry the update.');
	});
});

describe('extractDatasetReviewVersion', () => {
	it('returns null for null payload', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion(null)).toBeNull();
	});

	it('returns null for undefined payload', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion(undefined)).toBeNull();
	});

	it('returns session_version from flat object', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion({ session_version: 3 })).toBe(3);
	});

	it('returns version when session_version is absent', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion({ version: 'v2' })).toBe('v2');
	});

	it('prefers session_version over version', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion({ session_version: 5, version: 1 })).toBe(5);
	});

	it('recurses into nested session object', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion({ session: { version: 7 } })).toBe(7);
	});

	it('iterates array and returns first found version', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion([{ id: 1 }, { session_version: 2 }, { id: 3 }])).toBe(2);
	});

	it('returns null for empty array', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion([])).toBeNull();
	});
});

describe('normalizeDatasetReviewDetail', () => {
	it('returns null for null detail', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		expect(normalizeDatasetReviewDetail(null)).toBeNull();
	});

	it('returns null for undefined detail', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		expect(normalizeDatasetReviewDetail(undefined)).toBeNull();
	});

	it('passes through legacy flat detail (session_id without session wrapper)', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = { session_id: 's1', status: 'active' };
		expect(normalizeDatasetReviewDetail(detail)).toBe(detail);
	});

	it('flattens refreshed detail with session wrapper', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = {
			session: { session_id: 's1', readiness_state: 'ready' },
			preview: { preview_id: 'p1' },
			session_version: 3,
			findings: [{ id: 'f1' }],
		};
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.session_id).toBe('s1');
		expect(result?.session_version).toBe(3);
		expect(result?.preview).toEqual({ preview_id: 'p1' });
		expect(result?.findings).toEqual([{ id: 'f1' }]);
	});

	it('fills default arrays when not present in detail', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = { session: { session_id: 's2' } };
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.findings).toEqual([]);
		expect(result?.semantic_fields).toEqual([]);
		expect(result?.imported_filters).toEqual([]);
		expect(result?.execution_mappings).toEqual([]);
		expect(result?.previews).toEqual([]);
	});

	it('extracts clarification_session from nested clarification object', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = {
			session: { session_id: 's3' },
			clarification: { clarification_session: { id: 'cs-1' } },
		};
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.clarification_sessions).toEqual([{ id: 'cs-1' }]);
	});

	it('filters out null clarification_session', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = {
			session: { session_id: 's4' },
			clarification: { clarification_session: null },
		};
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.clarification_sessions).toEqual([]);
	});

	it('uses existing clarification_sessions when no clarification object', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = {
			session: { session_id: 's5' },
			clarification_sessions: [{ id: 'cs-2' }],
		};
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.clarification_sessions).toEqual([{ id: 'cs-2' }]);
	});

	it('uses session_version from summary when not in root', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = {
			session: { session_id: 's6', session_version: 42, version: 7 },
		};
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.session_version).toBe(42);
		expect(result?.version).toBe(42);
	});

	it('falls back to summary version when neither root nor summary session_version exist', async () => {
		const { normalizeDatasetReviewDetail } = await import('../datasetReview.ts');
		const detail = {
			session: { session_id: 's7', version: 99 },
		};
		const result = normalizeDatasetReviewDetail(detail);
		expect(result?.session_version).toBe(99);
		expect(result?.version).toBe(99);
	});
});

describe('extractDatasetReviewVersion — additional edge cases', () => {
	it('returns null when array has no item with version', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion([{ id: 1 }, { id: 2 }])).toBeNull();
	});

	it('returns null when session field has no version', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion({ session: { id: 's1' } })).toBeNull();
	});

	it('returns null for empty object', async () => {
		const { extractDatasetReviewVersion } = await import('../datasetReview.ts');
		expect(extractDatasetReviewVersion({})).toBeNull();
	});
});
// #endregion DatasetReviewApiTest
