package com.erp.finance.listener;

import com.erp.common.core.event.OrderCancelledEvent;
import com.erp.common.core.event.OrderCreatedEvent;
import com.erp.common.core.event.OrderPaidEvent;
import com.erp.common.core.event.OrderShippedEvent;
import com.erp.finance.entity.IncomeRecord;
import com.erp.finance.entity.RefundRecord;
import com.erp.finance.repository.IncomeRecordRepository;
import com.erp.finance.repository.RefundRecordRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 财务事件消费者 - 监听订单事件并执行业务处理
 * 处理订单创建/发货/取消等事件，驱动财务记账
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class FinanceEventConsumer {

    private final IncomeRecordRepository incomeRecordRepository;
    private final RefundRecordRepository refundRecordRepository;

    /**
     * 监听订单创建事件 - 预登记应收账款的占位记录
     */
    @Async
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        log.info("[财务事件] 收到订单创建事件: orderId={}, shortId={}, amount={}",
                event.getOrderId(), event.getShortId(), event.getTotalAmount());
        try {
            recordIncome(event);
        } catch (Exception e) {
            log.error("[财务事件处理失败] OrderCreatedEvent: orderId={}, error={}",
                    event.getOrderId(), e.getMessage(), e);
        }
    }

    /**
     * 监听订单支付成功事件 - 记录实际收款
     */
    @Async
    @EventListener
    public void onOrderPaid(OrderPaidEvent event) {
        log.info("[财务事件] 收到订单支付事件: orderId={}, shortId={}, amount={}, method={}",
                event.getOrderId(), event.getShortId(), event.getPaidAmount(), event.getPaymentMethod());
        try {
            updateIncomeRecordPaid(event);
        } catch (Exception e) {
            log.error("[财务事件处理失败] OrderPaidEvent: orderId={}, error={}",
                    event.getOrderId(), e.getMessage(), e);
        }
    }

    /**
     * 监听订单发货事件 - 确认应收并记录收入
     */
    @Async
    @EventListener
    public void onOrderShipped(OrderShippedEvent event) {
        log.info("[财务事件] 收到订单发货事件: orderId={}, shortId={}, amount={}, express={}",
                event.getOrderId(), event.getShortId(), event.getTotalAmount(), event.getExpressNo());
        try {
            recordShippedIncome(event);
        } catch (Exception e) {
            log.error("[财务事件处理失败] OrderShippedEvent: orderId={}, error={}",
                    event.getOrderId(), e.getMessage(), e);
        }
    }

    /**
     * 监听订单取消/退款事件 - 处理退款
     */
    @Async
    @EventListener
    public void onOrderCancelled(OrderCancelledEvent event) {
        log.info("[财务事件] 收到订单取消事件: orderId={}, shortId={}, type={}, amount={}",
                event.getOrderId(), event.getShortId(), event.getEventType(), event.getRefundAmount());
        try {
            processRefund(event);
        } catch (Exception e) {
            log.error("[财务事件处理失败] OrderCancelledEvent: orderId={}, error={}",
                    event.getOrderId(), e.getMessage(), e);
        }
    }

    /**
     * 记录订单创建时的应收账款
     */
    @Transactional
    public void recordIncome(OrderCreatedEvent event) {
        // 检查是否已存在该订单的收入记录，避免重复
        IncomeRecord existing = incomeRecordRepository.findByOrderNo(event.getOrderNo());
        if (existing != null) {
            log.warn("[财务] 订单已存在收入记录，跳过: orderNo={}", event.getOrderNo());
            return;
        }

        IncomeRecord income = new IncomeRecord();
        income.setOrderNo(event.getOrderNo());
        income.setShortId(event.getShortId());
        income.setPlatform(event.getPlatform());
        income.setShopId(event.getShopId());
        income.setAmount(event.getTotalAmount());
        income.setActualAmount(BigDecimal.ZERO); // 未付款，实际到账为0
        income.setPaymentMethod(event.getPaymentMethod());
        income.setStatus(IncomeRecord.STATUS_PENDING);
        income.setSource(IncomeRecord.SOURCE_ORDER);
        income.setPaymentTime(null);
        income.setCreateTime(LocalDateTime.now());
        income.setUpdateTime(LocalDateTime.now());

        incomeRecordRepository.insert(income);
        log.info("[财务] 创建应收账款记录: orderNo={}, amount={}", event.getOrderNo(), event.getTotalAmount());
    }

    /**
     * 更新订单为已支付状态
     */
    @Transactional
    public void updateIncomeRecordPaid(OrderPaidEvent event) {
        IncomeRecord income = incomeRecordRepository.findByOrderNo(event.getOrderNo());
        if (income == null) {
            log.warn("[财务] 支付事件但找不到收入记录: orderNo={}", event.getOrderNo());
            // 如果不存在，先创建
            recordIncomeFromPaidEvent(event);
            return;
        }

        income.setStatus(IncomeRecord.STATUS_CONFIRMED);
        income.setActualAmount(event.getPaidAmount());
        income.setPaymentMethod(event.getPaymentMethod());
        if (event.getPaymentTime() != null) {
            income.setPaymentTime(event.getPaymentTime());
        } else {
            income.setPaymentTime(LocalDateTime.now());
        }
        income.setUpdateTime(LocalDateTime.now());

        incomeRecordRepository.updateById(income);
        log.info("[财务] 更新收入记录为已支付: orderNo={}, paidAmount={}",
                event.getOrderNo(), event.getPaidAmount());
    }

    /**
     * 从支付事件创建收入记录
     */
    @Transactional
    public void recordIncomeFromPaidEvent(OrderPaidEvent event) {
        IncomeRecord existing = incomeRecordRepository.findByOrderNo(event.getOrderNo());
        if (existing != null) return;

        IncomeRecord income = new IncomeRecord();
        income.setOrderNo(event.getOrderNo());
        income.setShortId(event.getShortId());
        income.setPlatform(event.getPlatform());
        income.setShopId(event.getShopId());
        income.setAmount(event.getPaidAmount());
        income.setActualAmount(event.getPaidAmount());
        income.setPaymentMethod(event.getPaymentMethod());
        income.setStatus(IncomeRecord.STATUS_CONFIRMED);
        income.setSource(IncomeRecord.SOURCE_ORDER);
        LocalDateTime paymentTime = event.getPaymentTime() != null ? event.getPaymentTime() : LocalDateTime.now();
        income.setPaymentTime(paymentTime);
        income.setCreateTime(LocalDateTime.now());
        income.setUpdateTime(LocalDateTime.now());

        incomeRecordRepository.insert(income);
        log.info("[财务] 从支付事件创建收入记录: orderNo={}, amount={}",
                event.getOrderNo(), event.getPaidAmount());
    }

    /**
     * 发货时确认应收账款，记录为已发货收入
     */
    @Transactional
    public void recordShippedIncome(OrderShippedEvent event) {
        IncomeRecord income = incomeRecordRepository.findByOrderNo(event.getOrderNo());
        if (income != null) {
            // 更新为已确认状态
            income.setStatus(IncomeRecord.STATUS_CONFIRMED);
            income.setActualAmount(event.getTotalAmount());
            if (income.getPaymentMethod() == null) {
                income.setPaymentMethod("online"); // 发货时默认线上支付
            }
            LocalDateTime shipTime = event.getShipTime() != null ? event.getShipTime() : LocalDateTime.now();
            if (income.getPaymentTime() == null) {
                income.setPaymentTime(shipTime);
            }
            income.setUpdateTime(LocalDateTime.now());
            incomeRecordRepository.updateById(income);
            log.info("[财务] 更新收入记录为已确认: orderNo={}, amount={}",
                    event.getOrderNo(), event.getTotalAmount());
        } else {
            // 直接创建发货记录
            IncomeRecord incomeNew = new IncomeRecord();
            incomeNew.setOrderNo(event.getOrderNo());
            incomeNew.setShortId(event.getShortId());
            incomeNew.setPlatform(event.getPlatform());
            incomeNew.setShopId(event.getShopId());
            incomeNew.setAmount(event.getTotalAmount());
            incomeNew.setActualAmount(event.getTotalAmount());
            incomeNew.setPaymentMethod("online");
            incomeNew.setStatus(IncomeRecord.STATUS_CONFIRMED);
            incomeNew.setSource(IncomeRecord.SOURCE_ORDER);
            LocalDateTime shipTime = event.getShipTime() != null ? event.getShipTime() : LocalDateTime.now();
            incomeNew.setPaymentTime(shipTime);
            incomeNew.setCreateTime(LocalDateTime.now());
            incomeNew.setUpdateTime(LocalDateTime.now());
            incomeRecordRepository.insert(incomeNew);
            log.info("[财务] 创建发货收入记录: orderNo={}, amount={}",
                    event.getOrderNo(), event.getTotalAmount());
        }
    }

    /**
     * 处理订单退款/取消
     */
    @Transactional
    public void processRefund(OrderCancelledEvent event) {
        if ("cancel".equals(event.getEventType())) {
            // 订单取消时，更新收入记录为已取消
            IncomeRecord income = incomeRecordRepository.findByOrderNo(event.getOrderNo());
            if (income != null) {
                income.setStatus(IncomeRecord.STATUS_CANCELLED);
                income.setUpdateTime(LocalDateTime.now());
                incomeRecordRepository.updateById(income);
                log.info("[财务] 更新收入记录为已取消: orderNo={}", event.getOrderNo());
            }
        } else if ("refund".equals(event.getEventType())) {
            // 退款时创建退款记录
            RefundRecord refund = new RefundRecord();
            refund.setOrderNo(event.getOrderNo());
            refund.setShortId(event.getShortId());
            refund.setRefundAmount(event.getRefundAmount() != null ? event.getRefundAmount() : BigDecimal.ZERO);
            refund.setRefundReason(event.getRefundReason());
            refund.setStatus(RefundRecord.STATUS_PENDING);
            refund.setType(RefundRecord.TYPE_ORDER_REFUND);
            refund.setSource(RefundRecord.SOURCE_ORDER);
            refund.setRefundTime(event.getEventTime() != null ? event.getEventTime() : LocalDateTime.now());
            refund.setCreateTime(LocalDateTime.now());
            refund.setUpdateTime(LocalDateTime.now());
            refundRecordRepository.insert(refund);

            // 更新收入记录为已退款
            IncomeRecord income = incomeRecordRepository.findByOrderNo(event.getOrderNo());
            if (income != null) {
                income.setStatus("refunded"); // 自定义状态表示已退款
                income.setUpdateTime(LocalDateTime.now());
                incomeRecordRepository.updateById(income);
            }

            log.info("[财务] 创建退款记录: orderNo={}, amount={}",
                    event.getOrderNo(), event.getRefundAmount());
        }
    }
}
