/**
* Controller handling VNPAY payment integration endpoints.
 *
 * Provides both web interface (JSP pages) and REST APIs for payment operations:
 * - Payment creation and processing
 * - Transaction status queries
 * - Refund operations
 * - Instant Payment Notification (IPN) handling
 *
 * Web Interface Endpoints:
 * - GET /      : Index page
 * - GET /pay   : Payment form
 * - GET /querydr : Transaction query
 * - GET /refund : Refund request
 * - GET /ipn   : IPN test interface
 *
 * REST API Endpoints:
 * - POST /api/payment/create : Create new payment
 * - POST /api/payment/process : Process payment return
 * - POST /api/payment/query    : Query transaction status
 * - POST /api/payment/refund : Request refund
 * - POST /ipn               : Handle IPN notifications
 *
 * Supports both JSP templates (/WEB-INF/jsp/) and HTML templates
(/resources/templates/)
 * for different view rendering needs.
 */
package Project_ITSS.IPaymentSubsytem.com.vnpay.common.controller;
import Project_ITSS.IPaymentSubsytem.com.vnpay.common.dto.*;
import Project_ITSS.IPaymentSubsytem.com.vnpay.common.service.VNPayService;
import Project_ITSS.IPaymentSubsytem.com.vnpay.common.service.VNPayService.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Controller
public class VNPayController {
    private static final Logger logger =
LoggerFactory.getLogger(VNPayController.class);
    private final VNPayService vnPayService;
    @Autowired
    public VNPayController(VNPayService vnPayService) {
        this.vnPayService = vnPayService;
    }
/**
 * View Controllers for rendering JSP pages
 */
/**
  * Renders the index page
  * @return index view name
  */
@GetMapping("/")
public String index() {
     return "index";
}
/**
  * Renders the payment form page
  * @return payment form view name
  */
@GetMapping("/pay")
public String paymentPage() {
     return "vnpay_pay";
}
/**
  * Renders the transaction query page
  * @return query form view name
  */
@GetMapping("/querydr")
public String queryPage() {
     return "vnpay_querydr";
}
/**
  * Renders the refund request page
  * @return refund form view name
  */
@GetMapping("/refund")
public String refundPage() {
     return "vnpay_refund";
}
/**
 * Handles the return URL from VNPAY after payment
 * Validates the payment response signature and displays the result
 *
 * @param requestParams Parameters returned from VNPAY
 * @param request HTTP request
 * @param model Spring MVC model
 * @return return page view name
 */
@GetMapping("/return")
public String returnPage(
        @RequestParam Map<String, String> requestParams,
        HttpServletRequest request,
        org.springframework.ui.Model model) {
    // Create copy of params for hash calculation
    Map<String, String> fields = new HashMap<>(requestParams);
    // Get and remove hash from param map before recalculating
          String vnp_SecureHash = fields.get("vnp_SecureHash");
          fields.remove("vnp_SecureHashType");
          fields.remove("vnp_SecureHash");
          // Create response object
          PaymentReturnResponse response = new PaymentReturnResponse();
          // Validate hash
          String signValue = vnPayService.hashAllFields(fields);
          response.setValidHash(signValue.equals(vnp_SecureHash));
          if (response.isValidHash()) {
              // Parse and validate required fields
              try {
                  response.setTransactionId(fields.get("vnp_TxnRef"));
                  response.setAmount(Long.parseLong(fields.getOrDefault("vnp_Amount",
"0")));
                  response.setOrderInfo(fields.get("vnp_OrderInfo"));
                  response.setResponseCode(fields.get("vnp_ResponseCode"));
                  response.setVnpayTransactionId(fields.get("vnp_TransactionNo"));
                  response.setBankCode(fields.get("vnp_BankCode"));
                  // Parse payment date
                  String payDate = fields.get("vnp_PayDate");
                  if (payDate != null && payDate.length() >= 14) {
                      LocalDateTime dateTime = LocalDateTime.parse(
                          payDate.substring(0, 14),
                          DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
                      );
                      response.setPaymentDate(dateTime);
                  }
                  response.setTransactionStatus(fields.get("vnp_TransactionStatus"));
              } catch (Exception e) {
                  // Log the error
                  logger.error("Error processing return URL parameters", e);
                  response.setMessage("Lỗi xử lý thông tin thanh toán");
                  response.setValidHash(false);
              }
          }
        // Log transaction details
        logger.info("Payment return - TxnId: {}, Amount: {}, Status: {},
ResponseCode: {}",
            response.getTransactionId(),
            response.getAmount(),
            response.getTransactionStatus(),
            response.getResponseCode()
        );
          model.addAttribute("payment", response);
          return "vnpay_return";
    }
    /**
     * Renders the IPN test page
     * @return IPN test view name
     */
    @GetMapping("/ipn")
    public String ipnPage() {
        return "vnpay_ipn";
    }
    /**
      * REST API Controllers for VNPAY integration
      */
    /**
      * API endpoint for creating a new payment
      * Generates payment URL with VNPAY signature
      *
      * @param request Payment request with amount and other details
      * @param servletRequest HTTP request for client IP
      * @return ResponseEntity with payment URL and status
      */
    @GetMapping("/api/payment/form")
    public String showPaymentForm() {
         return "payment-form";
    }
    @PostMapping("/api/payment/create")
    @ResponseBody
    public ResponseEntity<PaymentResponse> createPayment(
            @RequestBody PaymentRequest request,
            HttpServletRequest servletRequest) {
        PaymentResponse response = vnPayService.createPayment(request,
servletRequest);
        return ResponseEntity.ok(response);
    }
    @PostMapping("/api/payment/process")
    @ResponseBody
    public ResponseEntity<PaymentReturnResponse> processPayment(
            @RequestParam Map<String, String> requestParams) {
          Map<String, String> fields = new HashMap<>(requestParams);
          String vnp_SecureHash = fields.get("vnp_SecureHash");
          fields.remove("vnp_SecureHashType");
          fields.remove("vnp_SecureHash");
          PaymentReturnResponse response = new PaymentReturnResponse();
          String signValue = vnPayService.hashAllFields(fields);
          response.setValidHash(signValue.equals(vnp_SecureHash));
          if (response.isValidHash()) {
              try {
                  response.setTransactionId(fields.get("vnp_TxnRef"));
                  response.setAmount(Long.parseLong(fields.getOrDefault("vnp_Amount",
"0")));
                  response.setOrderInfo(fields.get("vnp_OrderInfo"));
                  response.setResponseCode(fields.get("vnp_ResponseCode"));
                  response.setVnpayTransactionId(fields.get("vnp_TransactionNo"));
                  response.setBankCode(fields.get("vnp_BankCode"));
                  String payDate = fields.get("vnp_PayDate");
                  if (payDate != null && payDate.length() >= 14) {
                      LocalDateTime dateTime = LocalDateTime.parse(
                          payDate.substring(0, 14),
                        DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
                    );
                    response.setPaymentDate(dateTime);
                }
                response.setTransactionStatus(fields.get("vnp_TransactionStatus"));
            } catch (Exception e) {
                logger.error("Error processing payment response", e);
                response.setMessage("Error processing payment information");
                response.setValidHash(false);
            }
        }
        logger.info("Payment processed - TxnId: {}, Amount: {}, Status: {},
ResponseCode: {}",
            response.getTransactionId(),
            response.getAmount(),
            response.getTransactionStatus(),
            response.getResponseCode()
        );
        return ResponseEntity.ok(response);
    }
    /**
      * API endpoint for querying transaction status
      *
      * @param request Query parameters with order ID
      * @param servletRequest HTTP request for client IP
      * @return ResponseEntity with transaction details
      */
    @PostMapping("/api/payment/query")
    @ResponseBody
    public ResponseEntity<QueryResponse> queryTransaction(
             @RequestBody QueryRequest request,
             HttpServletRequest servletRequest) {
         QueryResponse response = vnPayService.queryTransaction(request,
servletRequest);
         return ResponseEntity.ok(response);
    }
    /**
      * API endpoint for refund requests
      *
      * @param request Refund details including amount
      * @param servletRequest HTTP request for client IP
      * @return ResponseEntity with refund status
      */
    @PostMapping("/api/payment/refund")
    @ResponseBody
    public ResponseEntity<RefundResponse> refundTransaction(
             @RequestBody RefundRequest request,
             HttpServletRequest servletRequest) {
         RefundResponse response = vnPayService.refundTransaction(request,
servletRequest);
         return ResponseEntity.ok(response);
    }
    /**
     * Handles IPN (Instant Payment Notification) from VNPAY
     * Validates signature and processes payment confirmation
     *
     * @param requestParams Parameters sent by VNPAY
     * @return ResponseEntity with processing status
     */
    @PostMapping("/ipn")
    @ResponseBody
    public ResponseEntity<IPNResponse> handleIpnNotification(
            @RequestParam MultiValueMap<String, String> requestParams) {
        // Convert MultiValueMap to Map<String, String> for VNPay service
        Map<String, String> vnpParams = new HashMap<>();
        requestParams.forEach((key, value) -> {
            if (value != null && !value.isEmpty()) {
                vnpParams.put(key, value.get(0));
            }
        });
        IPNResponse response = vnPayService.handleIpnRequest(vnpParams);
        return ResponseEntity.ok(response);
    }
}