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

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

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Calendar;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.diagnosis.MedicalResourceTestSamples;
import com.ruoyi.web.modules.diagnosis.domain.BizMedicalResource;

@DisplayName("MedicalResourceValidation")
class MedicalResourceValidationTest
{

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

    @Test
    @DisplayName("兽医仅姓名与接诊方式可保存")
    void vetOnlyRequiredFields()
    {
        BizMedicalResource row = new BizMedicalResource();
        row.setResourceType(MedicalResourceRules.RESOURCE_TYPE_VET);
        row.setResourceName("测试兽医");
        row.setConsultModesList(Arrays.asList(1));
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("兽医填写服务时段非法仍失败")
    void vetInvalidServiceTime()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleVetDraft();
        row.setServiceStartTime("18:00");
        row.setServiceEndTime("08:00");
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("兽医服务时段")
    void serviceTimeRange()
    {
        assertDoesNotThrow(() -> MedicalResourceValidation.validateServiceTimeRange("08:00", "18:00", true));
        assertThrows(ServiceException.class,
                () -> MedicalResourceValidation.validateServiceTimeRange("18:00", "08:00", true));
        assertDoesNotThrow(() -> MedicalResourceValidation.validateServiceTimeRange(null, null, false));
    }
    void contactPhone()
    {
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateContactPhone("123", true));
        assertDoesNotThrow(() -> MedicalResourceValidation.validateContactPhone("13800138000", true));
    }

    @Test
    @DisplayName("收费标准")
    void feeStandard()
    {
        assertThrows(ServiceException.class,
                () -> MedicalResourceValidation.validateFeeStandard(BigDecimal.ZERO, true));
        assertDoesNotThrow(() -> MedicalResourceValidation.validateFeeStandard(new BigDecimal("100"), true));
    }

    @Test
    @DisplayName("设备不要求手机")
    void equipmentNoPhone()
    {
        BizMedicalResource row = new BizMedicalResource();
        row.setResourceType(MedicalResourceRules.RESOURCE_TYPE_EQUIPMENT);
        row.setResourceName("B超仪");
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("设备仅设备名称可保存")
    void equipmentOptionalProfileFields()
    {
        BizMedicalResource row = new BizMedicalResource();
        row.setResourceType(MedicalResourceRules.RESOURCE_TYPE_EQUIPMENT);
        row.setResourceName("B超仪");
        row.setPhotoFileUrl(null);
        row.setPhotoFilePath(null);
        row.setIntroduction(null);
        row.setEquipmentModel(null);
        row.setAffiliatedUnit(null);
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("设备填写型号超长失败")
    void equipmentInvalidModel()
    {
        BizMedicalResource row = new BizMedicalResource();
        row.setResourceType(MedicalResourceRules.RESOURCE_TYPE_EQUIPMENT);
        row.setResourceName("B超仪");
        row.setEquipmentModel("12345678901");
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("兽医缺收费可保存")
    void vetMissingFeeAllowed()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleVetDraft();
        row.setFeeStandard(null);
        row.setServiceArea(null);
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("兽医填写收费须为正数")
    void vetInvalidFee()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleVetDraft();
        row.setFeeStandard(BigDecimal.ZERO);
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("已发布不可改")
    void updatePublished()
    {
        BizMedicalResource db = MedicalResourceTestSamples.samplePublishedVet();
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateForUpdate(db));
    }

    @Test
    @DisplayName("仅已发布可下架")
    void offlineRules()
    {
        BizMedicalResource draft = MedicalResourceTestSamples.sampleVetDraft();
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateForOffline(draft));
        assertDoesNotThrow(() -> MedicalResourceValidation.validateForOffline(
                MedicalResourceTestSamples.samplePublishedVet()));
    }

    @Test
    @DisplayName("分配账号类型与次数")
    void assignAccount()
    {
        BizMedicalResource team = MedicalResourceTestSamples.sampleTeamDraft();
        team.setId(1L);
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateForAssignAccount(team));
        BizMedicalResource assigned = MedicalResourceTestSamples.sampleVetDraft();
        assigned.setId(1L);
        assigned.setAccountAssigned(MedicalResourceRules.ACCOUNT_ASSIGNED_YES);
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateForAssignAccount(assigned));
    }

    @Test
    @DisplayName("团队成立时间未来")
    void establishDateFuture()
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.YEAR, 1);
        assertThrows(ServiceException.class,
                () -> MedicalResourceValidation.validateEstablishDate(cal.getTime(), true));
    }

    @Test
    @DisplayName("兽医不要求单日最大接诊")
    void vetNoMaxDaily()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleVetDraft();
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
        row.setMaxDailyAppointments(20);
        MedicalResourceValidation.validateRowForSave(row);
        assertNull(row.getMaxDailyAppointments());
    }

    @Test
    @DisplayName("兽医仅必填业务字段可保存")
    void vetOptionalProfileFields()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleVetDraft();
        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(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("兽医选填手机号格式仍校验")
    void vetOptionalPhoneFormat()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleVetDraft();
        row.setContactPhone("123");
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("专家团队仅团队名称可保存")
    void teamOptionalProfileFields()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleTeamDraft();
        row.setPhotoFileUrl(null);
        row.setPhotoFilePath(null);
        row.setIntroduction(null);
        row.setContactPhone(null);
        row.setAffiliatedUnit(null);
        row.setEstablishDate(null);
        row.setTeamSize(null);
        row.setPersonInCharge(null);
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("专家团队填写规模须为正整数")
    void teamInvalidSize()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleTeamDraft();
        row.setTeamSize(0);
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("诊疗机构资料选填保留级别")
    void orgOptionalProfileFields()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleOrgDraft();
        row.setPhotoFileUrl(null);
        row.setPhotoFilePath(null);
        row.setIntroduction(null);
        row.setDetailAddress(null);
        row.setPersonInCharge(null);
        row.setContactPhone(null);
        row.setMaxDailyAppointments(null);
        row.setServiceStartTime(null);
        row.setServiceEndTime(null);
        row.setServiceWeekdaysList(null);
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("诊疗机构缺级别失败")
    void orgMissingLevel()
    {
        BizMedicalResource row = new BizMedicalResource();
        row.setResourceType(MedicalResourceRules.RESOURCE_TYPE_ORG);
        row.setResourceName("县动物医院");
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("诊疗机构名称与级别可保存")
    void orgNameAndLevel()
    {
        BizMedicalResource row = new BizMedicalResource();
        row.setResourceType(MedicalResourceRules.RESOURCE_TYPE_ORG);
        row.setResourceName("县动物医院");
        row.setOrgLevel(MedicalResourceRules.ORG_LEVEL_CLINIC);
        assertDoesNotThrow(() -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("诊疗机构填写单日接诊须为正整数")
    void orgInvalidMaxDaily()
    {
        BizMedicalResource row = MedicalResourceTestSamples.sampleOrgDraft();
        row.setMaxDailyAppointments(0);
        assertThrows(ServiceException.class, () -> MedicalResourceValidation.validateRowForSave(row));
    }

    @Test
    @DisplayName("接诊方式至少一项")
    void consultModes()
    {
        assertThrows(ServiceException.class,
                () -> MedicalResourceValidation.validateConsultModes(Arrays.asList(), true));
        assertDoesNotThrow(() -> MedicalResourceValidation.validateConsultModes(Arrays.asList(1), true));
    }
}
