package cn.nianxx.thhotel.platform.identity.service.impl;

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

import cn.nianxx.thhotel.ThHotelApplication;
import java.time.LocalDateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest(
        classes = ThHotelApplication.class,
        properties = {
                "spring.datasource.url=jdbc:h2:mem:m003_bootstrap_review;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE",
                "auth.bootstrap.admin.username=",
                "auth.bootstrap.admin.password=",
                "auth.bootstrap.default-hotel-id=HOTEL-TEST",
                "auth.bootstrap.default-hotel-name=测试酒店"
        })
@ActiveProfiles("test")
class PlatformIdentityBootstrapRunnerTest {

    @Autowired
    private PlatformIdentityBootstrapRunner bootstrapRunner;

    @Autowired
    private AuthProperties authProperties;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @BeforeEach
    void cleanReviewRows() {
        authProperties.getBootstrap().getAdmin().setUsername("");
        authProperties.getBootstrap().getAdmin().setPassword("");
        authProperties.getBootstrap().getAdmin().setDisplayName("系统管理员");
        jdbcTemplate.update("DELETE FROM platform_user_role WHERE user_id IN (SELECT id FROM platform_user WHERE username LIKE 'm003-review-%')");
        jdbcTemplate.update("DELETE FROM platform_user_hotel WHERE user_id IN (SELECT id FROM platform_user WHERE username LIKE 'm003-review-%')");
        jdbcTemplate.update("DELETE FROM platform_user WHERE username LIKE 'm003-review-%'");
        jdbcTemplate.update("DELETE FROM platform_role_permission WHERE role_id IN (SELECT id FROM platform_role WHERE role_code = 'RESERVATION_VIEWER') AND permission_id IN (SELECT id FROM platform_permission WHERE permission_code = 'SYSTEM_DEBUG_EML_RUN')");
    }

    @Test
    void shouldCreateBootstrapAdminWhenOnlyDisabledSuperAdminExists() {
        LocalDateTime now = LocalDateTime.now();
        jdbcTemplate.update("""
                INSERT INTO platform_user (
                  id, username, password_hash, display_name, user_status, super_admin,
                  password_changed_at, created_at, updated_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
                """,
                9003001001L,
                "m003-review-disabled-admin",
                "{bcrypt}disabled",
                "Disabled Admin",
                "DISABLED",
                true,
                now,
                now,
                now);
        authProperties.getBootstrap().getAdmin().setUsername("m003-review-recovered-admin");
        authProperties.getBootstrap().getAdmin().setPassword("Recovered@123456");
        authProperties.getBootstrap().getAdmin().setDisplayName("恢复管理员");

        bootstrapRunner.run((ApplicationArguments) null);

        Integer activeSuperAdminCount = jdbcTemplate.queryForObject("""
                SELECT COUNT(*)
                FROM platform_user
                WHERE username = 'm003-review-recovered-admin'
                  AND user_status = 'ACTIVE'
                  AND super_admin = 1
                """, Integer.class);
        assertThat(activeSuperAdminCount).isEqualTo(1);
    }

    @Test
    void shouldRemoveStaleBuiltInRolePermissionsDuringBootstrap() {
        Long viewerRoleId = jdbcTemplate.queryForObject("""
                SELECT id FROM platform_role WHERE role_code = 'RESERVATION_VIEWER'
                """, Long.class);
        Long debugPermissionId = jdbcTemplate.queryForObject("""
                SELECT id FROM platform_permission WHERE permission_code = 'SYSTEM_DEBUG_EML_RUN'
                """, Long.class);
        jdbcTemplate.update("""
                INSERT INTO platform_role_permission (id, role_id, permission_id, created_at)
                VALUES (?, ?, ?, ?)
                """, 9003002001L, viewerRoleId, debugPermissionId, LocalDateTime.now());

        bootstrapRunner.run((ApplicationArguments) null);

        Integer staleCount = jdbcTemplate.queryForObject("""
                SELECT COUNT(*)
                FROM platform_role_permission
                WHERE role_id = ?
                  AND permission_id = ?
                """, Integer.class, viewerRoleId, debugPermissionId);
        assertThat(staleCount).isZero();
    }
}
