package net.siegeln.cameleer.saas.audit;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Map;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class AuditServiceTest {

    @Mock
    private AuditRepository auditRepository;

    private AuditService auditService;

    @BeforeEach
    void setUp() {
        auditService = new AuditService(auditRepository);
    }

    @Test
    void log_createsAuditEntryWithAllFields() {
        UUID actorId = UUID.randomUUID();
        UUID tenantId = UUID.randomUUID();
        String actorEmail = "user@example.com";
        String resource = "/api/tenants/123";
        String environment = "production";
        String sourceIp = "192.168.1.1";
        String result = "SUCCESS";
        Map<String, Object> metadata = Map.of("key", "value");

        auditService.log(actorId, actorEmail, tenantId,
                AuditAction.TENANT_CREATE, resource,
                environment, sourceIp, result, metadata);

        ArgumentCaptor<AuditEntity> captor = ArgumentCaptor.forClass(AuditEntity.class);
        verify(auditRepository).save(captor.capture());

        AuditEntity saved = captor.getValue();
        assertEquals(actorId, saved.getActorId());
        assertEquals(actorEmail, saved.getActorEmail());
        assertEquals(tenantId, saved.getTenantId());
        assertEquals("TENANT_CREATE", saved.getAction());
        assertEquals(resource, saved.getResource());
        assertEquals(environment, saved.getEnvironment());
        assertEquals(sourceIp, saved.getSourceIp());
        assertEquals("SUCCESS", saved.getResult());
        assertEquals(metadata, saved.getMetadata());
    }

    @Test
    void log_worksWithNullOptionalFields() {
        auditService.log(null, null, null,
                AuditAction.AUTH_LOGIN, null,
                null, null, null, null);

        ArgumentCaptor<AuditEntity> captor = ArgumentCaptor.forClass(AuditEntity.class);
        verify(auditRepository).save(captor.capture());

        AuditEntity saved = captor.getValue();
        assertNull(saved.getActorId());
        assertNull(saved.getActorEmail());
        assertNull(saved.getTenantId());
        assertEquals("AUTH_LOGIN", saved.getAction());
        assertNull(saved.getResource());
        assertNull(saved.getEnvironment());
        assertNull(saved.getSourceIp());
        assertEquals("SUCCESS", saved.getResult()); // defaults to SUCCESS when null
        assertNull(saved.getMetadata());
    }
}
