<?php

namespace App\Http\Controllers\Api;

use App\Http\logic\api\SfPayLogic;
use App\Http\logic\api\SfPayCashierLogic;
use App\Inter\PayMentInterFace;
use App\Notification\TelegramBot;
use App\Services\SfPay;
use App\Util;
use App\Utility\SetNXLock;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;

class SfPayController implements PayMentInterFace
{
    /**
     * 代收下单
     */
    public function pay_order(
        $userId,
        $payAmt,
        $userName,
        $userEmail,
        $userPhone,
        $GiftsID,
        $buyIP,
        $AdId,
        $eventType,
        $pay_method = ''
    ) {
        $logic = new SfPayLogic();
        try {
            $res = $logic->pay_order($userId, $payAmt, $userPhone, $userEmail, $userName, $GiftsID, $buyIP, $AdId, $eventType, $pay_method);
        } catch (\Exception $exception) {
            Redis::set("PayErro_SfPay", 1);
            Redis::expire("PayErro_SfPay", 600);
            Util::WriteLog('SfPay_error', $exception->getMessage() . json_encode($logic->result ?? []));
            TelegramBot::getDefault()->sendProgramNotify("SfPay Except ", $exception->getMessage(), $exception);
            return apiReturnFail($logic->getError());
        }

        if (!empty($res) && isset($res['code']) && $res['code'] === 0) {
            // SfPay 成功返回: data.paymentLinkUrl 是支付链接
            $data = [
                'content'  => $res['data']['paymentLinkUrl'] ?? '',
                'money'    => $payAmt,
                'prdOrdNo' => $res['data']['orderNo'] ?? '',
            ];
            return apiReturnSuc($data);
        }

        if ($res == false) {
            return apiReturnFail($logic->getError() ?: 'Payment failed');
        }

        // 非0的响应，记录错误
        Redis::set("PayErro_SfPay", 1);
        Redis::expire("PayErro_SfPay", 600);
        $errMsg = $res['msg'] ?? 'Unknown error';
        TelegramBot::getDefault()->sendProgramNotify("SfPay ReturnFail ", $errMsg . " | " . json_encode($res) . "$userId");
        return apiReturnFail(['web.payment.paytype_error', $errMsg]);
    }

    /**
     * 代收异步回调通知
     *
     * SfPay回调格式（POST JSON，不加密）:
     * {
     *   "data": {
     *     "amount": "20.00",
     *     "orderNo": "...",
     *     "message": "Success",
     *     "type": "payment",
     *     "merchantOrderNo": "...",
     *     "processedTime": "...",
     *     "transferMode": "PIX",
     *     "status": "SUCCESS"
     *   },
     *   "signature_n": "..."
     * }
     */
    public function notify(Request $request)
    {
        $post = $request->all();
        $payload = json_encode($post);

        Util::WriteLog('SfPay', "SfPay回调订单\n" . $payload);

        $callbackData = $post['data'] ?? [];
        $signatureN = $post['signature_n'] ?? '';

        if (empty($callbackData) || empty($signatureN)) {
            Util::WriteLog('SfPay', '回调数据不完整');
            return response()->json(['code' => 200]);
        }

        // 验签
        $service = new SfPay();
        if (!$service->verifySign($callbackData, $signatureN)) {
            Util::WriteLog('SfPay', '签名错误');
            return response()->json(['code' => 200]);
        }

        $order_sn = $callbackData['merchantOrderNo'] ?? '';
        if (empty($order_sn)) {
            Util::WriteLog('SfPay', '缺少商户订单号');
            return response()->json(['code' => 200]);
        }

        // 代收回调加锁，防止并发重复处理
        $lockKey = 'pay_notify_SfPay_' . $order_sn;
        if (!SetNXLock::getExclusiveLock($lockKey, 60)) {
            Util::WriteLog('SfPay', '代收回调并发，订单已处理或处理中: ' . $order_sn);
            return response()->json(['code' => 200]);
        }

        $logic = new SfPayLogic();
        try {
            $ret = $logic->notify($post);
            return response()->json(['code' => 200]);
        } catch (\Exception $exception) {
            Redis::set("PayErro_SfPay", 1);
            Redis::expire("PayErro_SfPay", 600);
            TelegramBot::getDefault()->sendProgramNotify("SfPay 订单回调执行异常 ", json_encode($post), $exception);
            Util::WriteLog("SfPay_error", $post);
            return response()->json(['code' => 200]);
        } finally {
            SetNXLock::release($lockKey);
        }
    }

    /**
     * 代付异步回调通知
     *
     * SfPay代付回调格式（POST JSON，不加密）:
     * {
     *   "data": {
     *     "amount": "30.00",
     *     "orderNo": "...",
     *     "message": "...",
     *     "type": "payout",
     *     "merchantOrderNo": "...",
     *     "processedTime": "...",
     *     "processAmount": "0.00",
     *     "status": "SUCCESS"
     *   },
     *   "signature_n": "..."
     * }
     */
    public function cash_notify(Request $request)
    {
        $post = $request->all();
        $payload = json_encode($post);

        Util::WriteLog('SfPay', "SfPay 提现回调\n" . $payload);

        $callbackData = $post['data'] ?? [];
        $signatureN = $post['signature_n'] ?? '';

        if (empty($callbackData) || empty($signatureN)) {
            Util::WriteLog('SfPay', '提现回调数据不完整');
            return response('SUCCESS');
        }

        // 验签
        $service = new SfPay();
        if (!$service->verifySign($callbackData, $signatureN)) {
            Util::WriteLog('SfPay', '提现回调签名错误');
            return response('SUCCESS');
        }

        $logic = new SfPayCashierLogic();
        try {
            return $logic->notify($post);
        } catch (\Exception $exception) {
            TelegramBot::getDefault()->sendProgramNotify(
                "SfPay 提现异步回调执行异常 ",
                json_encode($post),
                $exception
            );
            Util::WriteLog("SfPay_error", $post);
            return response('SUCCESS');
        }
    }

    /**
     * 代收订单主动查询
     *
     * POST /api/sfpay/orderQuery
     * 用于回调未到达时主动查询订单状态
     */
    public function orderQuery(Request $request)
    {
        $merchantOrderNo = $request->input('merchantOrderNo', '');

        if (empty($merchantOrderNo)) {
            return apiReturnFail('merchantOrderNo is required');
        }

        $logic = new SfPayLogic();
        try {
            $res = $logic->orderQuery($merchantOrderNo);
        } catch (\Exception $e) {
            Util::WriteLog('SfPay_error', 'orderQuery exception: ' . $e->getMessage());
            return apiReturnFail('Query failed');
        }

        if ($res === false) {
            return apiReturnFail($logic->getError() ?: 'Query failed');
        }

        if (isset($res['code']) && $res['code'] === 0) {
            return apiReturnSuc($res['data'] ?? []);
        }

        return apiReturnFail($res['msg'] ?? 'Query error');
    }
}
