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

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.regex.Pattern;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.booking.domain.AppBookingSubmitBody;
import com.ruoyi.web.modules.booking.domain.vo.AppointmentResourceVo;

/**
 * 移动端提交预约校验。
 */
public final class AppBookingSubmitValidation
{
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

    private static final Pattern TIME_SLOT_PATTERN = Pattern.compile("^\\d{2}:\\d{2}~\\d{2}:\\d{2}$");

    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ISO_LOCAL_DATE;

    private AppBookingSubmitValidation()
    {
    }

    public static void validateBody(AppBookingSubmitBody body)
    {
        if (body == null)
        {
            throw new ServiceException("请求体不能为空");
        }
        if (body.getResourceId() == null)
        {
            throw new ServiceException("请选择预约对象");
        }
        if (StringUtils.isEmpty(body.getResourceType()))
        {
            throw new ServiceException("资源类型不能为空");
        }
        String type = body.getResourceType().trim();
        if (!AppointmentResourceRules.isAllowedResourceType(type))
        {
            throw new ServiceException("资源类型无效");
        }
        body.setResourceType(type);
        body.setAppointeeName(trimRequired(body.getAppointeeName(), "预约人", AppointmentResourceRules.MAX_APPOINTEE_NAME_LEN));
        body.setContactPhone(validatePhone(body.getContactPhone()));
        resolveTimeRange(body);
        body.setServiceAddress(trimRequired(body.getServiceAddress(), "服务地址", AppointmentResourceRules.MAX_ADDRESS_LEN));
        if (body.getServiceRequirement() != null)
        {
            body.setServiceRequirement(body.getServiceRequirement().trim());
            if (body.getServiceRequirement().length() > AppointmentResourceRules.MAX_REQUIREMENT_LEN)
            {
                throw new ServiceException("服务需求过长");
            }
        }
        parseAppointDate(body.getAppointDate());
    }

    public static LocalDate parseAppointDate(String appointDate)
    {
        if (StringUtils.isEmpty(appointDate))
        {
            throw new ServiceException("请选择预约日期");
        }
        try
        {
            return LocalDate.parse(appointDate.trim(), DATE_FMT);
        }
        catch (DateTimeParseException ex)
        {
            throw new ServiceException("预约日期格式无效");
        }
    }

    public static void assertServiceWeekdayAllowed(AppointmentResourceVo resource, LocalDate appointDate)
    {
        if (resource == null || StringUtils.isEmpty(resource.getServiceWeekdays()))
        {
            return;
        }
        int weekday = AppointmentBookingDateSupport.toWeekdayNumber(appointDate);
        String token = String.valueOf(weekday);
        for (String part : resource.getServiceWeekdays().split(","))
        {
            if (token.equals(part.trim()))
            {
                return;
            }
        }
        throw new ServiceException("所选日期不在服务日内");
    }

    private static void resolveTimeRange(AppBookingSubmitBody body)
    {
        if (StringUtils.isNotEmpty(body.getTimeStart()) && StringUtils.isNotEmpty(body.getTimeEnd()))
        {
            return;
        }
        String slot = body.getTimeSlot();
        if (StringUtils.isEmpty(slot))
        {
            throw new ServiceException("请选择预约时段");
        }
        slot = slot.trim();
        if (!TIME_SLOT_PATTERN.matcher(slot).matches())
        {
            throw new ServiceException("预约时段格式无效");
        }
        int sep = slot.indexOf('~');
        body.setTimeStart(slot.substring(0, sep));
        body.setTimeEnd(slot.substring(sep + 1));
    }

    private static String validatePhone(String phone)
    {
        if (StringUtils.isEmpty(phone))
        {
            throw new ServiceException("请填写联系电话");
        }
        String trimmed = phone.trim();
        if (!PHONE_PATTERN.matcher(trimmed).matches())
        {
            throw new ServiceException("联系电话格式无效");
        }
        return trimmed;
    }

    private static String trimRequired(String value, String label, int maxLen)
    {
        if (StringUtils.isEmpty(value) || value.trim().isEmpty())
        {
            throw new ServiceException(label + "不能为空");
        }
        String trimmed = value.trim();
        if (trimmed.length() > maxLen)
        {
            throw new ServiceException(label + "过长");
        }
        return trimmed;
    }
}
