// core/types/tests/interfaces.spec.ts
// 冒烟测试：验证接口定义可正确导入和使用

import { describe, expect, test } from 'bun:test';
import { BN } from '@ocap/util';
import type {
  // base
  BN as BNType,
  BytesType,
  DeepPartial,
  // hooks
  HookPhase,
  IAccountState,
  IAny,
  IChainConfig,
  // statedb
  IDBTransaction,
  IHookHandler,
  IHookResult,
  IPage,
  IPageInfo,
  IPagedResult,
  IRangeFilter,
  ISearchResult,
  // state
  IState,
  IStateContext,
  IStateWithOwner,
  ITimeFilter,
  PartialBy,
  RequiredBy,
  StateChangeType,
  StateKind,
  Timestamp,
} from '../interfaces';

describe('core/types/interfaces', () => {
  describe('base types', () => {
    test('should define BytesType as string | Buffer | Uint8Array', () => {
      const str: BytesType = 'hello';
      const buf: BytesType = Buffer.from('hello');
      const arr: BytesType = new Uint8Array([1, 2, 3]);
      expect(str).toBeDefined();
      expect(buf).toBeDefined();
      expect(arr).toBeDefined();
    });

    test('should define BN type compatible with @ocap/util BN class', () => {
      // BN class from @ocap/util should satisfy BNType from @ocap/types
      const fromStr: BNType = new BN('1000000');
      const fromNum: BNType = new BN(1000000);
      const fromNull: BNType = new BN(null);
      expect(fromStr.toString()).toBe('1000000');
      expect(fromNum.toString()).toBe('1000000');
      expect(fromNull.toString()).toBe('0');
    });

    test('should define Timestamp as string | number | Date', () => {
      const str: Timestamp = '2024-01-01T00:00:00Z';
      const num: Timestamp = Date.now();
      const date: Timestamp = new Date();
      expect(str).toBeDefined();
      expect(num).toBeDefined();
      expect(date).toBeDefined();
    });

    test('should define IAny interface', () => {
      const any: IAny = {
        typeUrl: 'type.googleapis.com/example',
        value: new Uint8Array([1, 2, 3]),
      };
      expect(any.typeUrl).toBe('type.googleapis.com/example');
      expect(any.value).toBeInstanceOf(Uint8Array);
    });

    test('should define utility types', () => {
      type Example = { a: string; b: number; c: boolean };
      type PartialA = PartialBy<Example, 'a'>;
      type RequiredC = RequiredBy<Partial<Example>, 'c'>;
      type Deep = DeepPartial<Example>;

      const partial: PartialA = { b: 1, c: true };
      const required: RequiredC = { c: false };
      const deep: Deep = { a: 'test' };

      expect(partial).toBeDefined();
      expect(required).toBeDefined();
      expect(deep).toBeDefined();
    });
  });

  describe('state types', () => {
    test('should define IStateContext', () => {
      const context: IStateContext = {
        genesisTx: 'tx123',
        renaissanceTx: 'tx456',
        genesisTime: new Date(),
        renaissanceTime: '2024-01-01',
      };
      expect(context.genesisTx).toBe('tx123');
    });

    test('should define IState', () => {
      const state: IState = {
        address: 'z1234567890',
        context: {
          genesisTx: 'tx123',
          renaissanceTx: 'tx456',
        },
      };
      expect(state.address).toBe('z1234567890');
    });

    test('should define IStateWithOwner extending IState', () => {
      const state: IStateWithOwner = {
        address: 'z1234567890',
        owner: 'z0987654321',
        issuer: 'z1111111111',
      };
      expect(state.owner).toBeDefined();
      expect(state.issuer).toBeDefined();
    });

    test('should define StateKind union', () => {
      const types: StateKind[] = [
        'account',
        'asset',
        'token',
        'token-factory',
        'asset-factory',
        'stake',
        'delegation',
        'rollup',
        'rollup-block',
        'evidence',
      ];
      expect(types).toHaveLength(10);
    });

    test('should define StateChangeType union', () => {
      const types: StateChangeType[] = ['create', 'update', 'delete'];
      expect(types).toHaveLength(3);
    });
  });

  describe('execution types', () => {
    test('should define IChainConfig', () => {
      const config: IChainConfig = {
        chainId: 'test-chain',
        chainName: 'Test Chain',
        consensus: {},
        transaction: {},
        token: {},
      };
      expect(config.chainId).toBe('test-chain');
    });

    test('should define IAccountState extending IState', () => {
      const account: IAccountState = {
        address: 'z1234567890',
        balance: '1000000',
        nonce: '1',
        numTxs: '10',
        pk: 'pk123',
        moniker: 'alice',
      };
      expect(account.balance).toBe('1000000');
    });
  });

  describe('hook types', () => {
    test('should define HookPhase union', () => {
      const phases: HookPhase[] = ['pre-check', 'post-check', 'pre-apply', 'post-apply', 'pre-commit', 'post-commit'];
      expect(phases).toHaveLength(6);
    });

    test('should define IHookResult', () => {
      const result: IHookResult = {
        continue: true,
        code: 0,
        message: 'success',
      };
      expect(result.continue).toBe(true);
    });

    test('should define IHookHandler', () => {
      const handler: IHookHandler = {
        name: 'test-hook',
        priority: 50,
        handler: async () => ({ continue: true }),
      };
      expect(handler.name).toBe('test-hook');
      expect(handler.priority).toBe(50);
    });
  });

  describe('statedb types', () => {
    test('should define IDBTransaction', () => {
      const tx: IDBTransaction = {
        id: 'tx-123',
        state: 'pending',
      };
      expect(tx.state).toBe('pending');
    });
  });

  describe('indexdb types', () => {
    test('should define IPage', () => {
      const page: IPage = {
        cursor: 'abc123',
        size: 20,
        order: 'desc',
      };
      expect(page.size).toBe(20);
    });

    test('should define IPageInfo extending IPage', () => {
      const pageInfo: IPageInfo = {
        cursor: 'abc123',
        size: 20,
        order: 'desc',
        next: 'def456',
        hasMore: true,
      };
      expect(pageInfo.hasMore).toBe(true);
    });

    test('should define IPagedResult', () => {
      const result: IPagedResult<{ id: string }> = {
        data: [{ id: '1' }, { id: '2' }],
        page: { hasMore: false },
        total: 2,
      };
      expect(result.data).toHaveLength(2);
      expect(result.total).toBe(2);
    });

    test('should define ITimeFilter', () => {
      const filter: ITimeFilter = {
        start: '2024-01-01',
        end: new Date(),
      };
      expect(filter.start).toBeDefined();
    });

    test('should define IRangeFilter', () => {
      const filter: IRangeFilter = {
        min: 0,
        max: '1000000',
      };
      expect(filter.min).toBe(0);
    });

    test('should define ISearchResult', () => {
      const result: ISearchResult = {
        type: 'account',
        address: 'z1234567890',
        score: 0.95,
        highlights: ['<em>alice</em>'],
        data: { moniker: 'alice' },
      };
      expect(result.score).toBe(0.95);
    });
  });
});
