package com.njzscloud.supervisory.order.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.njzscloud.supervisory.order.config.WechatPayConfig;
import com.njzscloud.supervisory.order.pojo.dto.*;
import com.njzscloud.supervisory.order.service.WechatPayService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * 微信支付服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WechatPayServiceImpl implements WechatPayService {
    
    private final WechatPayConfig wechatPayConfig;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    
    private static final String WECHAT_PAY_API_BASE = "https://api.mch.weixin.qq.com";
    private static final String JSAPI_ORDER_URL = WECHAT_PAY_API_BASE + "/v3/pay/transactions/jsapi";
    private static final String ORDER_QUERY_URL = WECHAT_PAY_API_BASE + "/v3/pay/transactions/out-trade-no/";
    private static final String ORDER_CLOSE_URL = WECHAT_PAY_API_BASE + "/v3/pay/transactions/out-trade-no/";
    private static final String REFUND_URL = WECHAT_PAY_API_BASE + "/v3/refund/domestic/refunds";
    private static final String REFUND_QUERY_URL = WECHAT_PAY_API_BASE + "/v3/refund/domestic/refunds/";
    
    @Override
    public WechatPayJsapiOrderResponseDto createMiniProgramOrder(WechatPayJsapiOrderDto orderDto) {
        return createJsapiOrder(orderDto);
    }
    
    @Override
    public WechatPayJsapiOrderResponseDto createJsapiOrder(WechatPayJsapiOrderDto orderDto) {
        try {
            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("appid", wechatPayConfig.getSubAppId());
            requestBody.put("mchid", wechatPayConfig.getSubMchId());
            requestBody.put("description", orderDto.getDescription());
            requestBody.put("out_trade_no", orderDto.getOutTradeNo());
            requestBody.put("notify_url", wechatPayConfig.getNotifyUrl());
            
            // 金额信息
            Map<String, Object> amount = new HashMap<>();
            amount.put("total", orderDto.getTotal());
            amount.put("currency", orderDto.getCurrency());
            requestBody.put("amount", amount);
            
            // 支付者信息
            Map<String, Object> payer = new HashMap<>();
            payer.put("openid", orderDto.getOpenid());
            requestBody.put("payer", payer);
            
            // 发送请求
            HttpHeaders headers = createHeaders();
            HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(requestBody), headers);
            
            ResponseEntity<WechatPayJsapiOrderResponseDto> response = restTemplate.exchange(
                JSAPI_ORDER_URL,
                HttpMethod.POST,
                entity,
                WechatPayJsapiOrderResponseDto.class
            );
            
            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                WechatPayJsapiOrderResponseDto responseDto = response.getBody();
                // 生成小程序支付参数
                responseDto.setPaySign(generateMiniProgramPaySign(responseDto));
                return responseDto;
            }
            
            throw new RuntimeException("创建订单失败");
            
        } catch (Exception e) {
            log.error("创建JSAPI订单失败", e);
            throw new RuntimeException("创建订单失败: " + e.getMessage());
        }
    }
    
    @Override
    public WechatPayOrderQueryResponseDto queryOrder(String outTradeNo) {
        try {
            HttpHeaders headers = createHeaders();
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            ResponseEntity<WechatPayOrderQueryResponseDto> response = restTemplate.exchange(
                ORDER_QUERY_URL + outTradeNo + "?mchid=" + wechatPayConfig.getSubMchId(),
                HttpMethod.GET,
                entity,
                WechatPayOrderQueryResponseDto.class
            );
            
            return response.getBody();
            
        } catch (Exception e) {
            log.error("查询订单失败", e);
            throw new RuntimeException("查询订单失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean closeOrder(String outTradeNo) {
        try {
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("mchid", wechatPayConfig.getSubMchId());
            
            HttpHeaders headers = createHeaders();
            HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(requestBody), headers);
            
            ResponseEntity<Void> response = restTemplate.exchange(
                ORDER_CLOSE_URL + outTradeNo + "/close",
                HttpMethod.POST,
                entity,
                Void.class
            );
            
            return response.getStatusCode() == HttpStatus.NO_CONTENT;
            
        } catch (Exception e) {
            log.error("关闭订单失败", e);
            return false;
        }
    }
    
    @Override
    public WechatPayRefundResponseDto refund(WechatPayRefundDto refundDto) {
        try {
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("out_trade_no", refundDto.getOutTradeNo());
            requestBody.put("out_refund_no", refundDto.getOutRefundNo());
            requestBody.put("reason", refundDto.getReason());
            requestBody.put("notify_url", wechatPayConfig.getRefundNotifyUrl());
            
            // 金额信息
            Map<String, Object> amount = new HashMap<>();
            amount.put("refund", refundDto.getRefund());
            amount.put("total", refundDto.getTotal());
            amount.put("currency", "CNY");
            requestBody.put("amount", amount);
            
            HttpHeaders headers = createHeaders();
            HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(requestBody), headers);
            
            ResponseEntity<WechatPayRefundResponseDto> response = restTemplate.exchange(
                REFUND_URL,
                HttpMethod.POST,
                entity,
                WechatPayRefundResponseDto.class
            );
            
            return response.getBody();
            
        } catch (Exception e) {
            log.error("申请退款失败", e);
            throw new RuntimeException("申请退款失败: " + e.getMessage());
        }
    }
    
    @Override
    public WechatPayRefundResponseDto queryRefund(String outRefundNo) {
        try {
            HttpHeaders headers = createHeaders();
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            ResponseEntity<WechatPayRefundResponseDto> response = restTemplate.exchange(
                REFUND_QUERY_URL + outRefundNo,
                HttpMethod.GET,
                entity,
                WechatPayRefundResponseDto.class
            );
            
            return response.getBody();
            
        } catch (Exception e) {
            log.error("查询退款失败", e);
            throw new RuntimeException("查询退款失败: " + e.getMessage());
        }
    }
    
    @Override
    public String handlePaymentCallback(WechatPayCallbackDto callbackDto) {
        try {
            // 解密回调数据
            WechatPayCallbackDto.PaymentInfo paymentInfo = decryptCallbackData(
                callbackDto.getResource().getCiphertext(),
                callbackDto.getResource().getAssociatedData(),
                callbackDto.getResource().getNonce()
            );
            
            // 处理支付结果
            if ("SUCCESS".equals(paymentInfo.getTradeState())) {
                // 支付成功，更新订单状态
                log.info("支付成功，订单号: {}, 微信支付单号: {}", 
                    paymentInfo.getOutTradeNo(), paymentInfo.getTransactionId());
                // TODO: 更新订单状态到数据库
            }
            
            return "SUCCESS";
            
        } catch (Exception e) {
            log.error("处理支付回调失败", e);
            return "FAIL";
        }
    }
    
    @Override
    public String handleRefundCallback(WechatPayRefundCallbackDto callbackDto) {
        try {
            // 解密回调数据
            WechatPayRefundCallbackDto.RefundInfo refundInfo = decryptRefundCallbackData(
                callbackDto.getResource().getCiphertext(),
                callbackDto.getResource().getAssociatedData(),
                callbackDto.getResource().getNonce()
            );
            
            // 处理退款结果
            if ("SUCCESS".equals(refundInfo.getRefundStatus())) {
                // 退款成功，更新订单状态
                log.info("退款成功，退款单号: {}, 微信退款单号: {}", 
                    refundInfo.getOutRefundNo(), refundInfo.getRefundId());
                // TODO: 更新订单状态到数据库
            }
            
            return "SUCCESS";
            
        } catch (Exception e) {
            log.error("处理退款回调失败", e);
            return "FAIL";
        }
    }
    
    @Override
    public boolean verifyCallback(String timestamp, String nonce, String body, String signature) {
        try {
            String message = timestamp + "\n" + nonce + "\n" + body + "\n";
            String expectedSignature = generateSignature(message);
            return expectedSignature.equals(signature);
        } catch (Exception e) {
            log.error("验证回调签名失败", e);
            return false;
        }
    }
    
    /**
     * 创建请求头
     */
    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "WECHATPAY2-SHA256-RSA2048 " + generateAuthorization());
        headers.set("Accept", "application/json");
        return headers;
    }
    
    /**
     * 生成授权信息
     */
    private String generateAuthorization() {
        // TODO: 实现微信支付签名生成逻辑
        return "mock_authorization";
    }
    
    /**
     * 生成小程序支付签名
     */
    private String generateMiniProgramPaySign(WechatPayJsapiOrderResponseDto responseDto) {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("appId", wechatPayConfig.getSubAppId());
            params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
            params.put("nonceStr", generateNonceStr());
            params.put("package", "prepay_id=" + responseDto.getPrepayId());
            params.put("signType", "RSA");
            
            // 生成签名
            String sign = generateSignature(buildSignString(params));
            params.put("paySign", sign);
            
            return objectMapper.writeValueAsString(params);
            
        } catch (Exception e) {
            log.error("生成小程序支付签名失败", e);
            throw new RuntimeException("生成支付签名失败");
        }
    }
    
    /**
     * 生成签名
     */
    private String generateSignature(String message) {
        try {
            // TODO: 使用商户私钥生成RSA签名
            return "mock_signature";
        } catch (Exception e) {
            log.error("生成签名失败", e);
            throw new RuntimeException("生成签名失败");
        }
    }
    
    /**
     * 构建签名字符串
     */
    private String buildSignString(Map<String, String> params) {
        return params.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .map(entry -> entry.getKey() + "=" + entry.getValue())
            .reduce((a, b) -> a + "&" + b)
            .orElse("");
    }
    
    /**
     * 生成随机字符串
     */
    private String generateNonceStr() {
        return UUID.randomUUID().toString().replace("-", "");
    }
    
    /**
     * 解密回调数据
     */
    private WechatPayCallbackDto.PaymentInfo decryptCallbackData(String ciphertext, String associatedData, String nonce) {
        try {
            // TODO: 实现AES-256-GCM解密
            return new WechatPayCallbackDto.PaymentInfo();
        } catch (Exception e) {
            log.error("解密回调数据失败", e);
            throw new RuntimeException("解密回调数据失败");
        }
    }
    
    /**
     * 解密退款回调数据
     */
    private WechatPayRefundCallbackDto.RefundInfo decryptRefundCallbackData(String ciphertext, String associatedData, String nonce) {
        try {
            // TODO: 实现AES-256-GCM解密
            return new WechatPayRefundCallbackDto.RefundInfo();
        } catch (Exception e) {
            log.error("解密退款回调数据失败", e);
            throw new RuntimeException("解密退款回调数据失败");
        }
    }
}
