package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.InfoInvoice;
import com.ruoyi.system.mapper.InfoInvoiceMapper;
import com.ruoyi.system.service.IInfoInvoiceService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.regex.Pattern;

/**
 * 用户发票抬头 Service 实现（发票信息管理）
 *
 * @author foodie
 * @date 2026-07-24
 */
@Service
public class InfoInvoiceServiceImpl extends ServiceImpl<InfoInvoiceMapper, InfoInvoice> implements IInfoInvoiceService
{
    /** 统编：8 位数字 */
    private static final Pattern UBN_PATTERN = Pattern.compile("^\\d{8}$");
    /** 自然人凭证：2 大写字母 + 14 数字 */
    private static final Pattern CARRIER_CDC_PATTERN = Pattern.compile("^[A-Z]{2}\\d{14}$");
    /** 邮箱格式（宽松校验） */
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");

    @Override
    public List<InfoInvoice> listByUserId(Long userId)
    {
        return list(new QueryWrapper<InfoInvoice>().eq("user_id", userId).orderByDesc("id"));
    }

    @Override
    public boolean saveOrUpdateMine(InfoInvoice invoice, Long userId)
    {
        // 强制以当前登录用户为准，前端传的 userId 无效（防越权）
        invoice.setUserId(userId);
        validateInvoiceProfile(invoice);
        // 更新时校验归属：该抬头必须属于当前用户
        if (invoice.getId() != null)
        {
            InfoInvoice exist = getById(invoice.getId());
            if (exist == null || !userId.equals(exist.getUserId()))
            {
                throw new ServiceException("抬头不存在或无权操作");
            }
        }
        return saveOrUpdate(invoice);
    }

    @Override
    public InfoInvoice getMine(Long id, Long userId)
    {
        InfoInvoice invoice = getById(id);
        if (invoice == null || !userId.equals(invoice.getUserId()))
        {
            return null;
        }
        return invoice;
    }

    @Override
    public boolean deleteMine(Long id, Long userId)
    {
        InfoInvoice invoice = getById(id);
        if (invoice == null || !userId.equals(invoice.getUserId()))
        {
            return false;
        }
        return removeById(id);
    }

    /**
     * 保存前中校验（见 contracts/api.md 校验矩阵）。
     * B2B：公司名 + 统编8位 + 邮箱必填 + 载具空。
     * B2C：姓名 + 载具必填（0手机条码以/开头、1自然人凭证2字母+14数字、2会员载具须带邮箱）+ 统编空。
     */
    private void validateInvoiceProfile(InfoInvoice invoice)
    {
        String category = invoice.getCategory();
        if (!"B2C".equals(category) && !"B2B".equals(category))
        {
            throw new ServiceException("发票类型不正确");
        }
        if (isBlank(invoice.getTitleName()))
        {
            throw new ServiceException("抬头名称不能为空");
        }
        if (isBlank(invoice.getBuyerName()))
        {
            throw new ServiceException("买方名称不能为空");
        }

        if ("B2B".equals(category))
        {
            if (invoice.getBuyerUbn() == null || !UBN_PATTERN.matcher(invoice.getBuyerUbn()).matches())
            {
                throw new ServiceException("统一编号须为8位数字");
            }
            if (isBlank(invoice.getBuyerEmail()) || !EMAIL_PATTERN.matcher(invoice.getBuyerEmail()).matches())
            {
                throw new ServiceException("邮箱格式不正确");
            }
            if (!isBlank(invoice.getCarrierType()) || !isBlank(invoice.getCarrierNum()))
            {
                throw new ServiceException("公司发票无需载具");
            }
            return;
        }

        // B2C
        if (!isBlank(invoice.getBuyerUbn()))
        {
            throw new ServiceException("个人发票无需统一编号");
        }
        String carrierType = invoice.getCarrierType();
        if (isBlank(carrierType))
        {
            throw new ServiceException("请选择载具类型");
        }
        if (isBlank(invoice.getCarrierNum()))
        {
            throw new ServiceException("载具号码不能为空");
        }
        String carrierNum = invoice.getCarrierNum();
        switch (carrierType)
        {
            case "0": // 手机条码：以 / 开头
                if (!carrierNum.startsWith("/"))
                {
                    throw new ServiceException("手机条码须以 / 开头");
                }
                break;
            case "1": // 自然人凭证：2 字母 + 14 数字
                if (!CARRIER_CDC_PATTERN.matcher(carrierNum).matches())
                {
                    throw new ServiceException("自然人凭证格式不正确");
                }
                break;
            case "2": // ezPay 会员载具：须带邮箱
                if (isBlank(invoice.getBuyerEmail()) || !EMAIL_PATTERN.matcher(invoice.getBuyerEmail()).matches())
                {
                    throw new ServiceException("会员载具须填写邮箱");
                }
                break;
            default:
                throw new ServiceException("载具类型不正确");
        }
        // 邮箱选填时也校验格式
        if (!isBlank(invoice.getBuyerEmail()) && !EMAIL_PATTERN.matcher(invoice.getBuyerEmail()).matches())
        {
            throw new ServiceException("邮箱格式不正确");
        }
    }

    private static boolean isBlank(String s)
    {
        return s == null || s.trim().isEmpty();
    }
}
