package com.nisemoe.nise.database

import com.nisemoe.generated.tables.references.BEATMAPS
import com.nisemoe.generated.tables.references.SCORES
import com.nisemoe.generated.tables.references.SCORES_SIMILARITY
import com.nisemoe.generated.tables.references.USERS
import com.nisemoe.nise.osu.OsuApi
import com.nisemoe.nise.osu.TokenService
import com.nisemoe.nise.scheduler.GlobalCache
import org.jooq.DSLContext
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.context.annotation.Import
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import java.time.LocalDateTime

@SpringBootTest
@ActiveProfiles("postgres")
@MockBean(GlobalCache::class, OsuApi::class, TokenService::class, UserService::class)
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(ScoreService::class)
@Disabled
class ScoreServiceTest {

    companion object {
        @Container
        private val postgresContainer = PostgreSQLContainer<Nothing>("postgres:13").apply {
            withDatabaseName("testdb")
            withUsername("testuser")
            withPassword("testpass")
            start()
        }

        @DynamicPropertySource
        @JvmStatic
        fun registerDynamicProperties(registry: DynamicPropertyRegistry) {
            registry.add("spring.datasource.url", postgresContainer::getJdbcUrl)
            registry.add("spring.datasource.username", postgresContainer::getUsername)
            registry.add("spring.datasource.password", postgresContainer::getPassword)
        }
    }

    @Autowired
    lateinit var scoreService: ScoreService

    @Autowired
    lateinit var dslContext: DSLContext

    @Test
    fun `should only return replay1`() {
        //
        dslContext.insertInto(SCORES_SIMILARITY)
            .set(SCORES_SIMILARITY.BEATMAP_ID, 1)
            .set(SCORES_SIMILARITY.REPLAY_ID_1, 1)
            .set(SCORES_SIMILARITY.REPLAY_ID_2, 2)
            .set(SCORES_SIMILARITY.SIMILARITY, 0.5)
            .execute()

        dslContext.insertInto(BEATMAPS)
            .set(BEATMAPS.BEATMAP_ID, 1)
            .set(BEATMAPS.BEATMAPSET_ID, 1)
            .set(BEATMAPS.TITLE, "test")
            .execute()

        dslContext.insertInto(SCORES)
            .set(SCORES.REPLAY_ID, 1)
            .set(SCORES.USER_ID, 1)
            .set(SCORES.DATE, LocalDateTime.now().minusDays(90))
            .execute()

        dslContext.insertInto(USERS)
            .set(USERS.USER_ID, 1)
            .set(USERS.USERNAME, "good boy")
            .execute()

        dslContext.insertInto(SCORES)
            .set(SCORES.REPLAY_ID, 2)
            .set(SCORES.USER_ID, 2)
            .set(SCORES.DATE, LocalDateTime.now().minusDays(180))
            .execute()

        dslContext.insertInto(USERS)
            .set(USERS.USER_ID, 2)
            .set(USERS.USERNAME, "naughty boy")
            .execute()

        dslContext.insertInto(SCORES_SIMILARITY)
            .set(SCORES_SIMILARITY.BEATMAP_ID, 1)
            .set(SCORES_SIMILARITY.REPLAY_ID_1, 4)
            .set(SCORES_SIMILARITY.REPLAY_ID_2, 3)
            .set(SCORES_SIMILARITY.SIMILARITY, 0.5)
            .execute()

        dslContext.insertInto(SCORES)
            .set(SCORES.REPLAY_ID, 3)
            .set(SCORES.USER_ID, 1)
            .set(SCORES.DATE, LocalDateTime.now().minusDays(90))
            .execute()

        dslContext.insertInto(SCORES)
            .set(SCORES.REPLAY_ID, 4)
            .set(SCORES.USER_ID, 2)
            .set(SCORES.DATE, LocalDateTime.now().minusDays(90))
            .execute()

        //
        val results = scoreService.getSimilarReplaysForUserId(1)
        assertNotNull(results)
        assertEquals(1, results.size)
        assertEquals("naughty boy", results.first().username_1)
    }

}