<?php

namespace App\Http\Controllers\Api;

use App\Http\logic\api\AiPayCashierLogic;
use App\Http\logic\api\AiPayLogic;
use App\Inter\PayMentInterFace;
use App\Notification\TelegramBot;
use App\Services\AiPay;
use App\Util;
use App\Utility\SetNXLock;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;

class AiPayController implements PayMentInterFace
{
    private $retryTimes = 0;

    public function pay_order($userId, $payAmt, $userName, $userEmail, $userPhone, $GiftsID, $buyIP, $AdId, $eventType, $pay_method = '')
    {
        $logic = new AiPayLogic();
        try {
            $res = $logic->pay_order($userId, $payAmt, $userPhone, $userEmail, $userName, $GiftsID, $buyIP, $AdId, $eventType, $pay_method);
        } catch (\Throwable $exception) {
            Redis::set('PayErro_AiPay', 1, 'EX', 600);
            Util::WriteLog('AiPay_error', $exception->getMessage());
            TelegramBot::getDefault()->sendProgramNotify('AiPay pay_order exception', $exception->getMessage(), $exception);
            return apiReturnFail($logic->getError());
        }

        if (isset($res['code']) && (int)$res['code'] === 0) {
            $data = [
                'content' => $res['data']['payUrl'] ?? '',
                'money' => $payAmt,
                'prdOrdNo' => $res['data']['sysOrderNo'] ?? '',
            ];
            return apiReturnSuc($data);
        }

        if ($res === false) {
            return apiReturnFail($logic->getError());
        }

        if ($this->retryTimes > 0) {
            Redis::set('PayErro_AiPay', 1, 'EX', 600);
            TelegramBot::getDefault()->sendProgramNotify('AiPay pay_order failed', json_encode($res));
            return apiReturnFail($logic->getError());
        }

        $this->retryTimes++;
        return $this->pay_order($userId, $payAmt, $userName, $userEmail, $userPhone, $GiftsID, $buyIP, $AdId, $eventType, $pay_method);
    }

    public function notify(Request $request)
    {
        $post = $request->all();
        Util::WriteLog('AiPay', 'pay notify: ' . json_encode($post, JSON_UNESCAPED_UNICODE));

        $service = new AiPay();
        if (!$service->verify($post)) {
            Util::WriteLog('AiPay', 'pay notify verify failed');
            return 'fail';
        }

        $order_sn = $post['mchOrderNo'] ?? '';
        if (empty($order_sn)) {
            Util::WriteLog('AiPay', '缺少订单号');
            return 'fail';
        }

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

        $logic = new AiPayLogic();
        try {
            return $logic->notify($post);
        } catch (\Throwable $exception) {
            Redis::set('PayErro_AiPay', 1, 'EX', 600);
            //TelegramBot::getDefault()->sendProgramNotify('AiPay notify exception', json_encode($post), $exception);
            return '{"success":false,"message":"internal error"}';
        } finally {
            SetNXLock::release($lockKey);
        }
    }

    public function sync_notify(Request $request)
    {
        Util::WriteLog('AiPay', 'sync callback: ' . json_encode($request->all(), JSON_UNESCAPED_UNICODE));
        return 'success';
    }

    public function cash_notify(Request $request)
    {
        $post = $request->all();
        Util::WriteLog('AiPay', 'cash notify: ' . json_encode($post, JSON_UNESCAPED_UNICODE));

        $service = new AiPay('AiPayOut');

        if($post['amount']){
            $post['amount'] = number_format($post['amount'], 2, '.', '');
        }


        if (!$service->verify($post)) {
            Util::WriteLog('AiPay', 'cash notify verify failed');
            return 'fail';
        }

        $logic = new AiPayCashierLogic();
        try {
            return $logic->notify($post);
        } catch (\Throwable $exception) {
            TelegramBot::getDefault()->sendProgramNotify('AiPay cash notify exception', json_encode($post), $exception);
            return '{"success":false,"message":"internal error"}';
        }
    }
}

