package com.mosquito.project.service;

import com.mosquito.project.permission.PermissionCheckService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

/**
 * 敏感数据脱敏服务测试
 */
@ExtendWith(MockitoExtension.class)
class SensitiveMaskingServiceTest {

    @Mock
    private PermissionCheckService permissionCheckService;

    @InjectMocks
    private SensitiveMaskingService service;

    // ========== 邮箱脱敏测试 ==========

    @Test
    void maskEmail_normalEmail_returnsMasked() {
        // 默认规则脱敏邮箱，只保留第一个字符
        String result = service.maskEmail("user@example.com");
        assertEquals("u***@example.com", result);
    }

    @Test
    void maskEmail_shortLocalPart_returnsCorrectMask() {
        // 默认规则脱敏邮箱
        String result = service.maskEmail("ab@domain.com");
        assertEquals("a***@domain.com", result);
    }

    @Test
    void maskEmail_singleCharLocalPart_returnsCorrectMask() {
        // 默认规则脱敏邮箱
        String result = service.maskEmail("a@domain.com");
        assertEquals("***@domain.com", result);
    }

    @Test
    void maskEmail_invalidEmail_returnsOriginal() {
        // 非标准邮箱不脱敏
        assertEquals("not-an-email", service.maskEmail("not-an-email"));
    }

    @Test
    void maskEmail_nullOrBlank_returnsEmpty() {
        assertEquals("", service.maskEmail(""));
        assertEquals("", service.maskEmail(null));
    }

    @Test
    void maskEmail_complexDomain_returnsMasked() {
        // 默认规则脱敏邮箱
        String result = service.maskEmail("test.user@sub.domain.co.uk");
        assertEquals("t***@sub.domain.co.uk", result);
    }

    @Test
    void maskEmail_specialCharsInLocalPart_returnsMasked() {
        // 默认规则脱敏邮箱
        String result = service.maskEmail("test+tag@domain.com");
        assertEquals("t***@domain.com", result);
    }

    // ========== 手机号脱敏测试 ==========

    @Test
    void maskPhone_validPhone_returnsMasked() {
        String result = service.maskPhone("13812345678");
        assertEquals("138****5678", result);
    }

    @Test
    void maskPhone_invalidPhone_returnsOriginal() {
        assertEquals("12345", service.maskPhone("12345"));
        assertEquals("", service.maskPhone(""));
        assertEquals("", service.maskPhone(null));
    }

    // ========== 身份证脱敏测试 ==========

    @Test
    void maskIdCard_15digit_returnsMasked() {
        String result = service.maskIdCard("310110199001011");
        // 规则6-4: 保留前6位和后4位，中间4位脱敏
        assertEquals("310110*****1011", result);
    }

    @Test
    void maskIdCard_18digit_returnsMasked() {
        String result = service.maskIdCard("310110199001011234");
        // 规则6-4: 保留前6位和后4位，中间8位脱敏
        assertEquals("310110********1234", result);
    }

    // ========== 银行卡脱敏测试 ==========

    @Test
    void maskBankCard_16digit_returnsMasked() {
        String result = service.maskBankCard("6222021234567890");
        assertEquals("6222********7890", result);
    }

    @Test
    void maskBankCard_19digit_returnsMasked() {
        String result = service.maskBankCard("6222021234567890123");
        assertEquals("6222***********0123", result);
    }

    // ========== 权限判断测试 ==========

    @Test
    void mask_withSensitivePermission_returnsOriginal() {
        // 有权限用户返回原值
        when(permissionCheckService.hasPermission(anyLong(), eq("system.sensitive.access.ALL"))).thenReturn(true);
        String result = service.mask("13812345678", "phone", 1L);
        assertEquals("13812345678", result);
    }

    @Test
    void mask_withoutSensitivePermission_returnsMasked() {
        // 无权限用户返回脱敏值
        when(permissionCheckService.hasPermission(anyLong(), eq("system.sensitive.access.ALL"))).thenReturn(false);
        String result = service.mask("13812345678", "phone", 1L);
        assertEquals("138****5678", result);
    }
}
