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;
import com.ruoyi.web.modules.industrypolicy.domain.BizSubsidyProject;

/**
 * ZCZX-BTXM-UT-005～011、017
 */
@DisplayName("SubsidyProjectValidation")
class SubsidyProjectValidationTest
{
    @Test
    @DisplayName("ZCZX-BTXM-UT-005 手工完成缺实际日")
    void ut005_manualCompleteNoActual()
    {
        BizSubsidyProject row = sampleRow();
        row.setExecStatus(SubsidyProjectRules.EXEC_COMPLETED);
        row.setActualEndDate(null);
        assertThrows(ServiceException.class, () -> SubsidyProjectStatusResolver.applySaveExecRules(row));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-006 项目名称长度")
    void ut006_projectName()
    {
        assertThrows(ServiceException.class, () -> SubsidyProjectValidation.validateProjectName(""));
        assertThrows(ServiceException.class, () -> SubsidyProjectValidation.validateProjectName(longStr(21)));
        assertDoesNotThrow(() -> SubsidyProjectValidation.validateProjectName("项目"));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-007 简介字数")
    void ut007_intro()
    {
        assertDoesNotThrow(() -> SubsidyProjectValidation.validateIntroduction(null));
        assertThrows(ServiceException.class, () -> SubsidyProjectValidation.validateIntroduction(longStr(51)));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-008 投资金额")
    void ut008_amount()
    {
        assertThrows(ServiceException.class, () -> SubsidyProjectValidation.validateInvestmentAmount(BigDecimal.ZERO));
        assertThrows(ServiceException.class, () -> SubsidyProjectValidation.validateInvestmentAmount(new BigDecimal("100.555")));
        assertDoesNotThrow(() -> SubsidyProjectValidation.validateInvestmentAmount(new BigDecimal("0.01")));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-009 计划日期先后")
    void ut009_planDates()
    {
        Date start = daysFromNow(0);
        Date endBefore = daysFromNow(-1);
        assertThrows(ServiceException.class, () -> SubsidyProjectValidation.validatePlanDates(start, endBefore));
        assertDoesNotThrow(() -> SubsidyProjectValidation.validatePlanDates(start, start));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-010 实际完成日")
    void ut010_actualEnd()
    {
        assertThrows(ServiceException.class,
                () -> SubsidyProjectValidation.validateActualEndDateWhenCompleted(daysFromNow(1)));
        assertDoesNotThrow(() -> SubsidyProjectValidation.validateActualEndDateWhenCompleted(daysFromNow(0)));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-011 开始日区间")
    void ut011_dateRange()
    {
        assertThrows(ServiceException.class,
                () -> SubsidyProjectValidation.validateDateRange("2025-12-01", "2025-01-01"));
        assertDoesNotThrow(() -> SubsidyProjectValidation.validateDateRange("2025-01-01", "2025-12-01"));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-017 封面后缀")
    void ut017_coverExt()
    {
        assertTrue(SubsidyProjectRules.isCoverExtensionAllowed("a.jpg"));
        org.junit.jupiter.api.Assertions.assertFalse(SubsidyProjectRules.isCoverExtensionAllowed("a.exe"));
    }

    @Test
    @DisplayName("列表排序 SQL")
    void listOrderBy() throws Exception
    {
        String path = "src/main/resources/mapper/industrypolicy/BizSubsidyProjectMapper.xml";
        String xml = new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
        assertTrue(xml.contains("project_start_date desc"));
        assertTrue(xml.contains("create_time desc"));
    }

    private static BizSubsidyProject sampleRow()
    {
        BizSubsidyProject r = new BizSubsidyProject();
        r.setProjectName("示范项目");
        r.setInvestmentAmount(new BigDecimal("10000"));
        r.setProjectStartDate(daysFromNow(-1));
        r.setPlannedEndDate(daysFromNow(10));
        r.setExecStatus(SubsidyProjectRules.EXEC_IN_PROGRESS);
        return r;
    }

    private static Date daysFromNow(int delta)
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, delta);
        return SubsidyProjectStatusResolver.truncateToDay(cal.getTime());
    }

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