package com.erp.finance.controller;

import com.erp.finance.dto.*;
import com.erp.finance.entity.IncomeRecord;
import com.erp.finance.entity.RefundRecord;
import com.erp.finance.service.IncomeService;
import com.erp.finance.service.RefundService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import com.erp.common.core.model.ApiResponse;

/**
 * 订单-财务联动控制器
 * 提供给 order-service 调用的财务联动接口
 */
@Slf4j
@RestController
@RequestMapping("/api/finance/linkage/order")
@RequiredArgsConstructor
public class OrderFinanceLinkageController {

    private final IncomeService incomeService;
    private final RefundService refundService;

    /**
     * 订单支付完成 → 记录收款
     * order-service 订单支付完成后调用此接口
     */
    @PostMapping("/payment/notify")
    public FinanceApiResponse<Map<String, Object>> notifyPayment(@RequestBody FinanceApiResponse.IncomeRecordRequest request) {
        try {
            log.info("[订单联动] 收到支付通知 orderNo={}, amount={}", request.getOrderNo(), request.getAmount());
            IncomeRecord record = incomeService.recordIncome(request);
            Map<String, Object> result = new HashMap<>();
            result.put("incomeNo", record.getIncomeNo());
            result.put("orderNo", record.getOrderNo());
            result.put("actualAmount", record.getActualAmount());
            result.put("status", record.getStatus());
            return FinanceApiResponse.success("收款记录创建成功", result);
        } catch (Exception e) {
            log.error("[订单联动] 支付通知处理失败 orderNo={}", request.getOrderNo(), e);
            return FinanceApiResponse.error(500, "支付通知处理失败: " + e.getMessage());
        }
    }

    /**
     * 订单取消 → 取消收款记录
     * order-service 订单取消后调用此接口
     */
    @PutMapping("/{orderNo}/cancel")
    public FinanceApiResponse<?> cancelOrderIncome(@PathVariable String orderNo,
                                                    @RequestParam String reason,
                                                    @RequestParam(required = false) String operator) {
        try {
            log.info("[订单联动] 取消订单收款 orderNo={}, reason={}", orderNo, reason);
            IncomeRecord existing = incomeService.getByOrderNo(orderNo);
            if (existing == null) {
                return FinanceApiResponse.success("无对应收款记录，跳过处理");
            }
            if (!IncomeRecord.STATUS_CANCELLED.equals(existing.getStatus())
                    && !IncomeRecord.STATUS_PENDING.equals(existing.getStatus())) {
                return FinanceApiResponse.error(400, "当前状态不允许取消: " + existing.getStatus());
            }
            incomeService.cancelIncome(existing.getId(), reason, operator);
            return FinanceApiResponse.success("订单收款已取消");
        } catch (Exception e) {
            log.error("[订单联动] 取消订单收款失败 orderNo={}", orderNo, e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 订单退款发起 → 创建退款记录（待确认）
     * order-service 发起退款时调用此接口
     */
    @PostMapping("/refund/create")
    public FinanceApiResponse<RefundRecordResponse> createOrderRefund(@RequestBody RefundService.RefundCreateRequest request) {
        try {
            log.info("[订单联动] 创建订单退款 orderNo={}, amount={}, source={}",
                    request.getOrderNo(), request.getRefundAmount(), request.getSource());
            request.setType(RefundRecord.TYPE_ORDER_REFUND);
            request.setSource(RefundRecord.SOURCE_ORDER);
            RefundRecord record = refundService.createRefundRecord(request);
            return FinanceApiResponse.success("退款记录创建成功", toRefundResponse(record));
        } catch (Exception e) {
            log.error("[订单联动] 创建订单退款失败 orderNo={}", request.getOrderNo(), e);
            return FinanceApiResponse.error(500, "创建退款记录失败: " + e.getMessage());
        }
    }

    /**
     * 订单退款完成 → 更新退款状态
     * order-service 退款成功后调用此接口
     */
    @PutMapping("/refund/{refundNo}/complete")
    public FinanceApiResponse<RefundRecordResponse> completeOrderRefund(@PathVariable String refundNo,
                                                                        @RequestParam String externalRefundNo,
                                                                        @RequestParam(required = false) String operator) {
        try {
            log.info("[订单联动] 完成订单退款 refundNo={}, externalRefundNo={}", refundNo, externalRefundNo);
            RefundRecord refund = refundService.getByRefundNo(refundNo);
            if (refund == null) {
                return FinanceApiResponse.notFound("退款记录不存在: " + refundNo);
            }
            RefundRecord updated = refundService.completeRefund(refund.getId(), externalRefundNo, operator);
            return FinanceApiResponse.success("退款完成", toRefundResponse(updated));
        } catch (Exception e) {
            log.error("[订单联动] 完成订单退款失败 refundNo={}", refundNo, e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 查询订单的收款和退款汇总
     */
    @GetMapping("/{orderNo}/summary")
    public FinanceApiResponse<Map<String, Object>> getOrderFinanceSummary(@PathVariable String orderNo) {
        try {
            log.info("[订单联动] 查询订单财务汇总 orderNo={}", orderNo);
            IncomeRecord income = incomeService.getByOrderNo(orderNo);
            Map<String, Object> summary = new HashMap<>();
            summary.put("orderNo", orderNo);
            summary.put("hasIncomeRecord", income != null);
            if (income != null) {
                summary.put("incomeNo", income.getIncomeNo());
                summary.put("incomeAmount", income.getActualAmount());
                summary.put("incomeStatus", income.getStatus());
                summary.put("paymentTime", income.getPaymentTime());
            }
            return FinanceApiResponse.success(summary);
        } catch (Exception e) {
            log.error("[订单联动] 查询订单财务汇总失败 orderNo={}", orderNo, e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 订单收款确认（人工确认）
     */
    @PutMapping("/income/{orderNo}/confirm")
    public FinanceApiResponse<IncomeRecordResponse> confirmOrderIncome(@PathVariable String orderNo,
                                                                       @RequestParam(required = false) String operator) {
        try {
            log.info("[订单联动] 确认订单收款 orderNo={}", orderNo);
            IncomeRecord income = incomeService.getByOrderNo(orderNo);
            if (income == null) {
                return FinanceApiResponse.notFound("未找到订单对应的收款记录: " + orderNo);
            }
            IncomeRecord confirmed = incomeService.confirmIncome(income.getId(), operator);
            return FinanceApiResponse.success("收款已确认", toIncomeResponse(confirmed));
        } catch (Exception e) {
            log.error("[订单联动] 确认订单收款失败 orderNo={}", orderNo, e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    private static RefundRecordResponse toRefundResponse(RefundRecord r) {
        return RefundRecordResponse.builder()
                .id(r.getId())
                .refundNo(r.getRefundNo())
                .orderNo(r.getOrderNo())
                .shortId(r.getShortId())
                .refundAmount(r.getRefundAmount())
                .refundReason(r.getRefundReason())
                .status(r.getStatus())
                .type(r.getType())
                .source(r.getSource())
                .operator(r.getOperator())
                .completeTime(r.getCompleteTime())
                .externalRefundNo(r.getExternalRefundNo())
                .createTime(r.getCreateTime())
                .build();
    }

    private static IncomeRecordResponse toIncomeResponse(IncomeRecord r) {
        return IncomeRecordResponse.builder()
                .id(r.getId())
                .incomeNo(r.getIncomeNo())
                .orderNo(r.getOrderNo())
                .shortId(r.getShortId())
                .platform(r.getPlatform())
                .shopId(r.getShopId())
                .shopName(r.getShopName())
                .amount(r.getAmount())
                .discountAmount(r.getDiscountAmount())
                .actualAmount(r.getActualAmount())
                .paymentMethod(r.getPaymentMethod())
                .paymentTime(r.getPaymentTime())
                .transactionId(r.getTransactionId())
                .accountNo(r.getAccountNo())
                .accountName(r.getAccountName())
                .status(r.getStatus())
                .source(r.getSource())
                .remark(r.getRemark())
                .createTime(r.getCreateTime())
                .build();
    }
}
