<?php

namespace Yajny\EventsYj\Library\CashU;

use Illuminate\Support\Facades\Log;
use Yajny\EventsYj\Events\PayoutUpdated;
use Yajny\Member\Entities\Payouts\PayoutStatusUtil;
use Yajny\Member\Models\Member;
use Yajny\Member\Models\UserPayoutMethods;
use Yajny\Member\Models\UserPayouts;

class CashUPayout
{
    private $CashUBaseURL;

    protected $payout = null;

    protected $method = null;

    protected $payoutMethod = null;

    public function __construct(UserPayouts $payout = null, UserPayoutMethods $method = null)
    {
        $this->CashUBaseURL = config('services.cashu.base_endpoint');

        if ($payout) {
            $this->payout = $payout;
            $this->method = $method;
        }
    }

    public function process()
    {
        $headers = [
            'Content-Type: text/xml',
        ];

        $ch = curl_init();

        $options = [
            CURLOPT_URL => "{$this->CashUBaseURL}/cashUDirect/cashUDirect.php",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS => $this->getPayoutBody('TOPUP_ACCOUNT_REQUEST'),
            CURLOPT_HTTPHEADER => $headers
        ];

        curl_setopt_array($ch, $options);

        $response = curl_exec($ch);

        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200;

        curl_close($ch);

        $this->handleCashUDisburseResult($status, $response);

        return $status;
    }

    private function handleCashUDisburseResult($status, $response)
    {
        $responseXML = simplexml_load_string(str_ireplace(['soap-env:', 'soapenv:', 'cas:', 'ns1:'], '', $response));
        $this->payout->api_response = json_encode($responseXML);
        if ($status) {
            $response = json_decode(json_encode($responseXML));
            if (isset($response->Body->cashUDirectResponse->return->TOPUP_ACCOUNT_REQUEST->refID)) {
                $this->payout->payment_ref_num = $response->Body->cashUDirectResponse->return->TOPUP_ACCOUNT_REQUEST->refID;
                $this->payout->status = PayoutStatusUtil::COMPLETED;
                $this->payout->paid_at = date('Y-m-d');
            } else {
                Log::error('Unexpected response', ['response' => $response, 'payout' => $this->payout->toArray(), 'status' => $status]);
                $this->payout->status = PayoutStatusUtil::FAILED;
            }
        } else {
            Log::error('Unexpected response', ['response' => $response, 'payout' => $this->payout->toArray(), 'status' => $status]);
            $this->payout->status = PayoutStatusUtil::FAILED;
        }
        $this->payout->save();
        if ($this->payout->status != PayoutStatusUtil::FAILED)
            event(new PayoutUpdated(Member::find($this->payout->user_id), $this->payout));
    }

    private function getPayoutBody($msgType)
    {
        $vendorID = config('services.cashu.vendor_id');
        $key = config('services.cashu.key');
        $placeholders = [
            '{{msgType}}' => $msgType,
            '{{msgDate}}' => date('Y-m-d\TH:m:i'),
            '{{vendorID}}' => $vendorID,
            '{{userID}}' => $this->payout->account,
            '{{amount}}' => $this->payout->final_amount,
            '{{currency}}' => 'USD',
            '{{refID}}' => time() . "-{$this->payout->id}",
            '{{reconDate}}' => date('Y-m-d\TH:m:i'),
            '{{isRetry}}' => 'false',
            '{{sigType}}' => 'MD5',
            '{{sigPath}}' => "/message/{$msgType}",
        ];
        $xmlBody = str_replace(array_keys($placeholders), array_values($placeholders), file_get_contents(__DIR__ . '/cashu_body.xml'));
        $xmlArray = simplexml_load_string(str_replace(['soapenv:', 'cas:'], '', $xmlBody));
        $requestKeys = json_decode(json_encode($xmlArray), true)['Body']['cashUDirect']['message'][$msgType] ?? [];
        unset($requestKeys['comment']);
        ksort($requestKeys);
        $md5String = implode('', $requestKeys) . $key;
        return str_replace('{{MD5}}', md5($md5String), $xmlBody);
    }
}
