package com.mosquito.project.service;

import com.mosquito.project.persistence.entity.SysAuditLogEntity;
import com.mosquito.project.persistence.repository.SysAuditLogRepository;
import com.mosquito.project.permission.PermissionCheckService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
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.HashMap;
import java.util.Map;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
@DisplayName("审计服务测试")
class AuditServiceTest {

    @Mock
    private SysAuditLogRepository auditLogRepository;

    @Mock
    private PermissionCheckService permissionCheckService;

    private AuditService auditService;

    @BeforeEach
    void setUp() {
        when(auditLogRepository.findMaxSequenceNum()).thenReturn(0L);
        when(auditLogRepository.findTopByOrderBySequenceNumDesc()).thenReturn(Optional.empty());
        when(auditLogRepository.save(any(SysAuditLogEntity.class))).thenAnswer(invocation -> {
            SysAuditLogEntity entity = invocation.getArgument(0);
            entity.setId(100L);
            return entity;
        });
        auditService = new AuditService(auditLogRepository, permissionCheckService);
    }

    @Test
    @DisplayName("recordAuditLog 应容忍匿名 userId 并正常写入")
    void shouldHandleAnonymousUserId() {
        Map<String, Object> logData = new HashMap<>();
        logData.put("userId", "anonymous");
        logData.put("userName", "匿名用户");
        logData.put("operation", "CALLBACK_REGISTER");

        Long savedId = assertDoesNotThrow(() -> auditService.recordAuditLog(logData));
        assertEquals(100L, savedId);

        ArgumentCaptor<SysAuditLogEntity> captor = ArgumentCaptor.forClass(SysAuditLogEntity.class);
        verify(auditLogRepository).save(captor.capture());
        SysAuditLogEntity saved = captor.getValue();
        assertNull(saved.getUserId());
        assertEquals("匿名用户", saved.getUserName());
        assertEquals("CALLBACK_REGISTER", saved.getOperation());
    }

    @Test
    @DisplayName("recordAuditLog 应解析数字 userId")
    void shouldParseNumericUserId() {
        Map<String, Object> logData = new HashMap<>();
        logData.put("userId", " 42 ");
        logData.put("userName", "系统管理员");
        logData.put("operation", "LOGIN");

        Long savedId = auditService.recordAuditLog(logData);
        assertEquals(100L, savedId);

        ArgumentCaptor<SysAuditLogEntity> captor = ArgumentCaptor.forClass(SysAuditLogEntity.class);
        verify(auditLogRepository).save(captor.capture());
        SysAuditLogEntity saved = captor.getValue();
        assertEquals(42L, saved.getUserId());
        assertEquals("系统管理员", saved.getUserName());
        assertEquals("LOGIN", saved.getOperation());
    }
}
