"""Tests for JavaScript syntax validation."""

from aiservice.validators.javascript_validator import validate_javascript_syntax, validate_typescript_syntax


class TestJavaScriptValidatorFallback:
    """Tests for the fallback validation (when Node.js is not available)."""

    def test_valid_simple_function(self) -> None:
        """Test that a simple valid function passes validation."""
        code = """
function add(a, b) {
    return a + b;
}
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_valid_arrow_function(self) -> None:
        """Test that arrow functions pass validation."""
        code = "const add = (a, b) => a + b;"
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_valid_class(self) -> None:
        """Test that a class definition passes validation."""
        code = """
class Calculator {
    constructor() {
        this.result = 0;
    }

    add(value) {
        this.result += value;
        return this;
    }
}
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_valid_async_function(self) -> None:
        """Test that async functions pass validation."""
        code = """
async function fetchData(url) {
    const response = await fetch(url);
    return response.json();
}
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_valid_template_literal(self) -> None:
        """Test that template literals pass validation."""
        code = """
const greeting = `Hello, ${name}!`;
const multiline = `
    This is a
    multiline string
`;
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_unclosed_brace(self) -> None:
        """Test that unclosed braces are detected."""
        code = """
function broken() {
    return true;
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is False
        assert error is not None

    def test_unclosed_parenthesis(self) -> None:
        """Test that unclosed parentheses are detected."""
        code = "const result = add(1, 2"
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is False
        assert error is not None

    def test_unclosed_bracket(self) -> None:
        """Test that unclosed brackets are detected."""
        code = "const arr = [1, 2, 3"
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is False
        assert error is not None

    def test_mismatched_brackets(self) -> None:
        """Test that mismatched brackets are detected."""
        code = "const arr = [1, 2, 3}"
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is False
        assert error is not None

    def test_string_with_brackets_ignored(self) -> None:
        """Test that brackets inside strings are ignored."""
        code = """
const str = "This string has { and } and [ and ]";
const obj = { valid: true };
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_empty_code(self) -> None:
        """Test that empty code passes validation."""
        is_valid, error = validate_javascript_syntax("")
        assert is_valid is True
        assert error is None

    def test_comments_only(self) -> None:
        """Test that code with only comments passes validation."""
        code = """
// This is a comment
/* This is a
   multiline comment */
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None

    def test_nested_structures(self) -> None:
        """Test that deeply nested structures pass validation."""
        code = """
const nested = {
    level1: {
        level2: {
            level3: [
                { deep: true }
            ]
        }
    }
};
"""
        is_valid, error = validate_javascript_syntax(code)
        assert is_valid is True
        assert error is None


class TestJavaScriptValidatorMain:
    """Tests for the main validation function."""

    def test_valid_module_exports(self) -> None:
        """Test that module.exports syntax passes validation."""
        code = """
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

module.exports = { fibonacci };
"""
        is_valid, error = validate_javascript_syntax(code)
        # This may pass with fallback even if Node.js isn't available
        # The point is it shouldn't crash
        assert isinstance(is_valid, bool)

    def test_valid_es6_imports(self) -> None:
        """Test that ES6 import syntax passes validation."""
        code = """
import { useState, useEffect } from 'react';

export function Counter() {
    const [count, setCount] = useState(0);
    return count;
}
"""
        is_valid, error = validate_javascript_syntax(code)
        assert isinstance(is_valid, bool)

    def test_destructuring(self) -> None:
        """Test that destructuring passes validation."""
        code = """
const { a, b } = obj;
const [first, second, ...rest] = arr;
"""
        is_valid, error = validate_javascript_syntax(code)
        assert isinstance(is_valid, bool)

    def test_spread_operator(self) -> None:
        """Test that spread operator passes validation."""
        code = """
const merged = { ...obj1, ...obj2 };
const combined = [...arr1, ...arr2];
"""
        is_valid, error = validate_javascript_syntax(code)
        assert isinstance(is_valid, bool)


class TestTypeScriptValidator:
    """Tests for TypeScript validation."""

    def test_typescript_types(self) -> None:
        """Test that TypeScript type annotations pass validation."""
        code = """
function add(a: number, b: number): number {
    return a + b;
}
"""
        is_valid, error = validate_typescript_syntax(code)
        # TypeScript uses the same validator as JavaScript
        assert isinstance(is_valid, bool)

    def test_typescript_interface(self) -> None:
        """Test that TypeScript interfaces pass validation (if Node available)."""
        code = """
interface User {
    name: string;
    age: number;
}

function greet(user: User): string {
    return `Hello, ${user.name}`;
}
"""
        is_valid, error = validate_typescript_syntax(code)
        assert isinstance(is_valid, bool)

    def test_tsx_simple_jsx(self) -> None:
        """Test that simple JSX syntax passes validation in TypeScript."""
        code = """
export const EmailPreviewContentMobile = (props: EmailPreviewContentMobileProps) => {
  const { className, ...rest } = props;

  return <div className={cn('max-w-sm', className)} {...rest} />;
};
"""
        is_valid, error = validate_typescript_syntax(code)
        assert is_valid is True, f"JSX should be valid in TypeScript. Error: {error}"
        assert error is None

    def test_tsx_nested_jsx(self) -> None:
        """Test that nested JSX elements pass validation."""
        code = """
export const Component = () => {
  return (
    <div>
      <h1>Title</h1>
      <p>Content</p>
    </div>
  );
};
"""
        is_valid, error = validate_typescript_syntax(code)
        assert is_valid is True, f"Nested JSX should be valid. Error: {error}"
        assert error is None

    def test_tsx_with_props_spread(self) -> None:
        """Test that JSX with spread props passes validation."""
        code = """
export const Button = (props: ButtonProps) => {
  return <button {...props}>Click me</button>;
};
"""
        is_valid, error = validate_typescript_syntax(code)
        assert is_valid is True, f"JSX with spread props should be valid. Error: {error}"
        assert error is None
