package com.jeesharp.business.modules.mall.application;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.finance.api.PayRefundApi;
import com.jeesharp.business.modules.finance.payrefund.dto.PayRefundCreateDTO;
import com.jeesharp.business.modules.member.service.MemberService;
import com.jeesharp.business.modules.member.vo.MemberDisplayVO;
import com.jeesharp.business.modules.mall.application.support.MallAfterSaleRefundCoordinator;
import com.jeesharp.business.modules.mall.convert.MallAfterSaleConvert;
import com.jeesharp.business.modules.mall.dto.MallAfterSaleSaveDTO;
import com.jeesharp.business.modules.mall.entity.MallAfterSale;
import com.jeesharp.business.modules.mall.enums.AfterSaleRefundTriggerModeEnum;
import com.jeesharp.business.modules.mall.service.MallAfterSaleService;
import com.jeesharp.business.modules.mall.service.MallSettingService;
import com.jeesharp.business.modules.mall.vo.MallAfterSaleInfoVO;
import com.jeesharp.business.modules.mall.vo.MallAfterSaleListVO;
import com.jeesharp.business.modules.mall.vo.MallAfterSaleQueryVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 商城售后应用服务（退款/退货/换货审核与处理）。
 *
 * <p><b>退款与优惠券</b>：{@link #handleAfterSale} 在售后单原状态为「退款中」且处理完成时，
 * 委托 {@link MallAfterSaleRefundCoordinator}（内部经 {@code BookingRefundTailSupport} 退券，幂等）。</p>
 *
 * <p>链路：用户申请 applyAfterSale → 管理端 auditAfterSale → handleAfterSale（财务退款后）。</p>
 *
 * @author jeesharp
 * @since 2026-05-08
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class MallAfterSaleApplicationService {

    private static final int AUDIT_APPROVED_STATUS = 1;

    private static final int REFUNDING_STATUS = 3;

    private static final String CONFIG_AFTER_SALE_REFUND_TRIGGER_MODE = "after_sale_refund_trigger_mode";

    private static final String REFUND_ONLY_TYPE = "REFUND_ONLY";

    private static final String RETURN_REFUND_TYPE = "RETURN_REFUND";

    private final MallAfterSaleService mallAfterSaleService;
    private final MemberService memberService;
    private final PayRefundApi payRefundApi;
    private final MallSettingService mallSettingService;
    private final MallAfterSaleRefundCoordinator mallAfterSaleRefundCoordinator;

    public MallAfterSaleInfoVO get(String id) {
        return MallAfterSaleConvert.INSTANCE.toInfoVO(mallAfterSaleService.get(id));
    }

    public PageRespVO<MallAfterSaleListVO> findPage(Page<MallAfterSale> page, MallAfterSaleQueryVO query) {
        MallAfterSaleQueryVO prepared = prepareQuery(query);
        if (prepared == null) {
            return emptyPage(page);
        }
        Page<MallAfterSale> result = mallAfterSaleService.findPage(page, prepared);
        PageRespVO<MallAfterSaleListVO> pageVo = MallAfterSaleConvert.INSTANCE.toPageRespVO(result);
        enrichMemberNameForList(pageVo.getRecords());
        return pageVo;
    }

    /**
     * 会员关键词 → memberIdIn 筛选条件（编排，不含会员数据组装）。
     */
    private MallAfterSaleQueryVO prepareQuery(MallAfterSaleQueryVO query) {
        MallAfterSaleQueryVO q = query != null ? query : new MallAfterSaleQueryVO();
        if (StrUtil.isBlank(q.getMemberKeyword())) {
            return q;
        }
        List<String> memberIds = memberService.findIdsByKeyword(q.getMemberKeyword().trim());
        q.setMemberKeyword(null);
        if (CollUtil.isEmpty(memberIds)) {
            return null;
        }
        q.setMemberIdIn(memberIds);
        return q;
    }

    private PageRespVO<MallAfterSaleListVO> emptyPage(Page<MallAfterSale> page) {
        PageRespVO<MallAfterSaleListVO> empty = new PageRespVO<>();
        empty.setRecords(Collections.emptyList());
        empty.setTotal(0L);
        empty.setPageNo(page.getPageNo());
        empty.setPageSize(page.getPageSize());
        empty.setPages(0L);
        return empty;
    }

    /** 列表「会员名称」列：由 MemberService 批量补全展示名（不依赖会员管理 list 接口）。 */
    private void enrichMemberNameForList(List<MallAfterSaleListVO> rows) {
        if (CollUtil.isEmpty(rows)) {
            return;
        }
        List<String> memberIds = rows.stream()
                .map(MallAfterSaleListVO::getMemberId)
                .filter(StrUtil::isNotBlank)
                .distinct()
                .toList();
        Map<String, MemberDisplayVO> displayMap = memberService.mapDisplayByIds(memberIds);
        for (MallAfterSaleListVO row : rows) {
            if (StrUtil.isBlank(row.getMemberId())) {
                continue;
            }
            MemberDisplayVO display = displayMap.get(row.getMemberId());
            if (display != null && StrUtil.isNotBlank(display.getMemberNickname())) {
                row.setMemberName(display.getMemberNickname());
            }
        }
    }

    @Transactional(readOnly = false)
    public void save(MallAfterSaleSaveDTO dto) {
        MallAfterSale entity = MallAfterSaleConvert.INSTANCE.toEntity(dto);
        if (StrUtil.isBlank(dto.getId())) {
            mallAfterSaleService.createAfterSale(entity);
            return;
        }
        mallAfterSaleService.updateAfterSale(entity);
    }

    @Transactional(readOnly = false)
    public void delete(String ids) {
        mallAfterSaleService.batchDelete(StrUtil.splitTrim(ids, ','));
    }

    /**
     * 审核售后单
     */
    @Transactional(readOnly = false)
    public void auditAfterSale(String afterSaleId, Integer status, String auditBy, String auditRemark) {
        mallAfterSaleService.auditAfterSale(afterSaleId, status, auditBy, auditRemark);
        if (AUDIT_APPROVED_STATUS == status && isAutoRefundTriggerMode()) {
            MallAfterSale afterSale = mallAfterSaleService.get(afterSaleId);
            if (afterSale != null && REFUNDING_STATUS == afterSale.getStatus()
                    && REFUND_ONLY_TYPE.equals(afterSale.getAfterSaleType())) {
                triggerRefundInternal(afterSale, auditBy);
            }
        }
    }

    /**
     * 运营手动发起微信退款（配置为 MANUAL 或退货退款场景补发）。
     */
    @Transactional(readOnly = false)
    public void triggerRefund(String afterSaleId, String operatorId) {
        MallAfterSale afterSale = mallAfterSaleService.get(afterSaleId);
        if (afterSale == null) {
            throw new BizErrorException("售后单不存在");
        }
        if (REFUNDING_STATUS != afterSale.getStatus()) {
            throw new BizErrorException("仅「退款中」状态的售后单可发起退款");
        }
        triggerRefundInternal(afterSale, operatorId);
    }

    private void triggerRefundInternal(MallAfterSale afterSale, String operatorId) {
        if (afterSale.getRefundAmount() == null || afterSale.getRefundAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BizErrorException("售后退款金额无效");
        }
        if (StrUtil.isBlank(afterSale.getOrderId())) {
            throw new BizErrorException("售后单缺少关联订单");
        }
        String type = afterSale.getAfterSaleType();
        if (!REFUND_ONLY_TYPE.equals(type) && !RETURN_REFUND_TYPE.equals(type)) {
            throw new BizErrorException("当前售后类型不支持微信退款");
        }
        PayRefundCreateDTO dto = new PayRefundCreateDTO();
        dto.setMallOrderId(afterSale.getOrderId());
        dto.setAfterSaleId(afterSale.getId());
        dto.setRefundAmount(afterSale.getRefundAmount());
        dto.setReason(StrUtil.blankToDefault(afterSale.getRefundReasonDesc(), "商城售后退款"));
        dto.setOperatorId(operatorId);
        payRefundApi.createAndExecute(dto);
    }

    private boolean isAutoRefundTriggerMode() {
        String mode = mallSettingService.getConfigValue(CONFIG_AFTER_SALE_REFUND_TRIGGER_MODE);
        if (StrUtil.isBlank(mode)) {
            return false;
        }
        return AfterSaleRefundTriggerModeEnum.AUTO == AfterSaleRefundTriggerModeEnum.fromValue(mode);
    }

    /**
     * 处理售后单（退款完成、退货完成、换货完成）。
     * <p>仅当处理前状态为退款中（status=3）时触发优惠券退回。</p>
     */
    @Transactional(readOnly = false)
    public void handleAfterSale(String afterSaleId, String handlerId, String handleRemark) {
        mallAfterSaleRefundCoordinator.applyRefundSuccess(afterSaleId, handlerId, handleRemark);
    }

    /**
     * 用户申请售后
     */
    @Transactional(readOnly = false)
    public void applyAfterSale(String orderId, String orderItemId, String memberId,
                              String skuId, String spuId, String afterSaleType,
                              Integer applyQuantity, BigDecimal refundAmount,
                              String refundReason, String refundReasonDesc, String refundDesc) {
        mallAfterSaleService.applyAfterSale(orderId, orderItemId, memberId, skuId, spuId, afterSaleType,
                applyQuantity, refundAmount, refundReason, refundReasonDesc, refundDesc);
    }

    /**
     * 获取会员的售后单列表
     */
    public List<MallAfterSale> getMemberAfterSales(String memberId) {
        return mallAfterSaleService.getMemberAfterSales(memberId);
    }
}
