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

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.trading.domain.BizMarketEntry;
import com.ruoyi.web.modules.trading.domain.BizMarketStall;
import com.ruoyi.web.modules.trading.domain.BizSupplier;
import com.ruoyi.web.modules.trading.mapper.BizMarketStallMapper;
import com.ruoyi.web.modules.trading.mapper.BizSupplierMapper;

/**
 * 市场进栏登记校验（M1～M4、外键、进栏时间、列表日期区间）。
 */
@Component
public class MarketEntryValidation
{
    private static final String DATE_PATTERN = "yyyy-MM-dd";

    @Autowired
    private BizMarketStallMapper bizMarketStallMapper;

    @Autowired
    private BizSupplierMapper bizSupplierMapper;

    @Autowired
    private MarketEntryEarTagResolver marketEntryEarTagResolver;

    public void validateListQuery(BizMarketEntry query)
    {
        if (query == null)
        {
            return;
        }
        validateDateRange(query.getEntryDateStart(), query.getEntryDateEnd());
    }

    public void prepareAndValidateForSave(BizMarketEntry row)
    {
        if (row == null)
        {
            throw new ServiceException("登记数据不能为空");
        }
        trimFields(row);
        if (row.getEntryTime() == null)
        {
            throw new ServiceException(MarketEntryRules.MSG_ENTRY_TIME_REQUIRED);
        }
        if (row.getEntryTime().after(new Date()))
        {
            throw new ServiceException(MarketEntryRules.MSG_ENTRY_TIME_FUTURE);
        }
        if (row.getStallId() == null)
        {
            throw new ServiceException(MarketEntryRules.MSG_STALL_REQUIRED);
        }
        if (row.getSupplierId() == null)
        {
            throw new ServiceException(MarketEntryRules.MSG_SUPPLIER_REQUIRED);
        }
        BizMarketStall stall = assertStallActive(row.getStallId());
        assertSupplierActive(row.getSupplierId());
        row.setStallCode(stall.getStallCode());

        List<String> tags = EarTagCodec.resolveMainTags(row.getEarTags(), row.getEarTagList());
        row.setEarTagList(tags);
        validateAtLeastOneTag(tags);
        row.setQuantity(tags.size());
        validateEarTagsEligible(row.getSupplierId(), row.getId(), tags);
    }

    public void assertSupplierActiveForQuery(Long supplierId)
    {
        if (supplierId == null)
        {
            throw new ServiceException(MarketEntryRules.MSG_SUPPLIER_REQUIRED);
        }
        assertSupplierActive(supplierId);
    }

    private static void validateAtLeastOneTag(List<String> tags)
    {
        if (tags == null || tags.isEmpty())
        {
            throw new ServiceException(MarketEntryRules.MSG_EAR_TAG_EMPTY);
        }
    }

    private void validateEarTagsEligible(Long supplierId, Long excludeEntryId, List<String> tags)
    {
        List<String> eligible = marketEntryEarTagResolver.listEligible(supplierId, excludeEntryId);
        Set<String> eligibleSet = new HashSet<>(eligible);
        Set<String> occupied = marketEntryEarTagResolver.loadOccupiedEarTags(excludeEntryId);
        for (String tag : tags)
        {
            if (!eligibleSet.contains(tag))
            {
                if (occupied.contains(tag))
                {
                    throw new ServiceException(MarketEntryRules.MSG_M4_OCCUPIED + "：" + tag);
                }
                throw new ServiceException(String.format(MarketEntryRules.MSG_M2_INVALID, tag));
            }
        }
    }

    private static void trimFields(BizMarketEntry row)
    {
        if (row.getRemark() != null)
        {
            String remark = row.getRemark().trim();
            row.setRemark(remark.isEmpty() ? null : remark);
            if (remark.length() > MarketEntryRules.MAX_REMARK_LEN)
            {
                throw new ServiceException("备注长度不能超过 " + MarketEntryRules.MAX_REMARK_LEN + " 字");
            }
        }
        if (row.getStallCode() != null)
        {
            row.setStallCode(row.getStallCode().trim());
        }
    }

    private BizMarketStall assertStallActive(Long stallId)
    {
        BizMarketStall stall = bizMarketStallMapper.selectBizMarketStallById(stallId);
        if (stall == null)
        {
            throw new ServiceException(MarketEntryRules.MSG_STALL_NOT_FOUND);
        }
        return stall;
    }

    private void assertSupplierActive(Long supplierId)
    {
        BizSupplier supplier = bizSupplierMapper.selectBizSupplierById(supplierId);
        if (supplier == null)
        {
            throw new ServiceException(MarketEntryRules.MSG_SUPPLIER_NOT_FOUND);
        }
    }

    public static void validateDateRange(String startDate, String endDate)
    {
        boolean hasStart = StringUtils.isNotEmpty(startDate);
        boolean hasEnd = StringUtils.isNotEmpty(endDate);
        if (!hasStart && !hasEnd)
        {
            return;
        }
        Date start = hasStart ? parseQueryDate(startDate, "开始日期") : null;
        Date end = hasEnd ? parseQueryDate(endDate, "结束日期") : null;
        if (start != null && end != null && start.after(end))
        {
            throw new ServiceException(MarketEntryRules.MSG_DATE_RANGE_INVALID);
        }
    }

    private static Date parseQueryDate(String text, String label)
    {
        try
        {
            SimpleDateFormat fmt = new SimpleDateFormat(DATE_PATTERN);
            fmt.setLenient(false);
            return fmt.parse(text.trim());
        }
        catch (ParseException ex)
        {
            throw new ServiceException(label + "格式无效，应为 yyyy-MM-dd");
        }
    }
}
