package com.ruoyi.jarvis.service.impl;

import com.ruoyi.jarvis.domain.JDOrder;
import com.ruoyi.jarvis.domain.ProductJdConfig;
import com.ruoyi.jarvis.mapper.JDOrderMapper;
import com.ruoyi.jarvis.service.IJDOrderProfitService;
import com.ruoyi.jarvis.service.IProductJdConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@Service
public class JDOrderProfitServiceImpl implements IJDOrderProfitService {

    private static final double XIANYU_NET_FACTOR = 0.984;
    private static final double MONEY_EPS = 0.009;

    @Autowired
    private IProductJdConfigService productJdConfigService;

    @Autowired
    private JDOrderMapper jdOrderMapper;

    @Override
    public void recalculate(JDOrder order) {
        if (order == null) {
            return;
        }
        String mark = order.getDistributionMark() == null ? "" : order.getDistributionMark().trim();
        boolean profitLocked = order.getProfitManual() != null && order.getProfitManual() == 1;
        boolean sellingLocked = order.getSellingPriceManual() != null && order.getSellingPriceManual() == 1;

        // 已退款：不参与利润计算，自动利润清空（手填利润保留由调用方传入的 profit 与 profitManual 决定；此处仅清未锁定利润）
        if (order.getIsRefunded() != null && order.getIsRefunded() == 1) {
            if (!profitLocked) {
                order.setProfit(null);
            }
            return;
        }

        if ("H-TF".equals(mark)) {
            if (!profitLocked) {
                // H-TF 固定利润 15，再扣额外成本（不走 F 单售价公式）
                order.setProfit(BigDecimal.valueOf(15.0 - extraCostOrZero(order))
                        .setScale(2, RoundingMode.HALF_UP).doubleValue());
            }
            return;
        }

        // 其余分销标记：与 F / F-* / PDD / H / … 共用同一利润公式（含额外成本）；须有售价渠道 + 售价才自动算出利润，否则清空
        if (!sellingLocked) {
            fillSellingPriceFromConfig(order);
        }
        if (!profitLocked) {
            String type = order.getSellingPriceType();
            Double sp = order.getSellingPrice();
            if (type != null && !type.trim().isEmpty() && sp != null) {
                computeProfitForF(order);
            } else {
                order.setProfit(null);
            }
        }
    }

    private void fillSellingPriceFromConfig(JDOrder order) {
        String type = order.getSellingPriceType();
        if (type == null || type.isEmpty()) {
            return;
        }
        String model = order.getModelNumber();
        if (model == null || model.trim().isEmpty()) {
            return;
        }
        ProductJdConfig cfg = productJdConfigService.selectProductJdConfigByModel(model.trim());
        if (cfg == null) {
            return;
        }
        if ("direct".equals(type)) {
            BigDecimal p = cfg.getSellingPriceDirect();
            if (p != null) {
                order.setSellingPrice(p.doubleValue());
            }
        } else if ("xianyu".equals(type)) {
            BigDecimal p = cfg.getSellingPriceXianyu();
            if (p != null) {
                order.setSellingPrice(p.doubleValue());
            }
        }
    }

    private void computeProfitForF(JDOrder order) {
        String type = order.getSellingPriceType();
        Double sp = order.getSellingPrice();
        if (type == null || type.isEmpty() || sp == null) {
            order.setProfit(null);
            return;
        }
        double pay = order.getPaymentAmount() != null ? order.getPaymentAmount() : 0.0;
        double rebate = order.getRebateAmount() != null ? order.getRebateAmount() : 0.0;
        double netReceipt;
        if ("xianyu".equals(type)) {
            netReceipt = BigDecimal.valueOf(sp).multiply(BigDecimal.valueOf(XIANYU_NET_FACTOR))
                    .setScale(2, RoundingMode.HALF_UP).doubleValue();
        } else if ("direct".equals(type)) {
            netReceipt = sp;
        } else {
            order.setProfit(null);
            return;
        }
        // 成本 = 下单付款 - 后返金额；利润 = 对客实收 − 成本 − 额外成本
        double cost = BigDecimal.valueOf(pay).subtract(BigDecimal.valueOf(rebate))
                .setScale(2, RoundingMode.HALF_UP).doubleValue();
        double net = netReceipt - cost - extraCostOrZero(order);
        order.setProfit(BigDecimal.valueOf(net)
                .setScale(2, RoundingMode.HALF_UP).doubleValue());
    }

    private static double extraCostOrZero(JDOrder order) {
        Double e = order == null ? null : order.getExtraCost();
        return e != null ? e : 0.0;
    }

    @Override
    public int syncAutoProfitIfChanged(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return 0;
        }
        Set<Long> seen = new HashSet<>();
        int updated = 0;
        for (Long id : ids) {
            if (id == null || !seen.add(id)) {
                continue;
            }
            JDOrder order = jdOrderMapper.selectJDOrderById(id);
            if (order == null) {
                continue;
            }
            if (order.getIsRefunded() != null && order.getIsRefunded() == 1) {
                continue;
            }
            if (order.getProfitManual() != null && order.getProfitManual() == 1) {
                continue;
            }
            String oldType = order.getSellingPriceType();
            Double oldSp = order.getSellingPrice();
            Double oldProfit = order.getProfit();

            recalculate(order);

            if (sameNullableString(oldType, order.getSellingPriceType())
                    && sameMoney(oldSp, order.getSellingPrice())
                    && sameMoney(oldProfit, order.getProfit())) {
                continue;
            }
            order.getParams().put("applyProfitFields", Boolean.TRUE);
            updated += jdOrderMapper.updateJDOrder(order);
        }
        return updated;
    }

    private static boolean sameNullableString(String a, String b) {
        String x = a == null ? "" : a.trim();
        String y = b == null ? "" : b.trim();
        return Objects.equals(x, y);
    }

    private static boolean sameMoney(Double a, Double b) {
        if (a == null && b == null) {
            return true;
        }
        if (a == null || b == null) {
            return false;
        }
        return Math.abs(a - b) < MONEY_EPS;
    }
}
