"""End-to-end tests for AST chunking across languages."""

import importlib
import pytest
from astchunk import ASTChunkBuilder
from astchunk.astchunk_builder import _LANGUAGE_REGISTRY

# Sample code snippets per language
SAMPLES = {
    "python": '''
def hello():
    print("hello world")

class Foo:
    def bar(self, x):
        return x * 2
''',
    "java": '''
public class Main {
    public static void main(String[] args) {
        System.out.println("hello");
    }
    public int add(int a, int b) {
        return a + b;
    }
}
''',
    "csharp": '''
using System;
class Program {
    static void Main() {
        Console.WriteLine("hello");
    }
    int Add(int a, int b) => a + b;
}
''',
    "typescript": '''
function greet(name: string): string {
    return `Hello, ${name}!`;
}
interface User { name: string; age: number; }
const add = (a: number, b: number): number => a + b;
''',
    "c": '''
#include <stdio.h>
void hello() { printf("hello\\n"); }
int add(int a, int b) { return a + b; }
int main() { hello(); return 0; }
''',
    "cpp": '''
#include <iostream>
class Foo {
public:
    void bar() { std::cout << "hello"; }
    int baz(int x) { return x * 2; }
};
int main() { Foo f; f.bar(); return 0; }
''',
    "go": '''
package main
import "fmt"
func hello() { fmt.Println("hello") }
func add(a, b int) int { return a + b }
func main() { hello() }
''',
    "rust": '''
fn main() {
    let x = 42;
    println!("{}", x);
}
struct Point { x: f64, y: f64 }
impl Point {
    fn new(x: f64, y: f64) -> Self { Point { x, y } }
}
''',
    "ruby": '''
def hello
  puts "hello world"
end
class Foo
  def bar(x)
    x * 2
  end
end
''',
    "bash": '''
#!/bin/bash
function hello() { echo "hello world"; }
for i in 1 2 3; do echo $i; done
hello
''',
    "kotlin": '''
fun main() {
    println("hello")
}
fun add(a: Int, b: Int): Int = a + b
class Foo(val x: Int) {
    fun bar() = x * 2
}
''',
    "scala": '''
object Main {
  def main(args: Array[String]): Unit = {
    println("hello")
  }
  def add(a: Int, b: Int): Int = a + b
}
''',
    "lua": '''
function hello()
    print("hello world")
end
function add(a, b)
    return a + b
end
hello()
''',
    "php": '''
<?php
function hello() { echo "hello world"; }
function add($a, $b) { return $a + $b; }
class Foo {
    public function bar($x) { return $x * 2; }
}
hello();
''',
    "zig": '''
const std = @import("std");
fn add(a: i32, b: i32) i32 { return a + b; }
pub fn main() void {
    std.debug.print("hello\\n", .{});
}
''',
}


def _is_parser_available(language: str) -> bool:
    """Check if tree-sitter parser for language is installed."""
    if language in _LANGUAGE_REGISTRY:
        module_name, _ = _LANGUAGE_REGISTRY[language]
    else:
        module_name = f"tree_sitter_{language}"
    try:
        importlib.import_module(module_name)
        return True
    except ImportError:
        return False


class TestChunking:
    @pytest.mark.parametrize("language", list(SAMPLES.keys()))
    def test_chunkify_produces_output(self, language):
        if not _is_parser_available(language):
            pytest.skip(f"Parser for {language} not installed")

        builder = ASTChunkBuilder(
            max_chunk_size=300,
            language=language,
            metadata_template="default",
        )
        chunks = builder.chunkify(SAMPLES[language])
        assert len(chunks) > 0

    @pytest.mark.parametrize("language", list(SAMPLES.keys()))
    def test_chunk_format(self, language):
        if not _is_parser_available(language):
            pytest.skip(f"Parser for {language} not installed")

        builder = ASTChunkBuilder(
            max_chunk_size=300,
            language=language,
            metadata_template="default",
        )
        chunks = builder.chunkify(SAMPLES[language])
        for chunk in chunks:
            assert "content" in chunk
            assert "metadata" in chunk
            assert isinstance(chunk["content"], str)
            assert len(chunk["content"].strip()) > 0

    @pytest.mark.parametrize("language", ["python", "cpp", "go"])
    def test_small_chunk_size_produces_multiple_chunks(self, language):
        if not _is_parser_available(language):
            pytest.skip(f"Parser for {language} not installed")

        builder = ASTChunkBuilder(
            max_chunk_size=50,
            language=language,
            metadata_template="default",
        )
        chunks = builder.chunkify(SAMPLES[language])
        assert len(chunks) >= 2, f"Expected multiple chunks for {language} with small max_chunk_size"
