package com.xxx.amp.magenta.livecodebench;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SuppressWarnings("ALL")
public class LiteralParserTest {
    LiteralParser parser = new LiteralParser();

    @Test
    public void testString() throws LiteralSyntaxException {
        assertEquals("abc", parser.parse(String.class, "\"abc\""));
    }

    @Test
    public void testNonString() {
        assertThrows(LiteralSyntaxException.class,
                () -> parser.parse(String.class, "1")
        );
    }

    @Test
    public void testInt() throws LiteralSyntaxException {
        assertEquals(1, parser.parse(Integer.class, "1"));
    }

    @Test
    public void testNonInt() {
        assertThrows(LiteralSyntaxException.class,
                () -> parser.parse(Integer.class, "\"a\"")
        );
        assertThrows(LiteralSyntaxException.class,
                () -> parser.parse(Integer.class, "[1, 2, 3, 4]")
        );
    }

    public void xxx(List<List<Integer>> list) {
        return;
    }

    public void yyy(List<Integer> list) {

    }

    public void zzz(List<String> list) {

    }

    public void www(int[][] array) {
    }

    public void bbb(List<Boolean> list) {

    }

    @Test
    public void testListInt() throws NoSuchMethodException, LiteralSyntaxException {
        assertIterableEquals(List.of(1, 2), (List<Integer>) parser.parse(
                getParamTypeFromMethod("yyy"),
                "[1, 2]"
        ));

        assertIterableEquals(List.of(List.of(1, 2), List.of(3, 4)),
                (Iterable<?>) parser.parse(
                        getParamTypeFromMethod("xxx"),
                        "[[1, 2], [3, 4]]"
                )
        );
    }

    @Test
    public void testListString() throws NoSuchMethodException, LiteralSyntaxException {
        assertIterableEquals(List.of("1", "2"), (List<String>) parser.parse(
                getParamTypeFromMethod("zzz"),
                "[\"1\", \"2\"]"
        ));
    }

    @Test
    public void testArrayIntInt() throws Exception {
        assertArrayEquals(new int[][]{{1, 2}, {3, 4}}, (int[][]) parser.parse(
                getParamTypeFromMethod("www"),
                "[[1,2],[3,4]]"
        ));
    }

    @Test
    public void testBooleanArray() throws Exception {
        assertIterableEquals(
                List.of(true, false),
                (List<Boolean>) parser.parse(
                        getParamTypeFromMethod("bbb"),
                        "[true, false]"
                )
        );
    }

    private Type getParamTypeFromMethod(String name) throws NoSuchMethodException {
        for (Method m : getClass().getMethods()) {
            if (name.equals(m.getName())) {
                return m.getParameters()[0].getAnnotatedType()
                        .getType();
            }
        }
        throw new NoSuchMethodException("Unknown method %s".formatted(name));
    }
}
