<?php

namespace App\Services\Payment;

use Auth;
use PhonePe\PhonePe as PhonePeSDK;
use Illuminate\Support\Facades\Log;
use Exception;

class PhonePePayment implements PaymentInterface
{
        private string $clientId;
        private string $callbackUrl;
        private string $transactionId;
        private string $clientSecret;
        private string $clientVersion;
        private string $payment_mode;
        private string $merchantId;
        private string $pgUrl;

    public function __construct($clientSecret, $clientId, $addtional_data_1,$addtional_data_2, $payment_mode)
    {
        // $this->clientId = 'TEST-CITYSURFONLINE_2508';
        $this->clientId = $clientId;
        $this->callbackUrl = url('/webhook/phonePe');
        $this->transactionId = uniqid();
        $this->clientSecret = $clientSecret;
        $this->clientVersion = $addtional_data_1;
        $this->payment_mode = $payment_mode;
        $this->merchantId = $addtional_data_2;
        $this->pgUrl = ($payment_mode == "UAT") ? "https://api-preprod.phonepe.com/apis/pg-sandbox" : "https://api.phonepe.com/apis/pg";
      
    }

    /**
     * Create payment intent for PhonePe
     *
     * @param $amount
     * @param $customMetaData
     * @return array
     * @throws Exception
     */
     public function createPaymentIntent($amount, $customMetaData) {
        Log::info("PhonePe Payment custome", [
                'amount' => $amount,
                'customMetaData' => $customMetaData,
            ]);
        $amount = $this->minimumAmountValidation('INR', $amount);
        $userMobile = Auth::user()->mobile;
        $metaData = 't' . '-' . $customMetaData['payment_transaction_id'] . '-' . 'p' . '-' . $customMetaData['package_id'];

        if ($customMetaData['platform_type'] == 'web') {
            $transactionId = uniqid();
            $mode = $this->payment_mode;
            if ($mode === 'PROD') {
                $tokenUrl = 'https://api.phonepe.com/apis/identity-manager/v1/oauth/token';
                $orderUrl = 'https://api.phonepe.com/apis/pg/checkout/v2/sdk/order';
                $payUrl = 'https://api.phonepe.com/apis/pg/checkout/v2/pay';
            } else {
                $tokenUrl = 'https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token';
                $orderUrl = 'https://api-preprod.phonepe.com/apis/pg-sandbox/checkout/v2/sdk/order';
                $payUrl = 'https://api-preprod.phonepe.com/apis/pg-sandbox/checkout/v2/pay';
            }
            $tokenCurl = curl_init();

            curl_setopt_array($tokenCurl, array(
                CURLOPT_URL => $tokenUrl,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_POSTFIELDS => http_build_query([
                    'client_id' => $this->clientId,
                    'client_version' => $this->clientVersion,
                    'client_secret' => $this->clientSecret,
                    'grant_type' => 'client_credentials',
                ]),
                CURLOPT_HTTPHEADER => array(
                    'Content-Type: application/x-www-form-urlencoded'
                ),
            ));

            $response = curl_exec($tokenCurl);
            curl_close($tokenCurl);

            // Decode token response
            $tokenResponse = json_decode($response, true);
            $accessToken = $tokenResponse['access_token'] ?? null;

            if (!$accessToken) {
                dd("Failed to retrieve token", $response);
            }
            // Build JSON payload properly
            $paymentData = [
                'merchantOrderId' => $metaData,
                'amount' => (int) round($amount * 100),
                "metadata" => [
                    "package_id" => $customMetaData['package_id'],
                    "payment_transaction_id" => $customMetaData['payment_transaction_id'],
                    "user_id" => Auth::user()->id,
                ],
                'paymentFlow' => [
                    'type' => 'PG_CHECKOUT',
                    'message' => 'Payment message used for collect requests',
                    'merchantUrls' => [
                        'redirectUrl' => route('phonepe.success.web'),
                    ],
                ],
            ];

            $payCUrl = curl_init();

            curl_setopt_array($payCUrl, array(
                CURLOPT_URL => $payUrl,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_POSTFIELDS => json_encode($paymentData),
                CURLOPT_HTTPHEADER => array(
                    'Content-Type: application/json',
                    'Authorization: O-Bearer ' . $accessToken,
                ),
            ));

            $response = curl_exec($payCUrl);
            $final_response = json_decode($response, true);
            if (!empty($final_response)) {

                $redirectURL =  $final_response['redirectUrl'];
                return $this->formatPaymentIntent($transactionId, $amount, 'INR', 'pending', $customMetaData, $redirectURL);
            }
            curl_close($payCUrl);
        } else {
            $redirectUrl = route('phonepe.success');
            $orderId = 'TX' . time(); // unique order ID
            $amount = (int) round($amount * 100); // amount in INR (not multiplied)
            $expireAfter = 1200; // in seconds (20 mins)
            $token = $this->getPhonePeToken();
            $order = $this->createOrder($token, $orderId, $amount);
            $order_data = json_decode($order, true);
            $requestPayload = [
                "orderId" => $order_data['orderId'],
                // "state"  => "PENDING",
                'merchantOrderId' => $metaData,
                "merchantId" => $this->merchantId,
                "expireAT" => $expireAfter,
                "token" => $order_data['token'],
                "paymentMode" => [
                    "type" => "PAY_PAGE"
                ]
            ];

            // Convert to JSON string as required by Flutter SDK
            $requestString = json_encode($requestPayload);

            if ($this->payment_mode == "UAT") {
                $payment_mode = "SANDBOX";
            } else {
                $payment_mode = "PRODUCTION";
            }

            return [
                "environment" => $payment_mode, // or "PRODUCTION"
                "merchantId" => $this->merchantId,
                "flowId" => $orderId,
                "enableLogging" => true, // false in production
                "request" => $requestPayload,
                "appSchema" => "eclassify", // for iOS deep link return
                "token" => $token,
            ];
        }
        throw new Exception("Error initiating payment: " . $redirectURL);
    }

    /**
     * Create and format payment intent for PhonePe
     *
     * @param $amount
     * @param $customMetaData
     * @return array
     * @throws Exception
     */
    public function createAndFormatPaymentIntent($amount, $customMetaData): array
    {
        $paymentIntent = $this->createPaymentIntent($amount, $customMetaData);
        $metaData = 't' . '-' . $customMetaData['payment_transaction_id'] . '-' . 'p' . '-' . $customMetaData['package_id'];
        return $this->formatPaymentIntent(
            id: $metaData,
            amount: $amount,
            currency: 'INR',
            status: "PENDING",
            metadata: $customMetaData,
            paymentIntent: $paymentIntent
        );
    }

    /**
     * Retrieve payment intent (check payment status)
     *
     * @param $transactionId
     * @return array
     * @throws Exception
     */
    public function retrievePaymentIntent($transactionId): array
    {
        $statusUrl = 'https://api.phonepe.com/v3/transaction/' . $transactionId . '/status';
        $signature = $this->generateSignature(''); // Adjust if needed based on PhonePe requirements

        $response = $this->sendRequest($statusUrl, '', $signature);

        if ($response['success']) {
            return $this->formatPaymentIntent($transactionId, $response['amount'], 'INR', $response['status'], [], $response);
        }

        throw new Exception("Error fetching payment status: " . $response['message']);
    }

    /**
     * Format payment intent response
     *
     * @param $id
     * @param $amount
     * @param $currency
     * @param $status
     * @param $metadata
     * @param $paymentIntent
     * @return array
     */
    public function formatPaymentIntent($id, $amount, $currency, $status, $metadata, $paymentIntent): array
    {
        return [
            'id' => $id,
            'amount' => $amount,
            'currency' => $currency,
            'metadata' => $metadata,
            'status' => match ($status) {
                "SUCCESS" => "succeeded",
                "PENDING" => "pending",
                "FAILED" => "failed",
                default => "unknown"
            },
            'payment_gateway_response' => $paymentIntent
        ];
    }

    /**
     * Minimum amount validation
     *
     * @param $currency
     * @param $amount
     * @return float|int
     */
    public function minimumAmountValidation($currency, $amount)
    {
        $minimumAmount = match ($currency) {
            'INR' => 1.00, // 1 Rupee
            default => 0.50
        };

        return ($amount >= $minimumAmount) ? $amount : $minimumAmount;
    }

    /**
     * Generate HMAC signature for PhonePe
     *
     * @param $encodedRequestBody
     * @return string
     */
    private function generateSignature($requestBody): string
    {
        // Concatenate raw JSON payload, endpoint, and salt key
        $stringToHash = $requestBody . '/pg/v1/pay' . $this->saltKey;

        // Hash the string using SHA256
        $hash = hash('sha256', $stringToHash);

        // Append salt index (Assumed to be 1 in this example)
        return $hash . '###' . 1;
    }

    /**
     * Send cURL request to PhonePe API
     *
     * @param $url
     * @param $requestBody
     * @param $signature
     * @return array
     */
    // private function sendRequest($url, $requestBody, $signature): array
    // {
    //     // dd($requestBody);
    //     $ch = curl_init($url);
    //     curl_setopt($ch, CURLOPT_POST, 1);
    //     curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
    //     curl_setopt($ch, CURLOPT_HTTPHEADER, [
    //         'Content-Type: application/json',
    //         'X-VERIFY: ' . $signature,
    //     ]);
    //     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    //     $response = curl_exec($ch);
    //     curl_close($ch);
    //     return json_decode($response, true);
    // }
    
     public function getPhonePeToken() {
        $clientId =  $this->clientId;
        $clientSecret = $this->clientSecret;
        $clientVersion = $this->clientVersion;

        $postData = http_build_query([
            'client_id' => $clientId,
            'client_version' => $clientVersion,
            'client_secret' => $clientSecret,
            'grant_type' => 'client_credentials',
        ]);

        if ($this->payment_mode == "UAT") {
            $url = 'https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token';
        } else {
            $url = 'https://api.phonepe.com/apis/identity-manager/v1/oauth/token';
        }
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded',
        ]);

        $response = curl_exec($ch);

        if (curl_errno($ch)) {
            throw new \Exception('Curl error: ' . curl_error($ch));
        }

        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $responseData = json_decode($response, true);

        if ($httpCode === 200 && isset($responseData['access_token'])) {
            return $responseData['access_token'];
        }

        throw new \Exception('Failed to fetch PhonePe token. Response: ' . $response);
    }

    public function createOrder($token, $merchantOrderId, $amount) {
        $url = $this->pgUrl . '/checkout/v2/sdk/order';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            "merchantOrderId" => $merchantOrderId,
            "amount" => $amount,
            "paymentFlow" => [
                "type" => "PG_CHECKOUT"
            ]
        ]));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: O-Bearer ' . $token,
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response = curl_exec($ch);
        curl_close($ch);

        return $response;
    }
}
