package com.ruoyi.web.modules.industrypolicy.support;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Calendar;
import java.util.Date;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.ruoyi.common.exception.ServiceException;

/**
 * ZCZX-BTJL-UT-001～009
 */
@DisplayName("SubsidyGrantRecordValidation")
class SubsidyGrantRecordValidationTest
{
    private static final String VALID_ID_CARD = "11010519491231002X";

    private static final String VALID_PHONE = "13800138000";

    private static final String VALID_BANK = "6222021234567890";

    @Test
    @DisplayName("ZCZX-BTJL-UT-001 补贴项目名称长度")
    void ut001_projectName()
    {
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyProjectName(""));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyProjectName(longStr(21)));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateSubsidyProjectName("项目"));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-002 受补贴人姓名长度")
    void ut002_recipientName()
    {
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateRecipientName(""));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateRecipientName(longStr(11)));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateRecipientName("张三"));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-003 补贴类型枚举")
    void ut003_subsidyType()
    {
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateSubsidyType(1));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateSubsidyType(3));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyType(0));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyType(null));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-004 身份证号")
    void ut004_idCard()
    {
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateIdCard(VALID_ID_CARD));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateIdCard("12345678901234567"));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateIdCard("11010519491231002Y"));
        ServiceException maskedEx = org.junit.jupiter.api.Assertions.assertThrows(ServiceException.class,
                () -> SubsidyGrantRecordValidation.validateIdCard("1101**********002X"));
        org.junit.jupiter.api.Assertions.assertTrue(maskedEx.getMessage().contains("脱敏"));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-005 联系电话")
    void ut005_phone()
    {
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateContactPhone(VALID_PHONE));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateContactPhone("1234567890"));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateContactPhone("23800138000"));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-006 银行账户")
    void ut006_bankAccount()
    {
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateBankAccount(VALID_BANK));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateBankAccount("6222021234567890123"));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateBankAccount("622202123456789"));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateBankAccount("62220212345678901234"));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateBankAccount("6222abc1234567890"));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-007 补贴金额")
    void ut007_amount()
    {
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyAmount(BigDecimal.ZERO));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyAmount(new BigDecimal("-1")));
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateSubsidyAmount(new BigDecimal("100.555")));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateSubsidyAmount(new BigDecimal("0.01")));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateSubsidyAmount(new BigDecimal("999999.99")));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-008 发放日期")
    void ut008_grantDate()
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 1);
        assertThrows(ServiceException.class, () -> SubsidyGrantRecordValidation.validateGrantDate(cal.getTime()));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateGrantDate(new Date()));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-009 日期区间")
    void ut009_dateRange()
    {
        assertThrows(ServiceException.class,
                () -> SubsidyGrantRecordValidation.validateDateRange("2025-06-01", "2025-01-01"));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateDateRange("2025-01-01", "2025-06-01"));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateDateRange("2025-01-01", null));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateDateRange(null, "2025-06-01"));
        assertDoesNotThrow(() -> SubsidyGrantRecordValidation.validateDateRange("2025-01-01", "2025-01-01"));
    }

    @Test
    @DisplayName("ZCZX-BTJL-UT-013 列表排序 SQL")
    void ut013_listOrderBy() throws Exception
    {
        String path = "src/main/resources/mapper/industrypolicy/BizSubsidyGrantRecordMapper.xml";
        String xml = new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
        assertTrue(xml.contains("grant_date desc"));
        assertTrue(xml.contains("create_time desc"));
    }

    private static String longStr(int len)
    {
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++)
        {
            sb.append('x');
        }
        return sb.toString();
    }
}
