package com.red.circle.order.app.command.pay.web.strategy;

import com.red.circle.component.pay.paymax.service.PlaceAnOrderParam;
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.ResponseErrorCode;
import com.red.circle.order.app.common.MiFaPayPlaceAnOrderParam;
import com.red.circle.order.app.dto.clientobject.MiFaPayResponseCO;
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
import com.red.circle.order.app.service.MiFaPayService;
import com.red.circle.order.domain.payer.PlaceAnOrderPaymentDetail;
import com.red.circle.order.infra.util.MemberInfoGenerator;
import com.red.circle.order.inner.asserts.OrderErrorCode;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.text.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * MiFaPay web 支付策略
 *
 * @author system
 */
@Slf4j
@Component("MIFA_PAY_PLACE_AN_ORDER")
@RequiredArgsConstructor
public class MiFaPayWebPayPlaceAnOrderStrategy implements PayWebPlaceAnOrderStrategyV2 {

    private final MiFaPayService miFaPayService;

    @Override
    public PlaceAnOrderResponseCO doOperation(PayPlaceAnOrderDetailsV2 details) {
        MiFaPayPlaceAnOrderParam param = getPlaceAnOrderParam(details);

        MiFaPayResponseCO response = requestApi(details, param);
        ResponseAssert.notNull(OrderErrorCode.CREATE_ORDER_ERROR, response);

        // 500 支付失败，调用第三方错误
        if (!response.isSuccess()) {
            ResponseAssert.failure(ResponseErrorCode.INTERNAL_SERVER_ERROR, response.getMsg());
        }

        // 解析内层data数据
        MiFaPayResponseCO.MiFaPayData data = parseResponseData(response.getData());

        return new PlaceAnOrderResponseCO()
                .setTradeNo(data != null ? data.getMbOrderId() : null)
                .setOrderId(data != null ? data.getOrderId() : details.getOrderId())
                .setCurrency(details.getCurrency())
                .setCountryCode(details.getCountryCode())
                .setFactoryCode(details.getFactoryCode())
                .setFactoryChannelCode(details.getFactoryChannel())
                .setRequestUrl(data != null ? data.getPayUrl() : null)
                .putRequestParam(param)
                .putResponseParam(response);
    }

    private MiFaPayResponseCO requestApi(PayPlaceAnOrderDetailsV2 details, MiFaPayPlaceAnOrderParam param) {
        try {
            return miFaPayService.placeAnOrder(param, details.getSysOrigin());
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("MiFaPay订单创建请求失败:details={}、requestParam={}",
                    JacksonUtils.toJson(details), JacksonUtils.toJson(param));
        }
        return null;
    }

    private MiFaPayPlaceAnOrderParam getPlaceAnOrderParam(PayPlaceAnOrderDetailsV2 details) {
        // 构建商品信息
        List<MiFaPayPlaceAnOrderParam.ProductInfo> products = details.getProducts().stream()
                .map(p -> MiFaPayPlaceAnOrderParam.ProductInfo.builder()
                        .sku(p.getCode())
                        .productName(p.getName())
                        .price(p.getAmountUsd().multiply(new BigDecimal("100")).toBigInteger().toString())
                        .quantity(String.valueOf(p.getQuantity()))
                        .build())
                .collect(Collectors.toList());

        // 金额转分（乘以100，去掉小数点）
        String amountInCents = details.getAmount()
                .multiply(new BigDecimal("100"))
                .toBigInteger()
                .toString();

        MemberInfoGenerator.MemberInfo memberInfo = MemberInfoGenerator.generate(String.valueOf(details.getAcceptUserId()));

        return MiFaPayPlaceAnOrderParam.builder()
                .merNo(null) // Service中会设置
                .orderId(details.getOrderId())
                .memberId(Objects.toString(details.getAcceptUserId()))
                .time(System.currentTimeMillis() / 1000)
                .amount(amountInCents)
                .currency(details.getCurrency())
                .payWay(extractPayWay(details.getChannelCode()))
                .payType(details.getFactoryChannel())
                .userIp(details.getRequestIp())
                .returnUrl(details.getSuccessRedirectUrl())
                .notifyUrl(miFaPayService.getNotifyUrl(details.getSysOrigin()))
                .language("en")
                .email(memberInfo.getEmail())
                .countryCode(replaceCountryCode(details.getCountryCode()))
                .firstName(memberInfo.getFirstName())
                .lastName(memberInfo.getLastName())
                .phone(memberInfo.getPhone())
                .productInfo(MiFaPayPlaceAnOrderParam.buildProductInfoJson(products))
                .terminalType("WEB")
                .build();
    }

    private String extractPayWay(String channelCode) {
        if (channelCode == null || channelCode.isEmpty()) {
            return channelCode;
        }

        int underscoreIndex = channelCode.indexOf('_');
        return underscoreIndex > 0 ? channelCode.substring(0, underscoreIndex) : channelCode;
    }

    private static String replaceCountryCode(String countryCode) {
        return CountryCodeAliasUtils.normalizePaymentCountryCode(countryCode);
    }


    private String getPlaceAnOrderPaymentDetailParam(PayPlaceAnOrderDetailsV2 details) {
        if (StringUtils.isBlank(details.getChannelCode())) {
            return null;
        }

        if (StringUtils.isBlank(details.getFactoryChannel())) {
            return null;
        }

        PlaceAnOrderPaymentDetail paymentDetail = new PlaceAnOrderPaymentDetail();
        paymentDetail.setPaymentType(details.getFactoryChannel());
        if (paymentDetail.getPaymentType().equals("PROMPTPAY")) {
            paymentDetail.setPaymentType("REALTIME_PAYMENT");
            paymentDetail.setTargetOrg("PROMPTPAY");
        }
        return paymentDetail.toString();
    }

    /**
     * 解析响应中的data字段（JSON字符串）
     */
    private MiFaPayResponseCO.MiFaPayData parseResponseData(String dataJson) {
        if (StringUtils.isBlank(dataJson)) {
            return null;
        }
        try {
            return JacksonUtils.readValue(dataJson, MiFaPayResponseCO.MiFaPayData.class);
        } catch (Exception e) {
            log.error("MiFaPay解析响应data失败: {}", dataJson, e);
            return null;
        }
    }
}
