package com.jeesharp.business.modules.finance.invoice.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.finance.invoice.dto.MemberInvoiceApplyCreateDTO;
import com.jeesharp.business.modules.finance.invoice.entity.MemberInvoiceApply;
import com.jeesharp.business.modules.finance.invoice.mapper.MemberInvoiceApplyMapper;
import com.jeesharp.business.modules.finance.invoice.service.MemberInvoiceApplyService;
import com.jeesharp.business.modules.finance.invoice.vo.MemberInvoiceApplyQueryVO;
import com.jeesharp.business.modules.finance.invoice.vo.MemberInvoiceApplyResultVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

/**
 * 发票申请领域服务实现；订单存在性由应用层校验。
 *
 * @author jeesharp
 * @since 2026-05-08
 */
@Service
@Transactional(readOnly = true)
public class MemberInvoiceApplyServiceImpl
        extends CrudService<MemberInvoiceApplyMapper, MemberInvoiceApply, MemberInvoiceApplyQueryVO>
        implements MemberInvoiceApplyService {

    private static final String IDS_SEPARATOR = ",";
    private static final DateTimeFormatter DT_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    @Transactional(readOnly = false)
    public void createApply(MemberInvoiceApply entity) {
        save(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public void updateApply(MemberInvoiceApply entity) {
        update(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public MemberInvoiceApplyResultVO createInvoiceApply(String memberId, MemberInvoiceApplyCreateDTO dto,
                                                         String tenantId, String tenantCode) {
        MemberInvoiceApply entity = new MemberInvoiceApply();
        entity.setId(IdUtil.getSnowflakeNextIdStr());
        entity.setMemberId(memberId);
        entity.setOrderId(dto.getOrderId());
        entity.setOrderNo(dto.getOrderNo());
        entity.setBizType(dto.getBizType());
        entity.setInvoiceType(dto.getInvoiceType());
        entity.setInvoiceTitle(dto.getInvoiceTitle());
        entity.setInvoiceTaxNo(dto.getInvoiceTaxNo());
        entity.setEmail(dto.getEmail());
        entity.setMobile(dto.getMobile());
        entity.setAmountLabel(dto.getAmountLabel());
        entity.setApplyReason(dto.getApplyReason());
        entity.setStatus("pending");
        entity.setTenantId(tenantId);
        entity.setTenantCode(tenantCode);
        sealOrderTenant(entity);
        save(entity);
        return buildResult(entity);
    }

    @Override
    public MemberInvoiceApplyResultVO getApplyResult(String id) {
        MemberInvoiceApply entity = get(id);
        if (entity == null) {
            throw new BizErrorException("发票申请不存在");
        }
        return buildResult(entity);
    }

    /**
     * 锁定订单所属商户租户，避免 C 端 {@code preInsert} 将会员上下文（如 {@code user_data}）写入申请单。
     */
    private static void sealOrderTenant(MemberInvoiceApply entity) {
        if (entity == null) {
            return;
        }
        if (StrUtil.isNotBlank(entity.getTenantCode()) || StrUtil.isNotBlank(entity.getTenantId())) {
            entity.closeTenantCodeAutoSet();
        }
    }

    private static MemberInvoiceApplyResultVO buildResult(MemberInvoiceApply entity) {
        MemberInvoiceApplyResultVO vo = new MemberInvoiceApplyResultVO();
        vo.setId(entity.getId());
        vo.setOrderId(entity.getOrderId());
        vo.setOrderNo(entity.getOrderNo());
        vo.setStatus(entity.getStatus());
        vo.setInvoiceTitle(entity.getInvoiceTitle());
        vo.setInvoiceFileName(entity.getInvoiceFileName());
        vo.setInvoiceFileUrl(entity.getInvoiceFileUrl());
        vo.setAuditRemark(entity.getAuditRemark());
        vo.setCreateDate(entity.getCreateDate() == null ? LocalDateTime.now().format(DT_FMT) : entity.getCreateDate().format(DT_FMT));
        return vo;
    }
}
