package com.magistr.app.controller;

import com.magistr.app.config.tenant.TenantConfigWatcher;
import com.magistr.app.config.tenant.TenantRoutingDataSource;
import com.magistr.app.service.TenantLifecycleException;
import com.magistr.app.service.TenantLifecycleService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.servlet.MockMvc;

import java.util.Map;
import java.util.function.Supplier;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;

class DatabaseControllerTest {

    private TenantLifecycleService lifecycleService;
    private TenantConfigWatcher tenantConfigWatcher;
    private MockMvc mockMvc;

    @BeforeEach
    void setUp() {
        TenantRoutingDataSource routingDataSource = mock(TenantRoutingDataSource.class);
        lifecycleService = mock(TenantLifecycleService.class);
        tenantConfigWatcher = mock(TenantConfigWatcher.class);
        mockMvc = standaloneSetup(new DatabaseController(
                routingDataSource,
                lifecycleService,
                tenantConfigWatcher
        )).build();
    }

    @Test
    void returnsServiceUnavailableInsteadOfFalseSuccessWhenLifecycleFails() throws Exception {
        when(lifecycleService.executeSerialized(
                org.mockito.ArgumentMatchers.<Supplier<ResponseEntity<Map<String, Object>>>>any()
        )).thenThrow(new TenantLifecycleException(
                "Не удалось выполнить миграции базы данных тенанта",
                new IllegalStateException("тестовые технические детали JDBC")
        ));

        mockMvc.perform(post("/api/database/tenants")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content("""
                                {
                                  "name": "Тестовый университет",
                                  "domain": "test",
                                  "url": "jdbc:postgresql://db/test",
                                  "username": "user",
                                  "password": "password"
                                }
                                """))
                .andExpect(status().isServiceUnavailable())
                .andExpect(jsonPath("$.success").value(false))
                .andExpect(jsonPath("$.message")
                        .value("Не удалось выполнить миграции базы данных тенанта"))
                .andExpect(jsonPath("$.message")
                        .value(org.hamcrest.Matchers.not(org.hamcrest.Matchers.containsString("JDBC"))));

        verify(tenantConfigWatcher, never()).refreshHash();
        verify(lifecycleService).executeSerialized(any(Supplier.class));
    }
}
