package org.jdbi.v3.sqlobject.customizer;

import java.util.List;
import java.util.Map;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.mapper.MapMapper;
import org.jdbi.v3.core.rule.H2DatabaseRule;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
import org.jdbi.v3.sqlobject.config.RegisterRowMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class TestMaxRows {
    private static final String QUERY = "select bar from foo";
    private static final String CREATE_INSERT = "create table foo(bar int primary key);" +
        "insert into foo(bar) values(1);" +
        "insert into foo(bar) values(2);" +
        "insert into foo(bar) values(3);";
    private static final int ROWS = 1;

    @Rule
    public H2DatabaseRule dbRule = new H2DatabaseRule().withPlugin(new SqlObjectPlugin());
    private Handle handle;

    @Before
    public void setUp() throws Exception
    {
        handle = dbRule.openHandle();
    }

    @Test
    public void testMethodWrong() {
        assertThatThrownBy(() -> handle.attach(FooMethodWrong.class))
            .isInstanceOf(IllegalArgumentException.class)
            .hasMessageContaining("no value given");
    }

    @Test
    public void testParamWrong() {
        assertThatThrownBy(() -> handle.attach(FooParamWrong.class))
            .isInstanceOf(IllegalArgumentException.class)
            .hasMessageContaining("value won't do anything");
    }

    @Test
    public void testMethodRight() {
        FooMethodRight sqlObject = handle.attach(FooMethodRight.class);
        assertThat(sqlObject).isInstanceOf(FooMethodRight.class);

        handle.createScript(CREATE_INSERT).execute();

        assertThat(sqlObject.bar()).hasSize(ROWS);
    }

    @Test
    public void testParamRight() {
        FooParamRight sqlObject = handle.attach(FooParamRight.class);
        assertThat(sqlObject).isInstanceOf(FooParamRight.class);

        handle.createScript(CREATE_INSERT).execute();

        assertThat(sqlObject.bar(ROWS)).hasSize(ROWS);
    }

    public interface FooMethodWrong extends SqlObject {
        @MaxRows
        @SqlQuery(QUERY)
        List<Map<String, Object>> bar();
    }

    public interface FooParamWrong extends SqlObject {
        @SqlQuery(QUERY)
        List<Map<String, Object>> bar(@MaxRows(ROWS) int rows);
    }

    public interface FooMethodRight extends SqlObject {
        @MaxRows(ROWS)
        @SqlQuery(QUERY)
        @RegisterRowMapper(MapMapper.class)
        List<Map<String, Object>> bar();
    }

    public interface FooParamRight extends SqlObject {
        @SqlQuery(QUERY)
        @RegisterRowMapper(MapMapper.class)
        List<Map<String, Object>> bar(@MaxRows int rows);
    }
}

@@ -1768,74 +1768,8 @@
 ss);
-%0A        assertThat(sqlObject).isInstanceOf(FooMethodRight.class);
 %0A%0A  
@@ -1997,73 +1997,8 @@
 ss);
-%0A        assertThat(sqlObject).isInstanceOf(FooParamRight.class);
 %0A%0A  
@@ -2104,32 +2104,252 @@
 e(ROWS);%0A    %7D%0A%0A
+    @Test%0A    public void testControlGroup() %7B%0A        NoMaxRows sqlObject = handle.attach(NoMaxRows.class);%0A%0A        handle.createScript(CREATE_INSERT).execute();%0A%0A        assertThat(sqlObject.bar()).hasSize(3);%0A    %7D%0A%0A
     public inter
@@ -2941,32 +2941,32 @@
 apMapper.class)%0A
-
         List%3CMap
@@ -3012,11 +3012,179 @@
 );%0A    %7D
+%0A%0A    public interface NoMaxRows extends SqlObject %7B%0A        @SqlQuery(QUERY)%0A        @RegisterRowMapper(MapMapper.class)%0A        List%3CMap%3CString, Object%3E%3E bar();%0A    %7D
 %0A%7D%0A

verify with a control group