/**
 * @fileoverview HTML and Interpolation Lexer Tests
 */

import { describe, expect, it } from 'vitest';
import { TokenType } from '../types/index.js';
import { OrdoJSLexer } from './lexer.js';

describe('OrdoJSLexer - HTML and Interpolation', () => {
  describe('Simple Interpolation', () => {
    it('should tokenize simple interpolation', () => {
      const lexer = new OrdoJSLexer('{name}');
      const stream = lexer.tokenize();

      expect(stream.tokens[0].type).toBe(TokenType.LEFT_BRACE);
      expect(stream.tokens[1].type).toBe(TokenType.IDENTIFIER);
      expect(stream.tokens[1].value).toBe('name');
      expect(stream.tokens[2].type).toBe(TokenType.RIGHT_BRACE);
    });

    it('should tokenize interpolation with expression', () => {
      const lexer = new OrdoJSLexer('{count + 1}');
      const stream = lexer.tokenize();

      expect(stream.tokens[0].type).toBe(TokenType.LEFT_BRACE);
      expect(stream.tokens[1].type).toBe(TokenType.IDENTIFIER);
      expect(stream.tokens[1].value).toBe('count');
      expect(stream.tokens[2].type).toBe(TokenType.PLUS);
      expect(stream.tokens[3].type).toBe(TokenType.NUMBER);
      expect(stream.tokens[3].value).toBe('1');
      expect(stream.tokens[4].type).toBe(TokenType.RIGHT_BRACE);
    });
  });

  describe('Markup Block Context', () => {
    it('should handle markup block with simple content', () => {
      const source = 'markup { hello world }';
      const lexer = new OrdoJSLexer(source);
      const stream = lexer.tokenize();

      expect(stream.tokens[0].type).toBe(TokenType.MARKUP);
      expect(stream.tokens[1].type).toBe(TokenType.LEFT_BRACE);
      expect(stream.tokens[2].type).toBe(TokenType.IDENTIFIER);
      expect(stream.tokens[2].value).toBe('hello');
      expect(stream.tokens[3].type).toBe(TokenType.IDENTIFIER);
      expect(stream.tokens[3].value).toBe('world');
      expect(stream.tokens[4].type).toBe(TokenType.RIGHT_BRACE);
    });
  });

  describe('Complete Component with Interpolation', () => {
    it('should tokenize component with client block and interpolation', () => {
      const source = `
        component Test {
          client {
            let count = 0;
          }
          markup {
            {count}
          }
        }
      `;

      const lexer = new OrdoJSLexer(source);
      const stream = lexer.tokenize();

      // Verify key tokens are present
      expect(stream.tokens.some(t => t.type === TokenType.COMPONENT)).toBe(true);
      expect(stream.tokens.some(t => t.type === TokenType.CLIENT)).toBe(true);
      expect(stream.tokens.some(t => t.type === TokenType.MARKUP)).toBe(true);
      expect(stream.tokens.some(t => t.type === TokenType.LET)).toBe(true);

      // Find the count identifier in different contexts
      const countTokens = stream.tokens.filter(t =>
        t.type === TokenType.IDENTIFIER && t.value === 'count'
      );
      expect(countTokens.length).toBeGreaterThanOrEqual(2); // Declaration and usage
    });
  });

  describe('Edge Cases', () => {
    it('should handle empty braces', () => {
      const lexer = new OrdoJSLexer('{}');
      const stream = lexer.tokenize();

      expect(stream.tokens[0].type).toBe(TokenType.LEFT_BRACE);
      expect(stream.tokens[1].type).toBe(TokenType.RIGHT_BRACE);
      expect(stream.tokens[2].type).toBe(TokenType.EOF);
    });

    it('should handle nested braces', () => {
      const lexer = new OrdoJSLexer('{ { } }');
      const stream = lexer.tokenize();

      expect(stream.tokens[0].type).toBe(TokenType.LEFT_BRACE);
      expect(stream.tokens[1].type).toBe(TokenType.LEFT_BRACE);
      expect(stream.tokens[2].type).toBe(TokenType.RIGHT_BRACE);
      expect(stream.tokens[3].type).toBe(TokenType.RIGHT_BRACE);
    });
  });
});
