package com.cameleer.server.app.outbound;

import com.cameleer.server.app.AbstractPostgresIT;
import com.cameleer.server.app.alerting.storage.PostgresAlertRuleRepository;
import com.cameleer.server.core.alerting.*;
import com.cameleer.server.core.http.TrustMode;
import com.cameleer.server.core.outbound.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.server.ResponseStatusException;

import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.UUID;

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

class OutboundConnectionServiceRulesReferencingIT extends AbstractPostgresIT {

    @Autowired OutboundConnectionService service;
    @Autowired OutboundConnectionRepository repo;

    private UUID envId;
    private UUID connId;
    private UUID ruleId;
    private PostgresAlertRuleRepository ruleRepo;

    @BeforeEach
    void seed() {
        ruleRepo = new PostgresAlertRuleRepository(jdbcTemplate, new ObjectMapper());
        envId = UUID.randomUUID();
        jdbcTemplate.update(
            "INSERT INTO environments (id, slug, display_name) VALUES (?, ?, ?)",
            envId, "env-" + UUID.randomUUID(), "Test Env");
        jdbcTemplate.update(
            "INSERT INTO users (user_id, provider, email) VALUES ('u-ref', 'local', 'a@b.test')" +
            " ON CONFLICT (user_id) DO NOTHING");

        var c = repo.save(new OutboundConnection(
            UUID.randomUUID(), "default", "conn-" + UUID.randomUUID(), null,
            "https://example.test", OutboundMethod.POST,
            Map.of(), null, TrustMode.SYSTEM_DEFAULT, List.of(), null,
            new OutboundAuth.None(), List.of(),
            Instant.now(), "u-ref", Instant.now(), "u-ref"));
        connId = c.id();

        ruleId = UUID.randomUUID();
        var rule = new AlertRule(
            ruleId, envId, "r", null, AlertSeverity.WARNING, true,
            ConditionKind.AGENT_STATE,
            new AgentStateCondition(new AlertScope(null, null, null), "DEAD", 60),
            60, 0, 60, "t", "m",
            List.of(new WebhookBinding(UUID.randomUUID(), connId, null, Map.of())),
            List.of(), Instant.now(), null, null, Map.of(),
            Instant.now(), "u-ref", Instant.now(), "u-ref");
        ruleRepo.save(rule);
    }

    @AfterEach
    void cleanup() {
        jdbcTemplate.update("DELETE FROM alert_rules WHERE id = ?", ruleId);
        jdbcTemplate.update("DELETE FROM outbound_connections WHERE id = ?", connId);
        jdbcTemplate.update("DELETE FROM environments WHERE id = ?", envId);
        jdbcTemplate.update("DELETE FROM users WHERE user_id = 'u-ref'");
    }

    @Test
    void deleteConnectionReferencedByRuleReturns409() {
        assertThat(service.rulesReferencing(connId)).hasSize(1);
        assertThatThrownBy(() -> service.delete(connId, "u-ref"))
            .isInstanceOf(ResponseStatusException.class)
            .hasMessageContaining("referenced by rules");
    }
}
