<?php

namespace App\Http\logic\api;

use App\dao\Pay\AccountPayInfo;
use App\dao\Pay\PayController;
use App\Http\helper\CreateOrder;
use App\Http\helper\NumConfig;
use App\Jobs\Order;
use App\Notification\TelegramBot;
use App\Services\CreateLog;
use App\Services\OrderServices;
use App\Services\PayConfig;
use App\Services\PayPlus;
use App\Util;
use Illuminate\Support\Facades\DB;

class PayPlusLogic extends BaseApiLogic
{
    protected $service;

    public function __construct(PayPlus $service = null)
    {
        $this->service = $service ?: new PayPlus();
    }

    public function pay_order(
        $userId,
        $payAmount,
        $userPhone,
        $userEmail,
        $userName,
        $GiftsID,
        $buyIP,
        $AdId,
        $eventType,
        $payMethod = ''
    ) {
        $dao = new AccountPayInfo();
        list($userPhone, $userName, $userEmail) = $dao->payInfo($userId);

        $payVerify = new PayController();
        $payAmount = $payVerify->verify($userId, $GiftsID, $payAmount);
        if ($payAmount === false || $payAmount < 0) {
            $this->error = $payVerify->getError() ?: 'Payment error_4';
            return false;
        }

        $orderSn = CreateOrder::order_sn($userId);
        $amount = (int) round($payAmount * NumConfig::NUM_VALUE);

        $logic = new OrderLogic();
        if (
            !$logic->orderCreate(
                $orderSn,
                $amount,
                'PayPlus',
                $userId,
                $payMethod,
                $GiftsID,
                $AdId,
                $eventType
            )
        ) {
            $this->error = $logic->getError();
            return false;
        }

        $payload = $this->buildPaymentPayload([
            'order_sn' => $orderSn,
            'amount' => $payAmount,
            'user_id' => $userId,
            'user_email' => $userEmail,
            'user_phone' => $userPhone,
            'user_name' => $userName,
            'buy_ip' => $buyIP,
            'pay_method' => $payMethod,
        ]);

        CreateLog::pay_request(
            $userPhone,
            json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
            $orderSn,
            $userEmail,
            $userId,
            $userName
        );

        Util::WriteLog('PayPlus', 'PayPlus payment request: ' . json_encode($payload));

        try {
            $result = $this->service->postPayin($payload);
            Util::WriteLog('PayPlus', 'PayPlus payment response: ' . json_encode($result));
            if ($result['code'] !== 200) {
                TelegramBot::getDefault()->sendProgramNotify(
                    'PayPlus payment failed',
                    'Response: ' . json_encode($result),
                    null
                );
            }
            return $result;
            
        } catch (\Exception $exception) {
            Util::WriteLog('PayPlus_error', $exception->getMessage());
            $this->error = 'Payment processing error';
            return false;
        }
    }

    public function buildPaymentPayload(array $input)
    {
        $config = $this->service->getConfig();
        $payMethod = (int) ($input['pay_method'] ?: 1);
        $methodMap = $config['payment_methods'] ?? [
            1 => 8,
            2 => 2,
            4 => 1,
            8 => 5,
        ];

        $nameParts = preg_split('/\s+/', trim((string) ($input['user_name'] ?? '')), 2);

        return [
            'order_type' => 'RECHARGE',
            'platform_order_id' => (string) $input['order_sn'],
            'currency' => strtoupper($config['currency'] ?? 'USD'),
            'amount' => number_format((float) $input['amount'], 2, '.', ''),
            'payment_method' => $methodMap[$payMethod] ?? 8,
            'return_url' => $config['return'] ?? '',
            'cancel_url' => $config['cancel'] ?? ($config['return'] ?? ''),
            'connection_info' => [
                'ip' => $input['buy_ip'] ?: '0.0.0.0',
                'country' => $config['country'] ?? 'US',
                'state' => $config['state'] ?? 'NA',
                'zip_code' => $config['zip'] ?? '00000',
                'media_source' => $config['media_source'] ?? 'organic',
                'language' => $config['language'] ?? 'en-US',
            ],
            'account_info' => [
                'merchant_user_id' => (string) $input['user_id'],
                'create_time' => time()*1000,
                'role' => 'PRIVATE',
                'email' => $this->emailOrDefault($input['user_email'] ?? '', $input['user_id']),
                'phone' => preg_replace('/\D+/', '', (string) ($input['user_phone'] ?? '')) ?: '0000000000',
                'area_code' => $config['area_code'] ?? '1',
                'first_name' => 'user',
                'last_name' => 'user',
                'vip_level' => 0,
            ],
        ];
    }

    public function notify(array $post)
    {
        $orderSn = $post['data']['platform_order_id'] ?? '';
        if ($orderSn === '') {
            return 'success';
        }

        $order = DB::connection('write')
            ->table('agent.dbo.order')
            ->where('order_sn', $orderSn)
            ->first();
        if (!$order || !empty($order->pay_at) || !empty($order->finished_at)) {
            return 'success';
        }

        $data = $post['data'] ?? [];
        $body = [
            'payment_sn' => $data['order_id'] ?? '',
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        if ($this->isSuccessfulPayment($post)) {
            if (!$this->confirmSuccessfulPayment($post)) {
                Util::WriteLog('PayPlus', 'PayPlus order query not successful: ' . json_encode($post));
                return 'success';
            }

            $AdId = $order->AdId ?: '';
            $eventType = $order->eventType ?: '';

            $payAmount = round((float) ($data['amount'] ?? 0), 2);
            $body['pay_status'] = 1;
            $body['pay_at'] = date('Y-m-d H:i:s');
            $body['finished_at'] = date('Y-m-d H:i:s');
            $body['amount'] = (int) round($payAmount * NumConfig::NUM_VALUE);

            $config = (new PayConfig())->getConfig('PayPlus');
            // 根据支付方式计算代收手续费: 费率% * 金额 + 固定$
            // pay_rate 格式: [1=>[10,0.3], 2=>[13,0.3], 4=>[11,0.3], 8=>[12,0.3]]
            $payRates = $config['pay_rate'] ?? null;
            if (is_array($payRates)) {
                $payMethod = $order->order_title ?? 1;
                $payRate = $payRates[$payMethod] ?? ($payRates[1] ?? [10, 0.3]);
                $feePercent = $payRate[0] ?? 10;
                $feeFixed = $payRate[1] ?? 0.3;
                $body['payment_fee'] = intval(($body['amount'] * $feePercent) / 100)
                    + (int)($feeFixed * NumConfig::NUM_VALUE);
            }

            $service = new OrderServices();
            list($give, $favorablePrice, $recharge, $czReason, $cjReason) = $service->getPayInfo(
                $order->GiftsID ?: '',
                $order->user_id ?: '',
                $payAmount
            );
            list($score) = $service->addRecord(
                $order->user_id,
                $payAmount,
                $favorablePrice,
                $orderSn,
                $order->GiftsID,
                $recharge,
                $czReason,
                $give,
                $cjReason,
                $order->AdId ?: '',
                $order->eventType ?: '',
                $body['payment_fee'] ?? 0
            );

            Order::dispatch([
                $order->user_id,
                $payAmount,
                $score,
                $favorablePrice,
                $order->GiftsID,
                $orderSn,
            ]);
        } else {
            return 'success';
        }

        DB::connection('write')
            ->table('agent.dbo.order')
            ->where('order_sn', $orderSn)
            ->update($body);

        return 'success';
    }

    public function isSuccessfulPayment(array $post)
    {
        return ($post['event'] ?? '') === 'PAYMENT.CAPTURE.COMPLETED'
            && ($post['event_detail_name'] ?? '') === 'payment_captured'
            && (int) ($post['data']['order_status'] ?? 0) === 3;
    }

    public function confirmSuccessfulPayment(array $post)
    {
        $data = $post['data'] ?? [];
        $platformOrderId = $data['platform_order_id'] ?? '';
        if ($platformOrderId === '') {
            return false;
        }

        try {
            $result = $this->service->queryPayinOrder($platformOrderId, $data['order_id'] ?? '');
        } catch (\Exception $exception) {
            Util::WriteLog('PayPlus_error', 'PayPlus query order failed: ' . $exception->getMessage());
            return false;
        }

        return $this->isSuccessfulPaymentQueryResult($result);
    }

    public function isSuccessfulPaymentQueryResult(array $result)
    {
        $data = $result['decryptedComponentDelta'] ?? ($result['data'] ?? $result);

        return (int) ($data['order_status'] ?? 0) === 3;
    }

    public function isFailedPayment(array $post)
    {
        $event = $post['event'] ?? '';
        $detail = $post['event_detail_name'] ?? '';
        $status = (int) ($post['data']['order_status'] ?? 0);

        return ($event === 'PAYMENT.CAPTURE.COMPLETED' && in_array($status, [4, 10, 11], true))
            || $event === 'PAYMENT.ORDER.TIMEOUT'
            || in_array($detail, ['payment_declined', 'payment_timeout'], true);
    }

    protected function resolvePaymentUrl(array $result)
    {
        $data = $result['data'] ?? $result;
        foreach (['cashierUrl', 'cashier_url', 'payment_url', 'paymentUrl', 'redirect_url', 'url'] as $key) {
            if (!empty($data[$key])) {
                return $data[$key];
            }
        }

        return '';
    }

    protected function emailOrDefault($email, $userId)
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'unknown' . $userId . '@example.com';
    }

    protected function stringOrDefault($value, $default)
    {
        $value = trim((string) $value);

        return $value === '' ? $default : $value;
    }
}
