package com.yimeng.okr.config;

import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class DatabaseMigrationRunnerTest {

    @Test
    void runAppliesVersionedMigrationsOnlyOnce() {
        JdbcTemplate jdbcTemplate = jdbcTemplate();
        jdbcTemplate.execute("""
                CREATE TABLE sys_user (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    username VARCHAR(64) NOT NULL UNIQUE,
                    password_hash VARCHAR(256) NOT NULL,
                    real_name VARCHAR(64) NOT NULL,
                    role VARCHAR(20) NOT NULL DEFAULT 'EMPLOYEE',
                    deleted INTEGER NOT NULL DEFAULT 0,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL
                )
                """);
        jdbcTemplate.execute("""
                CREATE TABLE performance_score (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    period_id INTEGER NOT NULL,
                    user_id INTEGER NOT NULL,
                    evaluator_id INTEGER NOT NULL,
                    type VARCHAR(20) NOT NULL,
                    deleted INTEGER NOT NULL DEFAULT 0,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL
                )
                """);
        jdbcTemplate.execute("""
                CREATE TABLE performance_feedback (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    period_id INTEGER NOT NULL,
                    user_id INTEGER NOT NULL,
                    superior_id INTEGER NOT NULL,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL
                )
                """);
        jdbcTemplate.execute("""
                CREATE TABLE okr_objective (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    period_id INTEGER NOT NULL,
                    title VARCHAR(256) NOT NULL,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL
                )
                """);

        DatabaseMigrationRunner runner = new DatabaseMigrationRunner(jdbcTemplate);
        runner.run();
        runner.run();

        assertColumnExists(jdbcTemplate, "sys_user", "status");
        assertColumnExists(jdbcTemplate, "performance_score", "published_at");
        assertTableExists(jdbcTemplate, "period_participant");
        assertEquals(1, jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM schema_migration WHERE version = 1", Integer.class));
    }

    private JdbcTemplate jdbcTemplate() {
        SingleConnectionDataSource dataSource = new SingleConnectionDataSource();
        dataSource.setDriverClassName("org.sqlite.JDBC");
        dataSource.setUrl("jdbc:sqlite::memory:");
        dataSource.setSuppressClose(true);
        return new JdbcTemplate(dataSource);
    }

    private void assertColumnExists(JdbcTemplate jdbcTemplate, String tableName, String columnName) {
        boolean exists = jdbcTemplate.queryForList("PRAGMA table_info(" + tableName + ")").stream()
                .anyMatch(row -> columnName.equalsIgnoreCase(String.valueOf(row.get("name"))));
        assertTrue(exists, tableName + "." + columnName + " should exist");
    }

    private void assertTableExists(JdbcTemplate jdbcTemplate, String tableName) {
        Integer count = jdbcTemplate.queryForObject("""
                SELECT COUNT(*) FROM sqlite_master
                WHERE type = 'table' AND name = ?
                """, Integer.class, tableName);
        assertEquals(1, count);
    }
}
