<?php

namespace App\Modules\Payment\BluepayRemote;

use App\Core\Payment\AbstractPayment;

class BluepayRemote extends AbstractPayment
{
    protected $apiUrl;

    public function __construct(array $config = [])
    {
        parent::__construct($config);
        // BluePay 2.0 uses the same endpoint for both test and live
        // Test mode is controlled by the MODE parameter in requests
        $this->apiUrl = 'https://secure.bluepay.com/interfaces/bp20post';
    }

    /**
     * Validate parameters and perform pre-fraud check before payment
     */
    public function attemptPayment(array $params)
    {
        // makePayment ile hizalı: expiry ay/yıl ayrık okunur, cvv opsiyonel değil.
        $requiredParams = ['amount', 'currency', 'order_id', 'card_number', 'cvv'];

        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bluepayremote_missing_param', ['param' => $param]),
                ];
            }
        }

        // Son kullanım tarihi: ay+yıl (makePayment ile aynı alanlar) veya birleşik card_expiry.
        $hasExpiry = (! empty($params['expiry_month']) || ! empty($params['card_expiry_month']))
            && (! empty($params['expiry_year']) || ! empty($params['card_expiry_year']));
        if (! $hasExpiry && empty($params['card_expiry'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bluepayremote_missing_param', ['param' => 'expiry']),
            ];
        }

        // Fraud check
        $fraudCheck = $this->performPreFraudCheck($params);
        if ($fraudCheck['status'] === 'error') {
            return $fraudCheck;
        }

        // Senkron S2S gateway — ara-durum 'pending' (standart zarf; 'ready' sözleşme-dışı).
        return [
            'status' => 'pending',
            'message' => __('admin/modules.bluepayremote_ready'),
            'data' => [
                'payment_method' => 'bluepayremote',
                'amount' => $params['amount'],
                'currency' => $params['currency'],
                'order_id' => $params['order_id'],
            ],
        ];
    }

    /**
     * Process payment via BluePay 2.0 POST interface (SALE transaction)
     */
    public function makePayment(array $params)
    {
        $cardNumber = str_replace([' ', '-'], '', $params['card_number']);
        $expiryMonth = str_pad($params['expiry_month'] ?? $params['card_expiry_month'] ?? '', 2, '0', STR_PAD_LEFT);
        $expiryYear = substr($params['expiry_year'] ?? $params['card_expiry_year'] ?? '', -2);
        $ccExpires = $expiryMonth . $expiryYear;

        $firstName = $params['billing_first_name'] ?? $params['billing_address']['first_name'] ?? '';
        $lastName = $params['billing_last_name'] ?? $params['billing_address']['last_name'] ?? '';
        $email = $params['customer_email'] ?? $params['email'] ?? '';
        $amount = number_format((float) $params['amount'], 2, '.', '');

        // bp20post kart alan adları: PAYMENT_ACCOUNT / CARD_CVV2 / CARD_EXPIRE
        // (WHMCS bluepayremote.php:53-55, HostBill class.bluepay.php:53-55).
        $postData = $this->buildPostData([
            'TRANS_TYPE' => 'SALE',
            'AMOUNT' => $amount,
            'PAYMENT_ACCOUNT' => $cardNumber,
            'CARD_EXPIRE' => $ccExpires,
            'CARD_CVV2' => $params['cvv'] ?? '',
            'INVOICE_ID' => (string) ($params['order_id'] ?? ''),
            'NAME1' => $firstName,
            'NAME2' => $lastName,
            'EMAIL' => $email,
            'PAYMENT_TYPE' => 'CREDIT',
        ]);

        // Generate tamper proof seal for this transaction
        $postData['TAMPER_PROOF_SEAL'] = $this->generateTamperProofSeal(
            'SALE',
            $amount,
            '',
            $firstName,
            $cardNumber
        );

        $response = $this->callBluepayApi($postData);

        if ($response === null) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bluepayremote_invalid_response'),
                'data' => [],
            ];
        }

        // bp20post başarı sinyali STATUS=1 (WHMCS bluepayremote.php:48, HostBill:95).
        // Result=APPROVED bp10emu (hosted) formatıdır — bu arayüzde HİÇ gelmez.
        $status = (string) ($response['STATUS'] ?? '');
        $transId = $response['TRANS_ID'] ?? $response['trans_id'] ?? '';
        $message = $response['MESSAGE'] ?? $response['Message'] ?? '';

        if ($status === '1') {
            return [
                'status' => 'success',
                'message' => __('admin/modules.bluepayremote_payment_success'),
                'transaction_id' => $transId,
                'data' => [
                    'trans_id' => $transId,
                    'auth_code' => $response['AUTH_CODE'] ?? '',
                    'avs_result' => $response['AVS'] ?? '',
                    'cvv_result' => $response['CVV2'] ?? '',
                    'message' => $message,
                    'payment_account' => $response['PAYMENT_ACCOUNT'] ?? '',
                    'card_type' => $response['CARD_TYPE'] ?? '',
                ],
            ];
        }

        // STATUS != 1 → başarısız/red.
        return [
            'status' => 'failed',
            'message' => ! empty($message)
                ? __('admin/modules.bluepayremote_payment_declined_detail', ['message' => $message])
                : __('admin/modules.bluepayremote_payment_declined'),
            'data' => [
                'trans_id' => $transId,
                'message' => $message,
                'status' => $status,
            ],
        ];
    }

    /**
     * bp20post senkron server-to-server bir arayüzdür: makePayment yanıtı anlık
     * döner; ayrı bir asenkron webhook/return AKIŞI YOKTUR (WHMCS/HostBill
     * referanslarında callback handler yok). İmzasız gelen HTTP parametrelerine
     * göre 'success' dönmek fail-open success-forgery açığı olurdu — bu yüzden
     * callback FAIL-CLOSED olarak desteklenmiyor işaretlenir (sahte-success yok).
     */
    public function handlePaymentCallback(array $params)
    {
        return [
            'status' => 'error',
            'message' => __('modules.payment_function_not_supported'),
        ];
    }

    /**
     * Process refund via BluePay 2.0 (REFUND transaction)
     */
    public function refundPayment(array $params)
    {
        if (empty($params['transaction_id'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bluepayremote_refund_missing_transaction'),
            ];
        }

        $amount = number_format((float) ($params['amount'] ?? 0), 2, '.', '');

        $postData = $this->buildPostData([
            'TRANS_TYPE' => 'REFUND',
            'MASTER_ID' => $params['transaction_id'],
            'AMOUNT' => $amount,
            'PAYMENT_TYPE' => 'CREDIT',
        ]);

        // Generate tamper proof seal for refund
        $postData['TAMPER_PROOF_SEAL'] = $this->generateTamperProofSeal(
            'REFUND',
            $amount,
            $params['transaction_id'],
            '',
            ''
        );

        $response = $this->callBluepayApi($postData);

        if ($response === null) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bluepayremote_invalid_response'),
                'data' => [],
            ];
        }

        // Refund başarı sinyali de STATUS=1 (WHMCS bluepayremote.php:48 pattern).
        $status = (string) ($response['STATUS'] ?? '');
        $transId = $response['TRANS_ID'] ?? $response['trans_id'] ?? '';
        $message = $response['MESSAGE'] ?? $response['Message'] ?? '';

        if ($status === '1') {
            return [
                'status' => 'success',
                'message' => __('admin/modules.bluepayremote_refund_success'),
                'refund_id' => $transId,
                'data' => [
                    'trans_id' => $transId,
                    'auth_code' => $response['AUTH_CODE'] ?? '',
                    'message' => $message,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => ! empty($message)
                ? __('admin/modules.bluepayremote_refund_error_detail', ['error' => $message])
                : __('admin/modules.bluepayremote_refund_failed'),
            'data' => [
                'trans_id' => $transId,
                'message' => $message,
                'status' => $status,
            ],
        ];
    }

    /**
     * Payment link generation is not supported for direct CC processing
     */
    public function generatePaymentLink(array $params)
    {
        return [
            'status' => 'error',
            'message' => __('admin/modules.bluepayremote_payment_link_not_supported'),
        ];
    }

    /**
     * Test connection by sending a $0.00 AUTH transaction
     */
    public function testConnection(array $params = [])
    {
        $amount = '0.00';

        $testCard = '4111111111111111';

        $postData = $this->buildPostData([
            'TRANS_TYPE' => 'AUTH',
            'AMOUNT' => $amount,
            'PAYMENT_ACCOUNT' => $testCard,
            'CARD_EXPIRE' => '1230',
            'PAYMENT_TYPE' => 'CREDIT',
        ]);

        // Generate tamper proof seal for test auth
        $postData['TAMPER_PROOF_SEAL'] = $this->generateTamperProofSeal(
            'AUTH',
            $amount,
            '',
            '',
            $testCard
        );

        $response = $this->callBluepayApi($postData);

        if ($response === null) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bluepayremote_connection_failed'),
            ];
        }

        // AUTH onayı STATUS=1 (HostBill authorize():22). Bir yanıt (STATUS
        // alanıyla) alabilmemiz = credential/seal geçerli demektir.
        $status = (string) ($response['STATUS'] ?? '');
        $message = $response['MESSAGE'] ?? $response['Message'] ?? '';

        if ($status === '1') {
            return [
                'status' => 'success',
                'message' => __('admin/modules.bluepayremote_connection_success'),
            ];
        }

        // STATUS != 1: kimlik/seal doğrulama hatası → fail-closed (false-positive yok).
        return [
            'status' => 'error',
            'message' => ! empty($message)
                ? __('admin/modules.bluepayremote_payment_error_detail', ['error' => $message])
                : __('admin/modules.bluepayremote_auth_failed'),
        ];
    }

    /**
     * Validate configuration fields
     */
    public function validateConfig()
    {
        $required = ['account_id', 'secret_key'];
        $missing = [];

        foreach ($required as $field) {
            if (empty($this->config[$field])) {
                $missing[] = $field;
            }
        }

        if (! empty($missing)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bluepayremote_config_missing', ['fields' => implode(', ', $missing)]),
            ];
        }

        return [
            'status' => 'success',
            'message' => __('admin/modules.bluepayremote_config_valid'),
        ];
    }

    /**
     * Get supported features
     */
    public function getFeatures(): array
    {
        return [
            'refund' => true,
            '3d_secure' => false,
            'save_card' => false,
            'recurring' => false,
            'fraud_check' => true,
        ];
    }

    /**
     * Get configuration fields for admin panel
     */
    public function getConfigFields(): array
    {
        return array_merge(parent::getConfigFields(), [
            'account_id' => [
                'type' => 'text',
                'label' => 'Account ID',
                'description' => 'BluePay Account ID (12-digit)',
                'required' => true,
                'value' => '',
                'placeholder' => 'Enter BluePay Account ID',
            ],
            'secret_key' => [
                'type' => 'password',
                'label' => 'Secret Key',
                'description' => 'BluePay Secret Key (for tamper-proof seal)',
                'required' => true,
                'value' => '',
                'placeholder' => 'Enter Secret Key',
            ],
            'currency' => [
                'type' => 'select',
                'label' => 'Currency',
                'description' => 'Default currency for payments',
                'required' => true,
                'value' => 'USD',
                'options' => [
                    'USD' => 'US Dollar (USD)',
                ],
            ],
        ]);
    }

    /**
     * Generate BluePay tamper-proof seal (MD5 hash)
     *
     * Hash composition: secret_key + account_id + trans_type + amount + master_id + name1 + payment_account
     */
    private function generateTamperProofSeal(
        string $transType,
        string $amount,
        string $masterId = '',
        string $name1 = '',
        string $paymentAccount = ''
    ): string {
        $secretKey = $this->getConfig('secret_key', '');
        $accountId = $this->getConfig('account_id', '');

        $sealString = $secretKey . $accountId . $transType . $amount . $masterId . $name1 . $paymentAccount;

        return md5($sealString);
    }

    /**
     * Build POST data array with common fields
     */
    private function buildPostData(array $transactionData): array
    {
        $data = [
            'ACCOUNT_ID' => $this->getConfig('account_id', ''),
            'MODE' => $this->isTestMode() ? 'TEST' : 'LIVE',
        ];

        return array_merge($data, $transactionData);
    }

    /**
     * Parse BluePay response string into associative array
     *
     * BluePay returns URL-encoded name=value pairs separated by &
     */
    private function parseResponse(string $response): array
    {
        $result = [];
        parse_str($response, $result);

        return $result;
    }

    /**
     * Call BluePay 2.0 API via the PRC-888 form-urlencoded helper
     * (TLS-verify açık + SSRF proto-kısıtı). bp20post yanıtı URL-encoded
     * name=value çiftleridir; parse edilerek assoc döner.
     */
    private function callBluepayApi(array $data): ?array
    {
        $result = $this->postForm($this->apiUrl, $data, [], ['timeout' => 60]);

        if (! empty($result['error']) || $result['raw_response'] === '') {
            return null;
        }

        return $this->parseResponse((string) $result['raw_response']);
    }

    public function getSupportedFeatures(): array
    {
        return $this->getFeatures();
    }
}
