package com.ruoyi.warehouse.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.warehouse.domain.ProductInfo;
import com.ruoyi.warehouse.mapper.ProductInfoMapper;
import com.ruoyi.warehouse.service.IProductInfoService;

@Service
public class ProductInfoServiceImpl implements IProductInfoService
{
    @Autowired
    private ProductInfoMapper productInfoMapper;

    @Override
    public List<ProductInfo> selectProductInfoList(ProductInfo productInfo)
    {
        return productInfoMapper.selectProductInfoList(productInfo);
    }

    @Override
    public List<ProductInfo> selectProductInfoAll()
    {
        return productInfoMapper.selectProductInfoAll();
    }

    @Override
    public ProductInfo selectProductInfoById(Long id)
    {
        return productInfoMapper.selectProductInfoById(id);
    }

    @Override
    public boolean checkProductCodeUnique(ProductInfo productInfo)
    {
        if (StringUtils.isBlank(productInfo.getProductCode()))
        {
            return UserConstants.UNIQUE;
        }
        Long id = StringUtils.isNull(productInfo.getId()) ? -1L : productInfo.getId();
        ProductInfo info = productInfoMapper.checkProductCodeUnique(productInfo.getProductCode());
        return StringUtils.isNull(info) || info.getId().longValue() == id.longValue() ? UserConstants.UNIQUE : UserConstants.NOT_UNIQUE;
    }

    @Override
    public String inferProductCategory(ProductInfo productInfo)
    {
        if (productInfo == null || StringUtils.isBlank(productInfo.getProductName()))
        {
            return null;
        }
        String category = inferCategoryFromHistory(productInfo);
        if (StringUtils.isNotBlank(category))
        {
            return category;
        }
        return generateCategory(productInfo);
    }

    @Override
    public int insertProductInfo(ProductInfo productInfo)
    {
        normalizeProductInfo(productInfo);
        validateProductInfoUnique(productInfo);
        return productInfoMapper.insertProductInfo(productInfo);
    }

    @Override
    public int updateProductInfo(ProductInfo productInfo)
    {
        normalizeProductInfo(productInfo);
        validateProductInfoUnique(productInfo);
        return productInfoMapper.updateProductInfo(productInfo);
    }

    @Override
    public int deleteProductInfoByIds(Long[] ids)
    {
        return productInfoMapper.deleteProductInfoByIds(ids);
    }

    private void normalizeProductInfo(ProductInfo productInfo)
    {
        if (StringUtils.isBlank(productInfo.getProductCode()))
        {
            productInfo.setProductCode(null);
        }
        productInfo.setProductName(trimToNull(productInfo.getProductName()));
        productInfo.setBrand(trimToNull(productInfo.getBrand()));
        productInfo.setCategory(trimToNull(productInfo.getCategory()));
        productInfo.setSpec(trimToNull(productInfo.getSpec()));
        productInfo.setUnit(trimToNull(productInfo.getUnit()));
        if (StringUtils.isBlank(productInfo.getCategory()) && StringUtils.isNotBlank(productInfo.getProductName()))
        {
            productInfo.setCategory(inferProductCategory(productInfo));
        }
    }

    private void validateProductInfoUnique(ProductInfo productInfo)
    {
        ProductInfo info = productInfoMapper.checkProductInfoUnique(productInfo);
        Long id = StringUtils.isNull(productInfo.getId()) ? -1L : productInfo.getId();
        if (StringUtils.isNotNull(info) && info.getId().longValue() != id.longValue())
        {
            throw new ServiceException("该产品已存在");
        }
    }

    private String trimToNull(String value)
    {
        return StringUtils.isBlank(value) ? null : value.trim();
    }

    private String inferCategoryFromHistory(ProductInfo productInfo)
    {
        Map<String, Integer> scores = new HashMap<>();
        for (ProductInfo product : productInfoMapper.selectProductInfoAll())
        {
            if (StringUtils.isBlank(product.getCategory()))
            {
                continue;
            }
            int score = categoryProductScore(productInfo, product);
            if (score > 0)
            {
                String category = product.getCategory().trim();
                scores.put(category, scores.getOrDefault(category, 0) + score);
            }
        }
        String bestCategory = null;
        int bestScore = 0;
        int secondScore = 0;
        for (Map.Entry<String, Integer> entry : scores.entrySet())
        {
            int score = entry.getValue();
            if (score > bestScore)
            {
                secondScore = bestScore;
                bestScore = score;
                bestCategory = entry.getKey();
            }
            else if (score > secondScore)
            {
                secondScore = score;
            }
        }
        if (bestScore >= 4 && bestScore >= secondScore + 2)
        {
            return bestCategory;
        }
        return null;
    }

    private int categoryProductScore(ProductInfo source, ProductInfo target)
    {
        int score = 0;
        score += fieldScore(source.getProductName(), target.getProductName(), 8);
        score += fieldScore(source.getBrand(), target.getBrand(), 6);
        score += fieldScore(source.getSpec(), target.getSpec(), 4);
        score += fieldScore(source.getUnit(), target.getUnit(), 1);
        String draftText = productDraftText(source);
        score += containsField(draftText, target.getProductName()) ? 4 : 0;
        score += containsField(draftText, target.getBrand()) ? 2 : 0;
        score += containsField(draftText, target.getSpec()) ? 2 : 0;
        return score;
    }

    private int fieldScore(String input, String target, int exactScore)
    {
        if (StringUtils.isBlank(input) || StringUtils.isBlank(target))
        {
            return 0;
        }
        if (input.trim().equalsIgnoreCase(target.trim()))
        {
            return exactScore;
        }
        if (containsIgnoreCase(input, target) || containsIgnoreCase(target, input))
        {
            return Math.max(1, exactScore / 2);
        }
        return 0;
    }

    private String productDraftText(ProductInfo productInfo)
    {
        return StringUtils.defaultString(productInfo.getProductName()) + " "
                + StringUtils.defaultString(productInfo.getBrand()) + " "
                + StringUtils.defaultString(productInfo.getSpec()) + " "
                + StringUtils.defaultString(productInfo.getUnit());
    }

    private String generateCategory(ProductInfo productInfo)
    {
        String text = productDraftText(productInfo).toLowerCase(Locale.ROOT);
        if (containsAny(text, "路由器", "交换机", "网关", "ap", "wifi", "网线", "光模块", "网络"))
        {
            return "网络设备";
        }
        if (containsAny(text, "电脑", "主机", "显示器", "键盘", "鼠标", "硬盘", "内存", "打印机", "扫描仪"))
        {
            return "办公设备";
        }
        if (containsAny(text, "纸", "抽纸", "卷纸", "硒鼓", "墨盒", "墨粉", "笔", "文件夹", "订书", "胶带"))
        {
            return "办公耗材";
        }
        if (containsAny(text, "手套", "口罩", "安全帽", "护目镜", "反光", "劳保"))
        {
            return "劳保用品";
        }
        if (containsAny(text, "扳手", "螺丝刀", "钳", "锤", "钻", "工具"))
        {
            return "工具";
        }
        if (containsAny(text, "螺丝", "螺母", "垫片", "扎带", "卡扣", "五金"))
        {
            return "五金耗材";
        }
        if (containsAny(text, "传感器", "继电器", "电源", "线束", "电缆", "接头", "模块", "芯片", "电阻", "电容"))
        {
            return "电子元器件";
        }
        if (containsAny(text, "机油", "润滑", "清洗剂", "胶水", "胶粘", "油漆", "化学"))
        {
            return "化工耗材";
        }
        if (containsAny(text, "轮胎", "刹车", "电瓶", "电池", "车灯", "滤芯", "汽车"))
        {
            return "汽车配件";
        }
        return "通用物料";
    }

    private boolean containsAny(String text, String... keywords)
    {
        for (String keyword : keywords)
        {
            if (containsIgnoreCase(text, keyword))
            {
                return true;
            }
        }
        return false;
    }

    private boolean containsField(String text, String field)
    {
        return StringUtils.isNotBlank(text) && StringUtils.isNotBlank(field) && containsIgnoreCase(text, field);
    }

    private boolean containsIgnoreCase(String text, String keyword)
    {
        if (StringUtils.isBlank(text) || StringUtils.isBlank(keyword))
        {
            return false;
        }
        return text.toLowerCase(Locale.ROOT).contains(keyword.toLowerCase(Locale.ROOT));
    }
}
