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

import java.math.BigDecimal;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.farming.domain.BizTechResource;

/**
 * 畜牧科技资源入参校验。
 */
public final class TechResourceValidation
{
    private static final String PHONE_PATTERN = "^1[3-9]\\d{9}$";

    private static final DateTimeFormatter TIME_FMT = DateTimeFormatter.ofPattern("HH:mm");

    private TechResourceValidation()
    {
    }

    public static void validateListQuery(BizTechResource query)
    {
        if (query == null || StringUtils.isEmpty(query.getResourceType()))
        {
            throw new ServiceException("资源类型不能为空");
        }
        Integer ps = query.getQueryPublishStatus();
        if (ps != null && ps != TechResourceRules.QUERY_PUBLISH_UNPUBLISHED
                && ps != TechResourceRules.QUERY_PUBLISH_PUBLISHED
                && ps != TechResourceRules.QUERY_PUBLISH_OFFLINE)
        {
            throw new ServiceException("发布状态筛选无效");
        }
    }

    public static void trimFieldsForSave(BizTechResource row)
    {
        if (row == null)
        {
            return;
        }
        trim(row::getResourceName, row::setResourceName);
        trim(row::getIntroduction, row::setIntroduction);
        trim(row::getAchievementSummary, row::setAchievementSummary);
        trim(row::getKeyTechPrinciple, row::setKeyTechPrinciple);
        trim(row::getTechAdvantage, row::setTechAdvantage);
        trim(row::getResearchDirection, row::setResearchDirection);
        trim(row::getCompletionUnit, row::setCompletionUnit);
        trim(row::getContactPhone, row::setContactPhone);
        trim(row::getAffiliatedUnit, row::setAffiliatedUnit);
        trim(row::getDetailAddress, row::setDetailAddress);
        trim(row::getServiceArea, row::setServiceArea);
        trim(row::getPhotoFileUrl, row::setPhotoFileUrl);
        trim(row::getPhotoFilePath, row::setPhotoFilePath);
        trim(row::getCoverFileUrl, row::setCoverFileUrl);
        trim(row::getCoverFilePath, row::setCoverFilePath);
        trim(row::getVideoFileUrl, row::setVideoFileUrl);
        trim(row::getVideoFilePath, row::setVideoFilePath);
        trim(row::getServiceStartTime, row::setServiceStartTime);
        trim(row::getServiceEndTime, row::setServiceEndTime);
        trim(row::getInstrumentModel, row::setInstrumentModel);
        trim(row::getStorageLocation, row::setStorageLocation);
        trim(row::getReservationProcess, row::setReservationProcess);
        trim(row::getPersonInCharge, row::setPersonInCharge);
        trim(row::getCourseTopic, row::setCourseTopic);
        if (row.getRemark() != null)
        {
            String r = row.getRemark().trim();
            row.setRemark(r.isEmpty() ? null : r);
        }
        TechResourceMultiValueCodec.encodeLists(row);
    }

    private static void trim(java.util.function.Supplier<String> getter, java.util.function.Consumer<String> setter)
    {
        String v = getter.get();
        if (v != null)
        {
            setter.accept(v.trim());
        }
    }

    public static void validateResourceName(String name, String resourceType)
    {
        int max = TechResourceRules.maxNameLength(resourceType);
        if (StringUtils.isEmpty(name) || name.length() < TechResourceRules.MIN_NAME_LEN || name.length() > max)
        {
            throw new ServiceException("资源名称须为1～" + max + "个字符");
        }
    }

    public static void validateText(String text, String label, int maxLen, boolean required)
    {
        if (StringUtils.isEmpty(text))
        {
            if (required)
            {
                throw new ServiceException("请填写" + label);
            }
            return;
        }
        if (text.length() > maxLen)
        {
            throw new ServiceException(label + "不能超过" + maxLen + "个字符");
        }
    }

    public static void validateTextRequired(String text, String label, int maxLen)
    {
        validateText(text, label, maxLen, true);
    }

    public static void validateContactPhone(String phone, boolean required)
    {
        if (StringUtils.isEmpty(phone))
        {
            if (required)
            {
                throw new ServiceException("请填写联系方式");
            }
            return;
        }
        if (!phone.matches(PHONE_PATTERN))
        {
            throw new ServiceException("联系方式格式不正确");
        }
    }

    public static void validateAffiliatedUnit(String unit, boolean required)
    {
        if (StringUtils.isEmpty(unit))
        {
            if (required)
            {
                throw new ServiceException("请填写隶属单位");
            }
            return;
        }
        if (unit.length() > TechResourceRules.MAX_UNIT_LEN)
        {
            throw new ServiceException("隶属单位不能超过20个字符");
        }
    }

    public static void validatePositiveAmount(BigDecimal amount, String label, boolean required)
    {
        if (amount == null)
        {
            if (required)
            {
                throw new ServiceException("请填写" + label);
            }
            return;
        }
        if (amount.compareTo(BigDecimal.ZERO) <= 0)
        {
            throw new ServiceException(label + "须为正数");
        }
    }

    public static void validateServiceTimeRange(String start, String end, boolean required)
    {
        if (StringUtils.isEmpty(start) || StringUtils.isEmpty(end))
        {
            if (required)
            {
                throw new ServiceException("请填写服务时段");
            }
            return;
        }
        try
        {
            LocalTime s = LocalTime.parse(start, TIME_FMT);
            LocalTime e = LocalTime.parse(end, TIME_FMT);
            if (e.isBefore(s))
            {
                throw new ServiceException("结束时间不能早于开始时间");
            }
        }
        catch (DateTimeParseException ex)
        {
            throw new ServiceException("服务时段格式须为 HH:mm");
        }
    }

    public static void validateServiceWeekdays(List<Integer> weekdays, boolean required)
    {
        if (weekdays == null || weekdays.isEmpty())
        {
            if (required)
            {
                throw new ServiceException("请至少选择一天服务周日");
            }
            return;
        }
        for (Integer d : weekdays)
        {
            if (d == null || d < 1 || d > 7)
            {
                throw new ServiceException("服务周日无效");
            }
        }
    }

    public static void validatePhotoPair(String url, String path, boolean required)
    {
        boolean hasUrl = StringUtils.isNotEmpty(url);
        boolean hasPath = StringUtils.isNotEmpty(path);
        if (!hasUrl && !hasPath)
        {
            if (required)
            {
                throw new ServiceException("请上传照片");
            }
            return;
        }
        if (hasUrl != hasPath)
        {
            throw new ServiceException("照片 url 与 path 须同时填写或同时为空");
        }
        validateImagePath(path);
    }

    public static void validatePhotoPairRequired(String url, String path)
    {
        validatePhotoPair(url, path, true);
    }

    public static void validateCoverPairOptional(String url, String path)
    {
        boolean hasUrl = StringUtils.isNotEmpty(url);
        boolean hasPath = StringUtils.isNotEmpty(path);
        if (hasUrl != hasPath)
        {
            throw new ServiceException("封面 url 与 path 须同时填写或同时为空");
        }
        if (hasPath)
        {
            validateImagePath(path);
        }
    }

    public static void validateVideoPairRequired(String url, String path)
    {
        if (StringUtils.isEmpty(url) || StringUtils.isEmpty(path))
        {
            throw new ServiceException("请上传视频文件");
        }
        if (!TechResourceRules.isVideoExtensionAllowed(path))
        {
            throw new ServiceException("仅支持 mp4 格式视频");
        }
        if (!path.startsWith(Constants.RESOURCE_PREFIX))
        {
            throw new ServiceException("视频存储路径非法");
        }
    }

    private static void validateImagePath(String path)
    {
        if (!TechResourceRules.isImageExtensionAllowed(path))
        {
            throw new ServiceException("仅支持 jpg/jpeg/png，且不超过 10MB");
        }
        if (!path.startsWith(Constants.RESOURCE_PREFIX))
        {
            throw new ServiceException("照片存储路径非法");
        }
    }

    public static void validateRemark(String remark)
    {
        if (remark != null && remark.length() > TechResourceRules.MAX_REMARK_LEN)
        {
            throw new ServiceException("备注不能超过500个字符");
        }
    }

    public static void validateRowForSave(BizTechResource row)
    {
        trimFieldsForSave(row);
        if (!TechResourceRules.isResourceTypeValid(row.getResourceType()))
        {
            throw new ServiceException("资源类型无效");
        }
        validateResourceName(row.getResourceName(), row.getResourceType());
        validateRemark(row.getRemark());
        String type = row.getResourceType();
        if (TechResourceRules.RESOURCE_TYPE_EXPERT.equals(type))
        {
            validateExpert(row);
        }
        else if (TechResourceRules.RESOURCE_TYPE_ACHIEVEMENT.equals(type))
        {
            validateAchievement(row);
        }
        else if (TechResourceRules.RESOURCE_TYPE_INSTRUMENT.equals(type))
        {
            validateInstrument(row);
        }
        else if (TechResourceRules.RESOURCE_TYPE_VIDEO.equals(type))
        {
            validateVideo(row);
        }
        else
        {
            throw new ServiceException("资源类型无效");
        }
    }

    private static void validateExpert(BizTechResource row)
    {
        validatePhotoPair(row.getPhotoFileUrl(), row.getPhotoFilePath(), false);
        validateText(row.getIntroduction(), "专家介绍", TechResourceRules.MAX_INTRO_LEN, false);
        validateContactPhone(row.getContactPhone(), false);
        validateAffiliatedUnit(row.getAffiliatedUnit(), false);
        validateText(row.getDetailAddress(), "详细地址", TechResourceRules.MAX_ADDRESS_LEN, false);
        validateText(row.getServiceArea(), "服务区域", TechResourceRules.MAX_SERVICE_AREA_LEN, false);
        validatePositiveAmount(row.getFeeStandard(), "收费标准", false);
        validateServiceTimeRange(row.getServiceStartTime(), row.getServiceEndTime(), false);
        validateServiceWeekdays(row.getServiceWeekdaysList(), false);
    }

    private static void validateAchievement(BizTechResource row)
    {
        validateCoverPairOptional(row.getCoverFileUrl(), row.getCoverFilePath());
        validateText(row.getResearchDirection(), "研究方向", TechResourceRules.MAX_DIRECTION_LEN, true);
        validateText(row.getAchievementSummary(), "成果摘要", TechResourceRules.MAX_INTRO_LEN, false);
        validateText(row.getKeyTechPrinciple(), "关键技术原理", TechResourceRules.MAX_INTRO_LEN, false);
        validateText(row.getTechAdvantage(), "技术优势", TechResourceRules.MAX_INTRO_LEN, false);
        validateText(row.getCompletionUnit(), "完成单位", TechResourceRules.MAX_UNIT_LEN, false);
    }

    private static void validateInstrument(BizTechResource row)
    {
        validatePhotoPair(row.getPhotoFileUrl(), row.getPhotoFilePath(), false);
        validateText(row.getIntroduction(), "仪器介绍", TechResourceRules.MAX_INTRO_LEN, false);
        validateAffiliatedUnit(row.getAffiliatedUnit(), false);
        validateText(row.getStorageLocation(), "存放地点", TechResourceRules.MAX_ADDRESS_LEN, false);
        validateText(row.getReservationProcess(), "预约流程", TechResourceRules.MAX_INTRO_LEN, false);
        validateText(row.getPersonInCharge(), "负责人", TechResourceRules.MAX_NAME_LEN_SHORT, false);
        validateContactPhone(row.getContactPhone(), false);
        validateText(row.getInstrumentModel(), "仪器型号", TechResourceRules.MAX_MODEL_LEN, false);
        validatePositiveAmount(row.getBorrowFee(), "借用金额", false);
        validateServiceTimeRange(row.getServiceStartTime(), row.getServiceEndTime(), false);
        validateServiceWeekdays(row.getServiceWeekdaysList(), false);
    }

    private static void validateVideo(BizTechResource row)
    {
        validateText(row.getIntroduction(), "课程简介", TechResourceRules.MAX_INTRO_LEN, false);
        if (StringUtils.isEmpty(row.getCourseTopic()))
        {
            throw new ServiceException("课程主题不能为空");
        }
        validateVideoPairRequired(row.getVideoFileUrl(), row.getVideoFilePath());
        validateCoverPairOptional(row.getCoverFileUrl(), row.getCoverFilePath());
    }

    public static void validateForUpdate(BizTechResource db)
    {
        if (db == null)
        {
            throw new ServiceException("记录不存在或已删除");
        }
        if (!TechResourceRules.canEdit(db.getPublishStatus()))
        {
            throw new ServiceException("已发布资源请先下架后再编辑");
        }
    }

    public static void validateForDelete(BizTechResource db)
    {
        if (db == null)
        {
            throw new ServiceException("记录不存在或已删除");
        }
        if (!TechResourceRules.canDelete(db.getPublishStatus()))
        {
            throw new ServiceException("已发布资源请先下架后再删除");
        }
    }

    public static void validateForPublish(BizTechResource db)
    {
        if (db == null)
        {
            throw new ServiceException("记录不存在或已删除");
        }
        if (!TechResourceRules.canPublish(db.getPublishStatus()))
        {
            throw new ServiceException("该资源已发布");
        }
    }

    public static void validateForOffline(BizTechResource db)
    {
        if (db == null)
        {
            throw new ServiceException("记录不存在或已删除");
        }
        if (!TechResourceRules.canOffline(db.getPublishStatus()))
        {
            throw new ServiceException("仅已发布资源可下架");
        }
    }

    public static void validateForAssignAccount(BizTechResource db)
    {
        if (db == null)
        {
            throw new ServiceException("记录不存在或已删除");
        }
        if (!TechResourceRules.canAssignAccount(db.getResourceType()))
        {
            throw new ServiceException("该资源类型不支持分配账号");
        }
        if (!TechResourceRules.canEdit(db.getPublishStatus()))
        {
            throw new ServiceException("已发布资源请先下架后再操作");
        }
        if (db.getAccountAssigned() != null
                && db.getAccountAssigned() == TechResourceRules.ACCOUNT_ASSIGNED_YES)
        {
            throw new ServiceException("该资源已分配账号，不可重复分配");
        }
    }

    public static void validateResourceTypeUnchanged(BizTechResource db, BizTechResource input)
    {
        if (input.getResourceType() != null && !input.getResourceType().equals(db.getResourceType()))
        {
            throw new ServiceException("资源类型保存后不可变更");
        }
    }
}
