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

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

import java.math.BigDecimal;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.farming.TechResourceTestSamples;
import com.ruoyi.web.modules.farming.domain.BizTechResource;

@DisplayName("TechResourceValidation")
class TechResourceValidationTest
{

    @Test
    @DisplayName("服务时段")
    void serviceTimeRange()
    {
        assertThrows(ServiceException.class,
                () -> TechResourceValidation.validateServiceTimeRange("18:00", "08:00", true));
        assertDoesNotThrow(() -> TechResourceValidation.validateServiceTimeRange("08:00", "18:00", true));
    }

    @Test
    @DisplayName("服务周日选填")
    void serviceWeekdaysOptional()
    {
        assertDoesNotThrow(() -> TechResourceValidation.validateServiceWeekdays(null, false));
    }

    @Test
    @DisplayName("成果缺研究方向失败")
    void achievementMissingDirection()
    {
        BizTechResource row = new BizTechResource();
        row.setResourceType(TechResourceRules.RESOURCE_TYPE_ACHIEVEMENT);
        row.setResourceName("育种新技术成果");
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("成果名称与研究方向可保存")
    void achievementNameAndDirection()
    {
        BizTechResource row = new BizTechResource();
        row.setResourceType(TechResourceRules.RESOURCE_TYPE_ACHIEVEMENT);
        row.setResourceName("育种新技术成果");
        row.setResearchDirection("繁育");
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("成果摘要超长失败")
    void achievementSummaryTooLong()
    {
        BizTechResource row = TechResourceTestSamples.sampleAchievementDraft();
        row.setAchievementSummary(repeat('x', 501));
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("课程缺视频失败")
    void videoMissingFile()
    {
        BizTechResource row = TechResourceTestSamples.sampleVideoDraft();
        row.setVideoFilePath(null);
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("课程简介选填")
    void videoOptionalIntro()
    {
        BizTechResource row = TechResourceTestSamples.sampleVideoDraft();
        row.setIntroduction(null);
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("借用金额须为正数")
    void borrowFee()
    {
        assertThrows(ServiceException.class,
                () -> TechResourceValidation.validatePositiveAmount(BigDecimal.ZERO, "借用金额", true));
    }

    @Test
    @DisplayName("专家仅姓名可保存")
    void expertOnlyName()
    {
        BizTechResource row = new BizTechResource();
        row.setResourceType(TechResourceRules.RESOURCE_TYPE_EXPERT);
        row.setResourceName("测试专家");
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("专家资料选填")
    void expertOptionalProfileFields()
    {
        BizTechResource row = TechResourceTestSamples.sampleExpertDraft();
        row.setPhotoFileUrl(null);
        row.setPhotoFilePath(null);
        row.setIntroduction(null);
        row.setContactPhone(null);
        row.setAffiliatedUnit(null);
        row.setDetailAddress(null);
        row.setServiceArea(null);
        row.setFeeStandard(null);
        row.setServiceStartTime(null);
        row.setServiceEndTime(null);
        row.setServiceWeekdaysList(null);
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("专家填写服务时段非法仍失败")
    void expertInvalidServiceTime()
    {
        BizTechResource row = TechResourceTestSamples.sampleExpertDraft();
        row.setServiceStartTime("18:00");
        row.setServiceEndTime("08:00");
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("专家填写收费须为正数")
    void expertInvalidFee()
    {
        BizTechResource row = TechResourceTestSamples.sampleExpertDraft();
        row.setFeeStandard(BigDecimal.ZERO);
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("共享仪器仅名称可保存")
    void instrumentOnlyName()
    {
        BizTechResource row = new BizTechResource();
        row.setResourceType(TechResourceRules.RESOURCE_TYPE_INSTRUMENT);
        row.setResourceName("显微镜");
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("共享仪器资料选填")
    void instrumentOptionalProfileFields()
    {
        BizTechResource row = TechResourceTestSamples.sampleInstrumentDraft();
        row.setPhotoFileUrl(null);
        row.setPhotoFilePath(null);
        row.setIntroduction(null);
        row.setInstrumentModel(null);
        row.setAffiliatedUnit(null);
        row.setStorageLocation(null);
        row.setReservationProcess(null);
        row.setPersonInCharge(null);
        row.setContactPhone(null);
        row.setBorrowFee(null);
        row.setServiceStartTime(null);
        row.setServiceEndTime(null);
        row.setServiceWeekdaysList(null);
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("类型字段矩阵")
    void typeMatrix()
    {
        BizTechResource achievement = TechResourceTestSamples.sampleAchievementDraft();
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(achievement));
        BizTechResource expert = TechResourceTestSamples.sampleExpertDraft();
        expert.setFeeStandard(null);
        assertDoesNotThrow(() -> TechResourceValidation.validateRowForSave(expert));
    }

    @Test
    @DisplayName("已发布不可改")
    void updatePublished()
    {
        assertThrows(ServiceException.class,
                () -> TechResourceValidation.validateForUpdate(TechResourceTestSamples.samplePublishedExpert()));
    }

    @Test
    @DisplayName("分配账号仅专家")
    void assignAccount()
    {
        BizTechResource achievement = TechResourceTestSamples.sampleAchievementDraft();
        achievement.setId(1L);
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateForAssignAccount(achievement));
    }

    @Test
    @DisplayName("已分配不可重复")
    void assignAccountAlready()
    {
        BizTechResource expert = TechResourceTestSamples.sampleExpertDraft();
        expert.setAccountAssigned(TechResourceRules.ACCOUNT_ASSIGNED_YES);
        assertThrows(ServiceException.class, () -> TechResourceValidation.validateForAssignAccount(expert));
    }

    private static String repeat(char c, int n)
    {
        StringBuilder sb = new StringBuilder(n);
        for (int i = 0; i < n; i++)
        {
            sb.append(c);
        }
        return sb.toString();
    }
}
