<?php

namespace App\Http\logic\api;

use App\dao\Estatisticas\RechargeWithDraw;
use App\Http\helper\NumConfig;
use App\Inter\CashierInterFace;
use App\Models\PrivateMail;
use App\Models\RecordUserDataStatistics;
use App\Services\PayPlus;
use App\Services\StoredProcedure;
use App\Util;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class PayPlusCashierLogic implements CashierInterFace
{
    const AGENT = 109;

    protected $service;

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

    public function payment(
        $RecordID,
        $amount,
        $accountName,
        $phone,
        $email,
        $OrderId,
        $PixNum,
        $PixType,
        $IFSCNumber,
        $BranchBank,
        $BankNO
    ) {
        $query = DB::connection('write')
            ->table('QPAccountsDB.dbo.OrderWithDraw')
            ->where('RecordID', $RecordID)
            ->first();
        if (!$query) {
            return 'fail';
        }

        $result = $this->createBeneficiaryAndPayout([
            'user_id' => $query->UserID,
            'amount' => round($amount / NumConfig::NUM_VALUE, 2),
            'currency' => $this->service->getConfig()['currency'] ?? 'USD',
            'order_id' => $OrderId,
            'pix_type' => $PixType,
            'cashapp_account' => $PixNum,
            'email' => $email,
            'phone' => $phone,
            'name' => $accountName,
        ]);

        if ($result && isset($result['code']) && (int) $result['code'] === 200) {
            return $result;
        }

        return 'fail';
    }

    public function createBeneficiaryAndPayout(array $input)
    {
        $beneficiary = $this->resolveBeneficiary($input);
        if (!$beneficiary) {
            return false;
        }

        $payload = [
            'amount' => (float) $input['amount'],
            'currency' => strtoupper($input['currency'] ?? ($this->service->getConfig()['currency'] ?? 'USD')),
            'reference_id' => (string) $input['order_id'],
            'beneficiary_id' => (int) $beneficiary['beneficiary_id'],
        ];

        if ((int) ($input['pix_type'] ?? 1) === 2) {
            $payload['paypal_email'] = $input['email'] ?: $beneficiary['email'];
            return $this->service->postPayout('/rest/v2/payouts/paypal', $payload);
        }

        $cashAppAccount = (string) ($input['cashapp_account'] ?? '');
        if ($cashAppAccount !== '' && strpos($cashAppAccount, '$') !== 0) {
            $cashAppAccount = '$' . $cashAppAccount;
        }

        $payload['cashapp_account'] = $cashAppAccount ?: '$unknown';

        return $this->service->postPayout('/rest/v2/payouts/cashApp', $payload);
    }

    public function resolveBeneficiary(array $input)
    {
        $payload = $this->service->buildBeneficiaryPayload($input);
        $created = $this->service->postPayout('/rest/v2/beneficiaries/create', $payload);

        if ((int) ($created['code'] ?? 0) === 200 && !empty($created['data']['beneficiary_id'])) {
            return $created['data'];
        }

        if ((int) ($created['code'] ?? 0) !== 4002001) {
            Util::WriteLog('PayPlus_error', 'beneficiary create failed: ' . json_encode($created));
            return false;
        }

        $query = $this->service->postPayout('/rest/v2/beneficiaries/query', [
            'payee_id' => $payload['payee_id'],
        ]);

        if ((int) ($query['code'] ?? 0) === 200 && !empty($query['data']['beneficiary_id'])) {
            return $query['data'];
        }

        Util::WriteLog('PayPlus_error', 'beneficiary query failed: ' . json_encode($query));

        return false;
    }

    public function notify($post)
    {
        if (!is_array($post)) {
            $post = json_decode($post, true) ?: [];
        }

        $orderId = $post['reference_id'] ?? '';
        if ($orderId === '') {
            return 'success';
        }

        $query = DB::connection('write')
            ->table('QPAccountsDB.dbo.OrderWithDraw')
            ->where('OrderId', $orderId)
            ->first();
        if (!$query || ($query->State != 5 && $query->State != 7)) {
            return 'success';
        }

        $orderStatus = $this->resolvePayoutStatus($post['status'] ?? '');
        if (!$orderStatus) {
            return 'success';
        }

        $agent = DB::connection('write')->table('agent.dbo.admin_configs')
            ->where('config_value', self::AGENT)
            ->where('type', 'cash')
            ->select('id')
            ->first();
        $agentId = $agent->id ?? '';

        $now = now();
        $userId = $query->UserID;
        $takeMoney = $query->WithDraw + $query->ServiceFee;
        $withdrawData = [
            'agent' => $agentId,
            'finishDate' => $now,
            'remark' => json_encode($post, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
        ];

        if ($orderStatus === 1) {
            $withdrawData['State'] = 2;
            $this->handleSuccess($query, $takeMoney);
        } else {
            $withdrawData['State'] = 6;
            PrivateMail::failMail($userId, $orderId, $takeMoney, $post['msg'] ?? 'REJECTED', '30000,' . $takeMoney);
        }

        DB::connection('write')->table('QPAccountsDB.dbo.AccountsRecord')->updateOrInsert(
            ['RecordID' => $query->RecordID, 'type' => 1],
            [
                'before_state' => $query->State,
                'after_state' => $withdrawData['State'],
                'RecordID' => $query->RecordID,
                'update_at' => date('Y-m-d H:i:s'),
            ]
        );
        DB::connection('write')
            ->table('QPAccountsDB.dbo.OrderWithDraw')
            ->where('OrderId', $query->OrderId)
            ->update($withdrawData);

        return 'success';
    }

    public function resolvePayoutStatus($status)
    {
        switch (strtoupper((string) $status)) {
            case 'PAID':
                return 1;
            case 'REJECTED':
            case 'REFUNDED':
                return 2;
            default:
                return 0;
        }
    }

    protected function handleSuccess($query, $takeMoney)
    {
        $userId = $query->UserID;
        $first = DB::connection('write')
            ->table('QPAccountsDB.dbo.UserTabData')
            ->where('UserID', $userId)
            ->first();
        if ($first) {
            DB::connection('write')
                ->table('QPAccountsDB.dbo.UserTabData')
                ->where('UserID', $userId)
                ->increment('TakeMoney', $takeMoney);
        } else {
            DB::connection('write')
                ->table('QPAccountsDB.dbo.UserTabData')
                ->insert(['TakeMoney' => $takeMoney, 'UserID' => $userId]);
            PrivateMail::praiseSendMail($userId);
        }

        try {
            StoredProcedure::addPlatformData($userId, 4, $takeMoney);
        } catch (\Exception $exception) {
            Util::WriteLog('StoredProcedure', $exception);
        }

        RecordUserDataStatistics::updateOrAdd($userId, $takeMoney, 0, $query->ServiceFee);
        (new RechargeWithDraw())->withDraw($userId, $takeMoney, 0, $query->ServiceFee);
        Redis::connection()->incr('draw_' . date('Ymd') . $userId);
        PrivateMail::successMail($userId, $query->OrderId, $takeMoney);
        StoredProcedure::user_label($userId, 2, $takeMoney);
    }
}
