/**
 * @fileoverview Final parser validation tests
 */

import { describe, expect, it } from 'vitest';
import { OrdoJSLexer } from './lexer.js';
import { OrdoJSParser } from './parser.js';

describe('OrdoJSParser - Final Validation', () => {
  const parseComponent = (source: string) => {
    const lexer = new OrdoJSLexer(source, 'test.ordo');
    const tokens = lexer.tokenize();
    const parser = new OrdoJSParser(tokens, {}, 'test.ordo');
    return parser.parse();
  };

  it('should parse minimal component', () => {
    const source = `
      component TestComponent {
        markup {
          <div>Hello World</div>
        }
      }
    `;

    const ast = parseComponent(source);
    expect(ast.component.name).toBe('TestComponent');
    expect(ast.component.markupBlock.elements).toHaveLength(1);
    expect(ast.component.markupBlock.elements[0].tagName).toBe('div');
  });

  it('should parse component with client block', () => {
    const source = `
      component TestComponent {
        client {
          let count = 0;
          const name = "test";
        }
        markup {
          <div>{count}</div>
        }
      }
    `;

    const ast = parseComponent(source);
    expect(ast.component.clientBlock).toBeDefined();
    expect(ast.component.clientBlock!.reactiveVariables).toHaveLength(2);
    expect(ast.component.clientBlock!.reactiveVariables[0].name).toBe('count');
    expect(ast.component.clientBlock!.reactiveVariables[1].name).toBe('name');
  });

  it('should parse component with server block', () => {
    const source = `
      component TestComponent {
        server {
          public getData(): string {
            return "data";
          }
        }
        markup {
          <div>Test</div>
        }
      }
    `;

    const ast = parseComponent(source);
    expect(ast.component.serverBlock).toBeDefined();
    expect(ast.component.serverBlock!.functions).toHaveLength(1);
    expect(ast.component.serverBlock!.functions[0].name).toBe('getData');
    expect(ast.component.serverBlock!.functions[0].isPublic).toBe(true);
  });

  it('should parse HTML with attributes', () => {
    const source = `
      component TestComponent {
        markup {
          <div class="container" id="main">
            <input type="text" placeholder="Enter text" />
            <button disabled>Click me</button>
          </div>
        }
      }
    `;

    const ast = parseComponent(source);
    const mainDiv = ast.component.markupBlock.elements[0];

    expect(mainDiv.attributes).toHaveLength(2);
    expect(mainDiv.attributes[0].name).toBe('class');
    expect(mainDiv.attributes[0].value).toBe('container');
    expect(mainDiv.attributes[1].name).toBe('id');
    expect(mainDiv.attributes[1].value).toBe('main');

    expect(mainDiv.children).toHaveLength(2);
  });

  it('should parse component with props', () => {
    const source = `
      component TestComponent(title: string, count: number = 0) {
        markup {
          <div>{title}: {count}</div>
        }
      }
    `;

    const ast = parseComponent(source);
    expect(ast.component.props).toHaveLength(2);
    expect(ast.component.props[0].name).toBe('title');
    expect(ast.component.props[0].dataType.name).toBe('string');
    expect(ast.component.props[0].isRequired).toBe(true);

    expect(ast.component.props[1].name).toBe('count');
    expect(ast.component.props[1].dataType.name).toBe('number');
    expect(ast.component.props[1].isRequired).toBe(false);
  });
});
