package com.ruoyi.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.PosStoreEzpay;
import com.ruoyi.system.domain.dto.StoreEzpayCredentialDto;
import com.ruoyi.system.domain.vo.PosStoreEzpayVo;
import com.ruoyi.system.mapper.PosStoreEzpayMapper;
import com.ruoyi.system.service.IPosStoreEzpayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 门店 ezPay 发票开通管理 Service 实现（纯 DB 操作；ezPay 联网验证由 Controller 层完成）。
 *
 * @author ruoyi
 * @date 2026-06-15
 */
@Service
public class PosStoreEzpayServiceImpl implements IPosStoreEzpayService {

    @Autowired
    private PosStoreEzpayMapper posStoreEzpayMapper;

    /** 申请状态 */
    private static final int STATUS_NOT_APPLIED = 0;
    private static final int STATUS_APPLYING = 1;
    private static final int STATUS_ENABLED = 2;

    @Override
    public List<PosStoreEzpayVo> selectEzpayStoreList(PosStoreEzpayVo query) {
        return posStoreEzpayMapper.selectEzpayStoreList(query);
    }

    @Override
    public PosStoreEzpayVo selectEzpayStoreDetail(Long storeId) {
        PosStoreEzpayVo vo = posStoreEzpayMapper.selectEzpayStoreDetail(storeId);
        if (vo == null) {
            throw new ServiceException("门店不存在");
        }
        return vo;
    }

    @Override
    public int apply(Long storeId) {
        PosStoreEzpay row = getOrCreateByStoreId(storeId);
        // 发起申请前必须先有统编：ezPay 线下申请表统编为必填项
        if (StrUtil.isBlank(row.getUbn())) {
            throw new ServiceException("请先让商家在门店设置填写统编");
        }
        if (!row.getUbn().matches("\\d{8}")) {
            throw new ServiceException("统编格式不正确，需为8位数字");
        }
        if (!Integer.valueOf(STATUS_NOT_APPLIED).equals(row.getEzpayStatus())) {
            throw new ServiceException("当前状态不允许发起申请");
        }
        row.setEzpayStatus(STATUS_APPLYING);
        row.setApplyTime(new Date());
        return saveOrUpdate(row);
    }

    @Override
    public int enableWithCredentials(StoreEzpayCredentialDto dto) {
        PosStoreEzpay row = getOrCreateByStoreId(dto.getStoreId());
        row.setMerchantId(dto.getMerchantId());
        row.setHashKey(dto.getHashKey());
        row.setHashIv(dto.getHashIv());
        if (dto.getCompanyId() != null) {
            row.setCompanyId(dto.getCompanyId());
        }
        row.setEzpayStatus(STATUS_ENABLED);
        row.setIsEnabled(1);
        row.setApprovedTime(new Date());
        row.setLastVerifyResult("PASS");
        return saveOrUpdate(row);
    }

    @Override
    public int recordVerifyResult(Long storeId, String result) {
        PosStoreEzpay row = getOrCreateByStoreId(storeId);
        row.setLastVerifyResult(truncate(result));
        return saveOrUpdate(row);
    }

    @Override
    public int toggleEnable(Long storeId) {
        PosStoreEzpay row = getOrCreateByStoreId(storeId);
        if (!Integer.valueOf(STATUS_ENABLED).equals(row.getEzpayStatus())) {
            throw new ServiceException("仅已开通门店可停用/恢复");
        }
        int next = Integer.valueOf(1).equals(row.getIsEnabled()) ? 0 : 1;
        row.setIsEnabled(next);
        return saveOrUpdate(row);
    }

    @Override
    public int markExempt(Long storeId, Integer invoiceExempt) {
        if (invoiceExempt == null || (invoiceExempt != 0 && invoiceExempt != 1)) {
            throw new ServiceException("免用发票标记取值非法");
        }
        return posStoreEzpayMapper.updateInvoiceExempt(storeId, invoiceExempt);
    }

    @Override
    public int reset(Long storeId) {
        PosStoreEzpay row = getOrCreateByStoreId(storeId);
        row.setEzpayStatus(STATUS_APPLYING);
        row.setApprovedTime(null);
        return saveOrUpdate(row);
    }

    @Override
    public int uploadUbn(Long storeId, String ubn) {
        return posStoreEzpayMapper.upsertUbn(storeId, ubn);
    }

    @Override
    public String getUbn(Long storeId) {
        PosStoreEzpay row = posStoreEzpayMapper.selectOne(
                new LambdaQueryWrapper<PosStoreEzpay>().eq(PosStoreEzpay::getStoreId, storeId));
        return row == null ? null : row.getUbn();
    }

    // ===== 内部辅助 =====

    /** 按 storeId 取行；无行则新建（status=0, enabled=1，不入库）。 */
    private PosStoreEzpay getOrCreateByStoreId(Long storeId) {
        if (storeId == null) {
            throw new ServiceException("门店不能为空");
        }
        PosStoreEzpay row = posStoreEzpayMapper.selectOne(
                new LambdaQueryWrapper<PosStoreEzpay>().eq(PosStoreEzpay::getStoreId, storeId));
        if (row == null) {
            row = new PosStoreEzpay();
            row.setStoreId(storeId);
            row.setEzpayStatus(STATUS_NOT_APPLIED);
            row.setIsEnabled(1);
        }
        return row;
    }

    /** 新增或更新（显式设置时间与人，不依赖 MetaObjectHandler）。 */
    private int saveOrUpdate(PosStoreEzpay row) {
        Date now = new Date();
        String user = currentUser();
        if (row.getId() == null) {
            row.setCreateTime(now);
            row.setUpdateTime(now);
            row.setCreateBy(user);
            row.setUpdateBy(user);
            return posStoreEzpayMapper.insert(row);
        }
        row.setUpdateTime(now);
        row.setUpdateBy(user);
        return posStoreEzpayMapper.updateById(row);
    }

    private String currentUser() {
        try {
            return SecurityUtils.getUsername();
        } catch (Exception e) {
            return "system";
        }
    }

    private static String truncate(String s) {
        if (s == null) {
            return "";
        }
        return s.length() > 240 ? s.substring(0, 240) : s;
    }
}
