import { describe, expect, test } from 'vitest';
import {
  COMPATIBLE_CONTRACT_VERSIONS,
  KRAIKEN_LIB_VERSION,
  STACK_META_ID,
  getVersionMismatchError,
  isCompatibleVersion,
} from '../version.js';

describe('version constants', () => {
  test('KRAIKEN_LIB_VERSION is a positive integer', () => {
    expect(typeof KRAIKEN_LIB_VERSION).toBe('number');
    expect(KRAIKEN_LIB_VERSION).toBeGreaterThan(0);
    expect(Number.isInteger(KRAIKEN_LIB_VERSION)).toBe(true);
  });

  test('STACK_META_ID is the expected string', () => {
    expect(STACK_META_ID).toBe('stack-meta');
  });

  test('COMPATIBLE_CONTRACT_VERSIONS is a non-empty array', () => {
    expect(Array.isArray(COMPATIBLE_CONTRACT_VERSIONS)).toBe(true);
    expect(COMPATIBLE_CONTRACT_VERSIONS.length).toBeGreaterThan(0);
  });

  test('COMPATIBLE_CONTRACT_VERSIONS includes KRAIKEN_LIB_VERSION', () => {
    expect(COMPATIBLE_CONTRACT_VERSIONS).toContain(KRAIKEN_LIB_VERSION);
  });
});

describe('isCompatibleVersion', () => {
  test('returns true for all known compatible versions', () => {
    for (const version of COMPATIBLE_CONTRACT_VERSIONS) {
      expect(isCompatibleVersion(version)).toBe(true);
    }
  });

  test('returns false for version 0', () => {
    expect(isCompatibleVersion(0)).toBe(false);
  });

  test('returns false for a future unknown version', () => {
    expect(isCompatibleVersion(9999)).toBe(false);
  });

  test('returns false for a negative version', () => {
    expect(isCompatibleVersion(-1)).toBe(false);
  });
});

describe('getVersionMismatchError', () => {
  test('returns a multi-line string for ponder context', () => {
    const error = getVersionMismatchError(99, 'ponder');
    expect(typeof error).toBe('string');
    expect(error.includes('\n')).toBe(true);
  });

  test('ponder context includes contract version number', () => {
    const error = getVersionMismatchError(99, 'ponder');
    expect(error).toContain('99');
  });

  test('ponder context includes VERSION MISMATCH header', () => {
    const error = getVersionMismatchError(99, 'ponder');
    expect(error).toContain('VERSION MISMATCH');
    expect(error).toContain('ponder');
  });

  test('ponder context includes ponder-specific rebuild instructions', () => {
    const error = getVersionMismatchError(99, 'ponder');
    expect(error).toContain('build-kraiken-lib.sh');
  });

  test('frontend context includes VERSION MISMATCH header', () => {
    const error = getVersionMismatchError(99, 'frontend');
    expect(error).toContain('VERSION MISMATCH');
    expect(error).toContain('frontend');
  });

  test('frontend context includes page refresh instruction', () => {
    const error = getVersionMismatchError(99, 'frontend');
    expect(error).toContain('refreshing');
  });

  test('error includes the library version', () => {
    const error = getVersionMismatchError(99, 'ponder');
    expect(error).toContain(String(KRAIKEN_LIB_VERSION));
  });

  test('error includes compatible versions list', () => {
    const error = getVersionMismatchError(99, 'ponder');
    const expectedVersions = COMPATIBLE_CONTRACT_VERSIONS.join(', ');
    expect(error).toContain(expectedVersions);
  });

  test('frontend and ponder errors differ in instructions', () => {
    const ponderError = getVersionMismatchError(99, 'ponder');
    const frontendError = getVersionMismatchError(99, 'frontend');
    expect(ponderError).not.toBe(frontendError);
  });
});
