package com.ruoyi.payment.controller;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.payment.domain.PaymentRecord;
import com.ruoyi.payment.service.IPaymentService;

/**
 * 支付处理API控制器
 *
 * 提供支付处理、收款确认、智能合约触发等RESTful API接口
 *
 * @author ruoyi
 * @date 2025-12-19
 */
@RestController
@RequestMapping("/api/payment")
public class PaymentController extends BaseController {

    @Autowired
    private IPaymentService paymentService;

    /**
     * 处理支付
     *
     * @param contractId 合同ID
     * @param payerId 支付方ID
     * @param payeeId 收款方ID
     * @param paymentAmount 支付金额
     * @param paymentMethod 支付方式
     * @param transactionId 交易流水号
     * @return 支付结果
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:add')")
    @Log(title = "支付处理", businessType = BusinessType.INSERT)
    @PostMapping("/process")
    public AjaxResult processPayment(
            @RequestParam("contractId") Long contractId,
            @RequestParam("payerId") Long payerId,
            @RequestParam("payeeId") Long payeeId,
            @RequestParam("paymentAmount") BigDecimal paymentAmount,
            @RequestParam("paymentMethod") String paymentMethod,
            @RequestParam("transactionId") String transactionId) {
        try {
            PaymentRecord payment = paymentService.processPayment(contractId, payerId, payeeId,
                    paymentAmount, paymentMethod, transactionId);
            return AjaxResult.success("支付处理成功", payment);
        } catch (Exception e) {
            logger.error("处理支付失败", e);
            return error("处理支付失败: " + e.getMessage());
        }
    }

    /**
     * 确认收款
     *
     * @param paymentId 支付记录ID
     * @return 确认结果
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:edit')")
    @Log(title = "支付处理", businessType = BusinessType.UPDATE)
    @PutMapping("/{paymentId}/confirm")
    public AjaxResult confirmPayment(@PathVariable("paymentId") Long paymentId) {
        try {
            boolean result = paymentService.confirmPayment(paymentId);
            return toAjax(result);
        } catch (Exception e) {
            logger.error("确认收款失败", e);
            return error("确认收款失败: " + e.getMessage());
        }
    }

    /**
     * 确认收款并触发智能合约
     *
     * @param paymentId 支付记录ID
     * @param contractAddress 智能合约地址
     * @return 智能合约执行结果
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:edit')")
    @Log(title = "支付处理", businessType = BusinessType.UPDATE)
    @PutMapping("/{paymentId}/confirm-and-trigger")
    public AjaxResult confirmPaymentAndTriggerContract(
            @PathVariable("paymentId") Long paymentId,
            @RequestParam("contractAddress") String contractAddress) {
        try {
            String result = paymentService.confirmPaymentAndTriggerContract(paymentId, contractAddress);
            return AjaxResult.success("智能合约执行成功", result);
        } catch (Exception e) {
            logger.error("确认收款并触发智能合约失败", e);
            return error("操作失败: " + e.getMessage());
        }
    }

    /**
     * 查询支付状态
     *
     * @param paymentId 支付记录ID
     * @return 支付状态
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:query')")
    @GetMapping("/{paymentId}/status")
    public AjaxResult getPaymentStatus(@PathVariable("paymentId") Long paymentId) {
        try {
            String status = paymentService.getPaymentStatus(paymentId);
            return AjaxResult.success("支付状态", status);
        } catch (Exception e) {
            logger.error("查询支付状态失败", e);
            return error("查询支付状态失败: " + e.getMessage());
        }
    }

    /**
     * 获取支付历史
     *
     * @param contractId 合同ID (可选)
     * @return 支付历史
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:list')")
    @GetMapping("/history")
    public TableDataInfo getPaymentHistory(@RequestParam(value = "contractId", required = false) Long contractId) {
        try {
            startPage();
            List<PaymentRecord> list;
            if (contractId != null) {
                list = paymentService.getPaymentsByContractId(contractId);
            } else {
                // 这里需要实现获取所有支付记录的方法
                list = paymentService.getPaymentsByContractId(null);
            }
            return getDataTable(list);
        } catch (Exception e) {
            logger.error("查询支付历史失败", e);
            return getDataTable(null);
        }
    }

    /**
     * 根据交易流水号查询支付记录
     *
     * @param transactionId 交易流水号
     * @return 支付记录
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:query')")
    @GetMapping("/transaction/{transactionId}")
    public AjaxResult getPaymentByTransactionId(@PathVariable("transactionId") String transactionId) {
        try {
            PaymentRecord payment = paymentService.getPaymentByTransactionId(transactionId);
            if (payment != null) {
                return success(payment);
            } else {
                return error("支付记录不存在");
            }
        } catch (Exception e) {
            logger.error("根据交易流水号查询支付记录失败", e);
            return error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 更新支付状态
     *
     * @param paymentId 支付记录ID
     * @param status 新状态
     * @return 更新结果
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:edit')")
    @Log(title = "支付处理", businessType = BusinessType.UPDATE)
    @PutMapping("/{paymentId}/status")
    public AjaxResult updatePaymentStatus(@PathVariable("paymentId") Long paymentId,
            @RequestParam("status") String status) {
        try {
            boolean result = paymentService.updatePaymentStatus(paymentId, status);
            return toAjax(result);
        } catch (Exception e) {
            logger.error("更新支付状态失败", e);
            return error("更新支付状态失败: " + e.getMessage());
        }
    }

    /**
     * 处理支付异常
     *
     * @param paymentId 支付记录ID
     * @param errorMessage 错误信息
     * @return 处理结果
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:edit')")
    @Log(title = "支付处理", businessType = BusinessType.UPDATE)
    @PutMapping("/{paymentId}/exception")
    public AjaxResult handlePaymentException(@PathVariable("paymentId") Long paymentId,
            @RequestParam("errorMessage") String errorMessage) {
        try {
            boolean result = paymentService.handlePaymentException(paymentId, errorMessage);
            return toAjax(result);
        } catch (Exception e) {
            logger.error("处理支付异常失败", e);
            return error("处理支付异常失败: " + e.getMessage());
        }
    }

    /**
     * 获取支付统计信息
     *
     * @param contractId 合同ID (可选)
     * @return 统计信息
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:query')")
    @GetMapping("/statistics")
    public AjaxResult getPaymentStatistics(@RequestParam(value = "contractId", required = false) Long contractId) {
        try {
            Map<String, Object> statistics = paymentService.getPaymentStatistics(contractId);
            return AjaxResult.success("统计信息", statistics);
        } catch (Exception e) {
            logger.error("获取支付统计信息失败", e);
            return error("获取统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 检查支付是否完成
     *
     * @param contractId 合同ID
     * @return 是否完成支付
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:query')")
    @GetMapping("/contract/{contractId}/completed")
    public AjaxResult isPaymentCompleted(@PathVariable("contractId") Long contractId) {
        try {
            boolean completed = paymentService.isPaymentCompleted(contractId);
            return AjaxResult.success("支付完成状态", completed);
        } catch (Exception e) {
            logger.error("检查支付完成状态失败", e);
            return error("检查失败: " + e.getMessage());
        }
    }

    /**
     * 计算合同应收金额
     *
     * @param contractId 合同ID
     * @return 应收金额
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:query')")
    @GetMapping("/contract/{contractId}/receivable")
    public AjaxResult getContractReceivableAmount(@PathVariable("contractId") Long contractId) {
        try {
            BigDecimal amount = paymentService.calculateContractReceivableAmount(contractId);
            return AjaxResult.success("应收金额", amount);
        } catch (Exception e) {
            logger.error("计算合同应收金额失败", e);
            return error("计算失败: " + e.getMessage());
        }
    }

    /**
     * 计算合同已收金额
     *
     * @param contractId 合同ID
     * @return 已收金额
     */
    @PreAuthorize("@ss.hasPermi('payment:payment:query')")
    @GetMapping("/contract/{contractId}/received")
    public AjaxResult getContractReceivedAmount(@PathVariable("contractId") Long contractId) {
        try {
            BigDecimal amount = paymentService.calculateContractReceivedAmount(contractId);
            return AjaxResult.success("已收金额", amount);
        } catch (Exception e) {
            logger.error("计算合同已收金额失败", e);
            return error("计算失败: " + e.getMessage());
        }
    }
}
