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

import com.google.api.client.util.Maps;
import com.red.circle.component.pay.paymax.PayMaxUtils;
import com.red.circle.framework.core.request.RequestClientEnum;
import com.red.circle.framework.web.props.EnvProperties;
import com.red.circle.order.app.common.PayerMaxProperties;
import com.red.circle.order.app.common.QuoteQueryParam;
import com.red.circle.order.app.common.QuoteQueryResponse;
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseDetailsService;
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseEventNotice;
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseFactory;
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseStatusStep;
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.http.RcHttpClient;
import com.red.circle.tool.core.json.JacksonUtils;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author pengliang on 2022/11/2
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PayPlaceAnOrderService {

  private final EnvProperties envProperties;
  private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
  private final FactoryPlaceAnOrderStrategyV2 factoryPlaceAnOrderStrategyV2;
  private final PayerMaxProperties payerMaxProperties;
  private final RcHttpClient rcHttpClient = RcHttpClient.builder().build();

  public PlaceAnOrderResponseCO doRequest(PayPlaceAnOrderDetailsV2 param) {
    // 第三方：请求下单
    PlaceAnOrderResponseCO response = factoryPlaceAnOrderStrategyV2.getStrategy(
            param.getStrategyCode())
        .doOperation(param);

    // 创建站内：预支付订单.
    inAppPurchaseDetailsService.create(
        new InAppPurchaseDetails()
            .setId(param.getOrderId())
            .setTrackId(param.getApplicationId())
            .setTrackCommodityType(param.getAppCommodityType())
            .setReceiptType(param.getReceiptType())
            .setSysOrigin(param.getSysOrigin())
            .setAcceptUserId(param.getAcceptUserId())
            .setOrderId(response.getTradeNo())
            .setEnv(env())
            .setFactory(
                new InAppPurchaseFactory()
                    .setPlatform(RequestClientEnum.H5.getClientName())
                    .setFactoryCode(param.getFactoryCode())
                    .setFactoryChannelCode(param.getChannelCode())
            )
            .setProducts(param.getProducts())
            .setProductDescriptor(param.getProductDescriptor())
            .setCountryCode(response.getCountryCode())
            .setCurrency(param.getCurrency())
            .setAmount(param.getAmount())
            .setAmountUsd(param.getAmountUsd())
            .setTrialPeriod(Boolean.FALSE)
            .setStatus(InAppPurchaseStatus.CREATE)
            .setReason("")
            .setPurchaseDateMs(TimestampUtils.now())
            .setCreateTime(TimestampUtils.now())
            .setUpdateTime(TimestampUtils.now())
            .setCreateUser(param.getCreateUserId())
            .setStatusSteps(List.of(
                new InAppPurchaseStatusStep()
                    .setStatus(InAppPurchaseStatus.CREATE)
                    .setCreateTime(TimestampUtils.now())
            ))
            .setPayNotices(List.of(
                new InAppPurchaseEventNotice()
                    .setEventId("custom-request-response-param")
                    .setNoticeType("API-INTERNAL-PARAMETERS")
                    .setNoticeData(response.extra())
                    .setCreateTime(TimestampUtils.now())
            ))
            .setMetadata(Maps.newHashMap())
            .setVersion(0)
    );

    return response;
  }

  private String env() {
    return envProperties.isProd() ? PayEnv.PROD.name() : PayEnv.TEST.name();
  }

  /**
   * 查询实时汇率
   * @param baseCurrency 基础币种（如USD）
   * @param targetCurrency 目标币种（如CNY）
   * @return 汇率值
   */
  public BigDecimal getRealTimeExchangeRate(String baseCurrency, String targetCurrency) {
    try {
      QuoteQueryParam param = new QuoteQueryParam();
      QuoteQueryParam.QuoteQueryData data = new QuoteQueryParam.QuoteQueryData();

      // 币种对格式：基础币种+目标币种，如USDCNY
      String ccyPair = baseCurrency + targetCurrency;
      data.setCcyPairList(Arrays.asList(ccyPair));
      data.setPriceTypeList(Arrays.asList("OFFER")); // 使用卖出价

      param.setAppId(payerMaxProperties.getAppId());
      param.setMerchantNo(payerMaxProperties.getMerchantId());
      param.setData(data);

      String url = payerMaxProperties.getGatewayBaseUrl() + "/aggregate-pay/api/gateway/quoteQuery";
      String jsonParam = JacksonUtils.toJson(param);
      String signature = PayMaxUtils.signRsa(jsonParam, payerMaxProperties.getRsaPrivateKey());
      
      if (!envProperties.isProd()) {
        log.info("Exchange Rate Query Request: {}\nParam:{}\nSign:{}", url, jsonParam, signature);
      }
      
      QuoteQueryResponse response = rcHttpClient.post()
          .uri(url)
          .header("sign", signature)
          .contentType("application/json")
          .bodyValue(jsonParam)
          .retrieve()
          .bodyToEntity(QuoteQueryResponse.class)
          .block();
      
      if (response != null && response.isSuccess() && response.getData() != null 
          && response.getData().getRateList() != null && !response.getData().getRateList().isEmpty()) {
        // 使用offerRate（卖出价）作为汇率
        BigDecimal rate = response.getData().getRateList().get(0).getOfferRate();
        log.info("Successfully got real-time exchange rate from {} to {}: {}", baseCurrency, targetCurrency, rate);
        return rate;
      } else {
        log.error("Failed to get real-time exchange rate, response: {}", 
                 response != null ? JacksonUtils.toJson(response) : "null");
        return null;
      }
    } catch (Exception e) {
      log.error("Error occurred while querying real-time exchange rate from {} to {}", 
               baseCurrency, targetCurrency, e);
      return null;
    }
  }

}
