<?php

namespace App\Http\Controllers\Api;

use App\Http\logic\api\WDPayLogic;
use App\Http\logic\api\WDPayCashierLogic;
use App\Inter\PayMentInterFace;
use App\Notification\TelegramBot;
use App\Services\WDPay;
use App\Services\PayConfig;
use App\Services\PayUtils;
use App\Util;
use App\Utility\SetNXLock;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class WDPayController implements PayMentInterFace
{
    private $retryTimes = 0;

    public function pay_order($userId, $payAmt, $userName, $userEmail, $userPhone, $GiftsID, $buyIP, $AdId, $eventType, $pay_method = '')
    {
        $logic = new WDPayLogic();
        try {
            $res = $logic->pay_order($userId, $payAmt, $userPhone, $userEmail, $userName, $GiftsID, $buyIP, $AdId, $eventType, $pay_method);
        } catch (\Exception $exception) {
            Redis::set("PayErro_WDPay", 1);
            Redis::expire("PayErro_WDPay", 600);
            Util::WriteLog('WDPay_error', $exception->getMessage() . json_encode($logic->result ?? []));

            TelegramBot::getDefault()->sendProgramNotify("WDPay Except ", $exception->getMessage(), $exception);
            return apiReturnFail($logic->getError());
        }

        if (!empty($res) && isset($res['code']) && $res['code'] == 0) {
            $data = [
                'content' => $res['data']['cashierUrl'],
                'money' => $payAmt,
                'prdOrdNo' => $res['data']['mchOrderNo'],
            ];
            return apiReturnSuc($data);
        } else if ($res == false) {
            return apiReturnFail($logic->getError());
        } else {
            if ($this->retryTimes > 0) {
                Redis::set("PayErro_WDPay", 1);
                Redis::expire("PayErro_WDPay", 600);
                TelegramBot::getDefault()->sendProgramNotify("WDPay RetrunFail ", $logic->getError() . " | " . json_encode($res));
                return apiReturnFail($logic->getError());
            } else {
                $this->retryTimes++;
                return $this->pay_order($userId, $payAmt, $userName, $userEmail, $userPhone, $GiftsID, $buyIP, $AdId, $eventType, $pay_method);
            }
        }
    }

    // 支付异步回调
    public function notify(Request $request)
    {
        // WDPay官方回调格式（POST JSON）:
        // {
        //     "amount": "4.99",
        //     "currency": "USD",
        //     "customerOrderNo": "xxxxxx",
        //     "orderNo": "c66uNp01892LvA",
        //     "sign": "2D9AB732083EF62AED9990C96A2BBA17",
        //     "signType": "MD5",
        //     "status": "succeeded"  // succeeded=成功, closed=失败
        // }
        
        $post = $request->all();
        $payload = json_encode($post, JSON_UNESCAPED_UNICODE);

        Util::WriteLog('WDPay', "WDPay支付回调\n" . $payload);

        // 验证签名
        $service = new WDPay();
        
        try {
            $verify = $service->verifySign($post);
        } catch (\Exception $e) {
            Util::WriteLog('WDPay', '验签失败：' . $e->getMessage());
            return response()->json(['success' => false, 'message' => 'Sign verify failed']);
        }

        if (!$verify) {
            Util::WriteLog('WDPay', '签名错误');
            return response()->json(['success' => false, 'message' => 'Invalid sign']);
        }

        // 提取商户订单号
        $order_sn = $post['customerOrderNo'] ?? '';
        if (empty($order_sn)) {
            Util::WriteLog('WDPay', '缺少订单号');
            return response()->json(['success' => false, 'message' => 'Missing customerOrderNo']);
        }

        // 代收回调加锁，防止并发重复处理
        $lockKey = 'pay_notify_WDPay_' . $order_sn;
        if (!SetNXLock::getExclusiveLock($lockKey, 60)) {
            Util::WriteLog('WDPay', '代收回调并发，订单已处理或处理中: ' . $order_sn);
            return '{"msg":"success","code":200}';
        }

        $logic = new WDPayLogic();
        try {
            $redis = Redis::connection();
            $ret = $logic->notify($post);
            if ($ret == '{"msg":"success","code":200}') {
                $redis->set("wdpay_notify_" . $order_sn, $order_sn, 3600 * 24);
            }
            return $ret;
        } catch (\Exception $exception) {
            Redis::set("PayErro_WDPay", 1);
            Redis::expire("PayErro_WDPay", 600);
            TelegramBot::getDefault()->sendProgramNotify("WDPay 订单回调执行 异常 ", json_encode($post), $exception);
            Util::WriteLog("WDPay_error", $exception->getMessage());
            return response()->json(['success' => false, 'message' => 'Process failed']);
        } finally {
            SetNXLock::release($lockKey);
        }
    }

    public function sync_notify(Request $request)
    {
        Log::info('WDPay同步回调');
        echo 'WDPay同步回调';
    }

    // 提现异步回调
    public function cash_notify(Request $request)
    {
        $post = $request->all();
        $payload = json_encode($post);

        Util::WriteLog('WDPay', "WDPay cash 异步回调\n" . $payload);

        // ✅ 使用 WDPayOut 配置进行验签
        $payConfigService = new PayConfig();
        $config = $payConfigService->getConfig('WDPayOut');
        $apiKey = $config['key'];
        
        try {
            $verify = PayUtils::verifySign($post, $apiKey);
        } catch (\Exception $e) {
            Util::WriteLog('WDPay cash', '验签失败：' . $e->getMessage());
            return 'fail';
        }

        if (!$verify) {
            Util::WriteLog('WDPay cash', '签名错误');
            return 'fail';
        }

        $logic = new WDPayCashierLogic();
        try {
            return $logic->notify($post);
        } catch (\Exception $exception) {
            TelegramBot::getDefault()->sendProgramNotify("WDPay 提现异步回调执行 异常 ", json_encode($post), $exception);
            Util::WriteLog("WDPay_error", $post);
            return '{"success":false,"message":"商户自定义出错信息"}';
        }
    }
}
