<?php
/**
 * Copyright © Simplyin. All rights reserved.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Service\Api;

/**
 * Order lifecycle and merchant sync SimplyIN API operations.
 */
class OrderApiClient
{
    /**
     * @var ApiTransport
     */
    private ApiTransport $transport;

    /**
     * Constructor
     *
     * @param ApiTransport $transport
     */
    public function __construct(ApiTransport $transport)
    {
        $this->transport = $transport;
    }

    /**
     * Create order (for authenticated users)
     *
     * @param array $orderData
     * @param string $authToken
     * @param string $customerEmail
     * @return array
     */
    public function createOrder($orderData, $authToken, $customerEmail = '')
    {
        $url = $this->transport->getApiBaseUrl() . '/checkout/createOrder';

        if ($authToken) {
            $url .= '?api_token=' . urlencode($authToken);
        }

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $apiKey = $this->transport->getApiKey();
            $orderData['merchantApiKey'] = $apiKey;

            if (isset($orderData['newOrderData'])) {
                if (isset($orderData['newOrderData']['shopName'])) {
                    $orderData['shopName'] = $orderData['newOrderData']['shopName'];
                } else {
                    $orderData['shopName'] = $this->transport->getShopName();
                }

                if (isset($orderData['newOrderData']['shopUserEmail'])) {
                    $orderData['shopUserEmail'] = $orderData['newOrderData']['shopUserEmail'];
                }

                if (isset($orderData['newOrderData']['blikCode'])) {
                    unset($orderData['newOrderData']['blikCode']);
                }
            }

            $this->transport->getCurl()->post($url, json_encode($orderData));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to create order'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Create order without account
     *
     * @param array $orderData
     * @param string $authToken
     * @return array
     */
    public function createOrderWithoutAccount($orderData, $authToken)
    {
        $url = $this->transport->getApiBaseUrl() . '/checkout/createOrderWithoutAccount';

        if ($authToken) {
            $url .= '?api_token=' . urlencode($authToken);
        }

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $payload = [
                'newOrderData' => $orderData['newOrderData']
            ];

            $this->transport->getCurl()->post($url, json_encode($payload));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to create order without account'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Create order and account
     *
     * @param array $orderData
     * @param array $accountData
     * @return array
     */
    public function createOrderAndAccount($orderData, $accountData)
    {
        $url = $this->transport->getApiBaseUrl() . '/checkout/createOrderAndAccount';

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $apiKey = $this->transport->getApiKey();

            $payload = [
                'merchantApiKey' => $apiKey,
                'shopName' => $this->transport->getShopName(),
                'shopUserEmail' => $accountData['email'],
                'newAccountData' => [
                    'email' => $accountData['email'],
                    'phoneNumber' => $accountData['phone'],
                    'name' => $accountData['firstName'],
                    'surname' => $accountData['lastName'],
                    'language' => 'EN',
                    'authStrategy' => 'sms'
                ],
                'newOrderData' => $orderData['newOrderData']
            ];

            $this->transport->getCurl()->post($url, json_encode($payload));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to create order and account'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Update order status in SimplyIN
     *
     * @param string $orderId
     * @param string $status
     * @param string $authToken
     * @return array
     */
    public function updateOrderStatus($orderId, $status, $authToken)
    {
        $url = $this->transport->getApiBaseUrl() . '/orders/updateStatus';

        if ($authToken) {
            $url .= '?api_token=' . urlencode($authToken);
        }

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $this->transport->getCurl()->post($url, json_encode([
                'orderId' => $orderId,
                'status' => $status
            ]));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to update order status'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Get controller URL
     *
     * @param string $path
     * @return string
     */
    public function getControllerURL(string $path): string
    {
        return $this->transport->getUrlBuilder()->getUrl($path);
    }

    /**
     * Get plugin sync info from API
     *
     * Called on first module install to sync configuration values
     *
     * @return array
     */
    public function getPluginSyncInfo()
    {
        $url = $this->transport->getApiBaseUrl() . '/plugin-sync/info';

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $this->transport->getCurl()->get($url);
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to get plugin sync info'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Verify if hashed emails exist in SimplyIN
     *
     * Used for batch checking customer existence before syncing orders
     *
     * @param array $hashedEmails Array of SHA-256 hashed email addresses
     * @return array
     */
    public function verifyHashedEmailsExist(array $hashedEmails)
    {
        $url = $this->transport->getApiBaseUrl() . '/users/verifyHashedEmailsExist';

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $payload = ['data' => $hashedEmails];
            $this->transport->getCurl()->post($url, json_encode($payload));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to verify hashed emails'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Save encrypted order status change to SimplyIN
     *
     * Used for updating order status and tracking info securely
     *
     * @param string $encryptedContent Encrypted order status data
     * @param string $hashedEmail SHA-256 hashed email with format "--{email}--"
     * @param string|null $plainPayload Plain payload for logging (optional)
     * @param string|null $email Original email for decrypting response (optional)
     * @return array
     */
    public function saveEncryptedOrderStatusChange(string $encryptedContent, string $hashedEmail, ?string $plainPayload = null, ?string $email = null)
    {
        $url = $this->transport->getApiBaseUrl() . '/encryption/saveEncryptedOrderStatusChange';

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin()
        ]);

        try {
            $payload = [
                'encryptedOrderStatusChangeContent' => $encryptedContent,
                'hashedEmail' => $hashedEmail
            ];

            $this->transport->getCurl()->post($url, json_encode($payload));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            // Try to decrypt the response if email is provided
            if ($email !== null && !empty($response)) {
                $secretKey = $this->transport->getSimplyinEncryption()->getSecretKey($email);
                $decryptedResponse = $this->transport->getSimplyinEncryption()->decrypt($response, $secretKey);

                if ($decryptedResponse !== false) {
                    // Try to parse decrypted response as JSON
                    $decodedDecrypted = json_decode($decryptedResponse, true);

                    $this->transport->getLogger()->info('SimplyIN saveEncryptedOrderStatusChange decodedResponse', ['decodedResponse' => $decodedDecrypted]);
                } else {
                    // Try JSON decode as fallback
                    $decodedResponse = json_decode($response, true);

                    $this->transport->getLogger()->info('SimplyIN saveEncryptedOrderStatusChange decodedResponse', ['decodedResponse' => $decodedResponse]);
                }
            } else {
                // No email provided, try JSON decode
                $decodedResponse = json_decode($response, true);
                $this->transport->getLogger()->info('SimplyIN saveEncryptedOrderStatusChange decodedResponse', ['decodedResponse' => $decodedResponse]);
            }

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to save encrypted order status change'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
}
