<?php

namespace App\Http\Controllers\Api;

use App\Http\logic\api\PagYeepPayLogic;
use App\Http\logic\api\PagYeepPayCashierLogic;
use App\Inter\PayMentInterFace;
use App\Notification\TelegramBot;
use App\Services\PagYeepPay;
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 PagYeepPayController implements PayMentInterFace
{
    private $retryTimes = 0;

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

            TelegramBot::getDefault()->sendProgramNotify("PagYeepPay 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_PagYeepPay", 1);
                Redis::expire("PayErro_PagYeepPay", 600);
                TelegramBot::getDefault()->sendProgramNotify("PagYeepPay 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)
    {
        // PagYeepPay回调格式（POST form表单）:
        // version, orgNo, custId, custOrderNo, prdOrdNo, payAmt, ordStatus, sign
        
        $post = $request->all();
        $payload = json_encode($post, JSON_UNESCAPED_UNICODE);

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

        // 验证签名
        $service = new PagYeepPay();
        
        try {
            $verify = $service->verifySign($post);
        } catch (\Exception $e) {
            Util::WriteLog('PagYeepPay', '验签失败：' . $e->getMessage());
            return 'SC000000';  // 仍然返回成功，避免重复回调
        }

        if (!$verify) {
            Util::WriteLog('PagYeepPay', '签名错误');
            return 'SC000000';  // 仍然返回成功，避免重复回调
        }

        // 提取商户订单号
        $order_sn = $post['custOrderNo'] ?? '';
        if (empty($order_sn)) {
            Util::WriteLog('PagYeepPay', '缺少订单号');
            return 'SC000000';
        }

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

        $logic = new PagYeepPayLogic();
        try {
            $redis = Redis::connection();
            $ret = $logic->notify($post);
            if ($ret == 'SC000000') {
                $redis->set("pagyeepay_notify_" . $order_sn, $order_sn, 3600 * 24);
            }
            return $ret;
        } catch (\Exception $exception) {
            Redis::set("PayErro_PagYeepPay", 1);
            Redis::expire("PayErro_PagYeepPay", 600);
            TelegramBot::getDefault()->sendProgramNotify("PagYeepPay 订单回调执行 异常 ", json_encode($post), $exception);
            Util::WriteLog("PagYeepPay_error", $exception->getMessage());
            return 'SC000000';
        } finally {
            SetNXLock::release($lockKey);
        }
    }

    public function sync_notify(Request $request)
    {
       echo "Success";
    }

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

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

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

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

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