<?php

/**
 * 文件功能：前台 VIP 支付控制器
 * 负责用户发起 VIP 支付、接收同步回调、接收异步通知并驱动本地会员开通
 */

namespace App\Http\Controllers;

use App\Http\Requests\CreateVipPaymentOrderRequest;
use App\Models\VipLevel;
use App\Services\VipPaymentCenterClient;
use App\Services\VipPaymentService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use RuntimeException;

/**
 * 前台 VIP 支付控制器
 * 负责接收用户选择的支付渠道，下发支付中心订单并处理回调结果。
 */
class VipPaymentController extends Controller
{
    /**
     * 构造函数
     *
     * @param  VipPaymentService  $vipPaymentService  本地 VIP 支付服务
     * @param  VipPaymentCenterClient  $paymentCenterClient  远端支付中心客户端
     */
    public function __construct(
        private readonly VipPaymentService $vipPaymentService,
        private readonly VipPaymentCenterClient $paymentCenterClient,
    ) {}

    /**
     * 创建 VIP 支付订单并跳转到 NovaLink 支付页
     *
     * @param  CreateVipPaymentOrderRequest  $request  已校验的购买请求
     */
    public function store(CreateVipPaymentOrderRequest $request): RedirectResponse
    {
        if (! $this->paymentCenterClient->isEnabled() || ! $this->paymentCenterClient->hasValidConfig()) {
            return redirect()->route('vip.center')->with('error', 'VIP 支付暂未开放，请联系管理员完成后台配置。');
        }

        $vipLevel = VipLevel::query()->findOrFail((int) $request->validated('vip_level_id'));
        $provider = (string) $request->validated('provider');

        try {
            // 先创建本地订单，再向支付中心发起下单，确保回调时有本地单据可追踪。
            $vipPaymentOrder = $this->vipPaymentService->createLocalOrder($request->user(), $vipLevel, $provider);
            $remoteOrder = $this->vipPaymentService->createRemoteOrder($vipPaymentOrder);
            $payUrl = (string) ($remoteOrder['pay_url'] ?? '');

            if ($payUrl === '') {
                throw new RuntimeException('支付中心未返回可用的支付地址。');
            }

            return redirect()->away($payUrl);
        } catch (\Throwable $exception) {
            return redirect()->route('vip.center')->with('error', '创建 VIP 支付订单失败：'.$exception->getMessage());
        }
    }

    /**
     * 处理支付完成后的同步回调
     *
     * @param  Request  $request  支付中心跳转返回参数
     */
    public function handleReturn(Request $request): RedirectResponse
    {
        $payload = $request->all();
        $vipPaymentOrder = $this->vipPaymentService->findByPaymentOrderNo($request->string('payment_order_no')->toString())
            ?? $this->vipPaymentService->findByMerchantOrderNo($request->string('merchant_order_no')->toString());

        if (! $vipPaymentOrder) {
            return redirect()->route('vip.center')->with('error', '未找到对应的 VIP 支付订单，请稍后在后台核对。');
        }

        $this->vipPaymentService->recordSyncReturn($vipPaymentOrder, $payload);

        try {
            // 同步回调只做页面回跳，但这里补查一次可让用户尽快看到最终结果。
            $vipPaymentOrder = $this->vipPaymentService->syncRemoteStatus($vipPaymentOrder);
        } catch (\Throwable $exception) {
            return redirect()->route('vip.center')->with('error', '支付结果正在确认中，请稍后刷新查看。');
        }

        if ($vipPaymentOrder->isVipOpened()) {
            return redirect()->route('vip.center')->with('success', 'VIP 支付成功，会员已开通。');
        }

        return redirect()->route('vip.center')->with('success', '支付页面已返回，系统正在确认支付结果，请稍后刷新查看。');
    }

    /**
     * 接收 NovaLink 支付中心的异步通知
     *
     * @param  Request  $request  支付中心回调请求
     */
    public function notify(Request $request): Response
    {
        $rawBody = $request->getContent();
        $signature = (string) $request->header('X-Payment-Signature', '');

        if (! $this->paymentCenterClient->isValidWebhookSignature($signature, $rawBody)) {
            return response('invalid signature', 401);
        }

        $payload = $request->json()->all();
        $vipPaymentOrder = $this->vipPaymentService->findByPaymentOrderNo($payload['payment_order_no'] ?? null)
            ?? $this->vipPaymentService->findByMerchantOrderNo($payload['merchant_order_no'] ?? null);

        if (! $vipPaymentOrder) {
            return response('order not found', 404);
        }

        if (($payload['status'] ?? '') !== 'paid') {
            return response('ignored', 200);
        }

        try {
            // 异步回调才是最终支付成功依据，这里完成幂等开通 VIP 的核心逻辑。
            $this->vipPaymentService->markOrderAsPaid($vipPaymentOrder, $payload, 'async');

            return response('success', 200);
        } catch (\Throwable $exception) {
            return response('error: '.$exception->getMessage(), 500);
        }
    }
}
