<?php

namespace App\Modules\Payment\Tco;

use App\Core\Payment\AbstractPayment;

class Tco extends AbstractPayment
{
    protected $apiUrl;

    protected $checkoutUrl;

    /** 2Checkout sales/account REST API base (sandbox-aware — WHMCS tco.php:33-37). */
    protected $apiBase;

    public function __construct(array $config = [])
    {
        parent::__construct($config);

        $sellerId = $this->getConfig('seller_id', '');

        $this->apiUrl = $this->isTestMode()
            ? "https://sandbox.2checkout.com/checkout/api/1/{$sellerId}/rs/authService"
            : "https://www.2checkout.com/checkout/api/1/{$sellerId}/rs/authService";

        $this->checkoutUrl = $this->isTestMode()
            ? 'https://sandbox.2checkout.com/checkout/purchase'
            : 'https://www.2checkout.com/checkout/purchase';

        // sales/acct REST API (refund + account detail). WHMCS tco.php sandbox'ta
        // sandbox.2checkout.com, prod'da www.2checkout.com kullanır.
        $this->apiBase = $this->isTestMode()
            ? 'https://sandbox.2checkout.com'
            : 'https://www.2checkout.com';
    }

    /**
     * Ödeme girişimi başlatır
     *
     * @return array
     */
    public function attemptPayment(array $params)
    {
        $requiredParams = ['amount', 'currency', 'order_id', 'customer_email'];

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

        return [
            'status' => 'ready',
            'message' => __('admin/modules.tco_ready'),
            'data' => [
                'payment_method' => 'tco',
                'amount' => $params['amount'],
                'currency' => $params['currency'],
                'order_id' => $params['order_id'],
                'redirect_url' => $this->checkoutUrl,
            ],
        ];
    }

    /**
     * Ödeme işlemini gerçekleştirir - 2Checkout redirect
     *
     * @return array
     */
    public function makePayment(array $params)
    {
        $redirectParams = $this->buildRedirectParams($params);

        $redirectUrl = $this->checkoutUrl.'?'.http_build_query($redirectParams);

        return [
            'status' => 'redirect',
            'message' => __('admin/modules.tco_redirect'),
            'redirect_url' => $redirectUrl,
            'data' => [
                'redirect_url' => $redirectUrl,
                'redirect_params' => $redirectParams,
                'method' => 'GET',
            ],
        ];
    }

    /**
     * 2Checkout callback'ini işler — İKİ ayrı doğrulama yolu (fail-closed).
     *
     * INS webhook: md5_hash alanı VAR → md5(sale_id+vendor_id+invoice_id+secret)
     *   (HostBill TwocheckoutNotification.php:14 / WHMCS Standard.php:46-47).
     *   message_type=ORDER_CREATED | (FRAUD_STATUS_CHANGED && fraud_status=pass)
     *   | RECURRING_INSTALLMENT_SUCCESS gate'i (WHMCS Standard.php:52-119).
     * Return passback: key alanı VAR → md5(secret+sid+order_number+total)
     *   (HostBill TwocheckoutReturn.php:14 / official buy-link passback).
     *
     * @return array
     */
    public function handlePaymentCallback(array $params)
    {
        // INS webhook'u md5_hash alanıyla, return passback'i key alanıyla ayırt et.
        if (isset($params['md5_hash']) && $params['md5_hash'] !== '') {
            return $this->handleInsCallback($params);
        }

        return $this->handleReturnCallback($params);
    }

    /**
     * INS (Instant Notification Service) webhook doğrulama + message_type gate.
     */
    private function handleInsCallback(array $params): array
    {
        $secretWord = $this->getConfig('secret_key', '');
        $saleId = (string) ($params['sale_id'] ?? '');
        $vendorId = (string) ($params['vendor_id'] ?? $this->getConfig('seller_id', ''));
        $invoiceId = (string) ($params['invoice_id'] ?? '');

        // WHMCS Standard.php:46: strtoupper(md5(sale_id.vendor.invoice.secret))
        $expected = strtoupper(md5($saleId.$vendorId.$invoiceId.$secretWord));

        if (empty($secretWord) || empty($saleId)
            || ! $this->secureCompare($expected, strtoupper((string) $params['md5_hash']))) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.tco_invalid_hash'),
            ];
        }

        $messageType = $params['message_type'] ?? '';
        $orderId = $params['vendor_order_id'] ?? $params['merchant_order_id'] ?? '';
        $amount = $params['invoice_list_amount'] ?? $params['item_list_amount_1'] ?? '';
        $currency = $params['list_currency'] ?? '';

        // ORDER_CREATED veya RECURRING_INSTALLMENT_SUCCESS → paid (WHMCS Standard.php:82,99).
        $paid = in_array($messageType, ['ORDER_CREATED', 'RECURRING_INSTALLMENT_SUCCESS'], true);

        // FRAUD_STATUS_CHANGED yalnız fraud_status=pass ise paid (WHMCS Standard.php:66-73).
        if ($messageType === 'FRAUD_STATUS_CHANGED') {
            $paid = ($params['fraud_status'] ?? '') === 'pass';
        }

        if (! $paid) {
            return [
                'status' => 'pending',
                'message' => __('admin/modules.tco_payment_pending'),
                'data' => [
                    'message_type' => $messageType,
                    'order_id' => $orderId,
                    'transaction_id' => $saleId,
                ],
            ];
        }

        return [
            'status' => 'success',
            'message' => __('admin/modules.tco_payment_success'),
            'transaction_id' => $saleId,
            'data' => [
                'order_number' => $saleId,
                'invoice_id' => $orderId,
                'total' => $amount,
                'currency' => $currency,
                'message_type' => $messageType,
            ],
        ];
    }

    /**
     * Return passback doğrulama (buy-link müşteri dönüşü).
     */
    private function handleReturnCallback(array $params): array
    {
        $secretWord = $this->getConfig('secret_key', '');
        $sellerId = (string) ($params['sid'] ?? $this->getConfig('seller_id', ''));
        $orderNumber = (string) ($params['order_number'] ?? '');
        $total = (string) ($params['total'] ?? '');

        // HostBill TwocheckoutReturn.php:14: strtoupper(md5(secret.sid.order.total))
        $expected = strtoupper(md5($secretWord.$sellerId.$orderNumber.$total));

        if (empty($secretWord) || empty($orderNumber)
            || ! $this->secureCompare($expected, strtoupper((string) ($params['key'] ?? '')))) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.tco_invalid_hash'),
            ];
        }

        return [
            'status' => 'success',
            'message' => __('admin/modules.tco_payment_success'),
            'transaction_id' => $orderNumber,
            'data' => [
                'order_number' => $orderNumber,
                'invoice_id' => $params['merchant_order_id'] ?? '',
                'total' => $total,
                'currency' => $params['currency_code'] ?? '',
            ],
        ];
    }

    /**
     * Ödeme iadesi yapar
     *
     * @return array
     */
    public function refundPayment(array $params)
    {
        $apiUsername = $this->getConfig('api_username', '');
        $apiPassword = $this->getConfig('api_password', '');

        if (empty($apiUsername) || empty($apiPassword)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.tco_api_credentials_missing'),
            ];
        }

        // WHMCS tco.php:31-36: sale_id "sale-invoice" formatında olabilir;
        // varsa böl. currency='vendor' SABİT (ISO kod DEĞİL). amount major-unit.
        $saleId = (string) ($params['invoice_id'] ?? $params['transaction_id'] ?? '');
        $refundData = [
            'sale_id' => $saleId,
            'amount' => number_format((float) $params['amount'], 2, '.', ''),
            'currency' => 'vendor',
            'category' => 5,
            'comment' => $params['reason'] ?? $params['note'] ?? 'Refund from ProCP',
        ];
        if (strpos($saleId, '-') !== false) {
            [$refundData['sale_id'], $refundData['invoice_id']] = explode('-', $saleId, 2);
        }

        // sales API form-urlencoded ister (WHMCS http_build_query). Basic auth
        // Authorization header ile (foundation transport USERPWD desteklemez).
        $refundUrl = $this->apiBase.'/api/sales/refund_invoice';
        $result = $this->postForm($refundUrl, $refundData, [
            'Accept: application/json',
            'Authorization: Basic '.base64_encode($apiUsername.':'.$apiPassword),
        ]);

        $httpCode = $result['http_code'];
        $responseData = is_array($result['response'])
            ? $result['response']
            : json_decode((string) $result['raw_response'], true);

        if ($httpCode === 200 && isset($responseData['response_code']) && $responseData['response_code'] === 'OK') {
            return [
                'status' => 'success',
                'message' => __('admin/modules.tco_refund_success'),
                'refund_id' => $responseData['refund_id'] ?? '',
                'data' => [
                    'response_code' => $responseData['response_code'],
                    'response_message' => $responseData['response_message'] ?? '',
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => $responseData['errors'][0]['message'] ?? __('admin/modules.tco_refund_failed'),
            'data' => [
                'http_code' => $httpCode,
                'response_code' => $responseData['response_code'] ?? null,
            ],
        ];
    }

    /**
     * 2Checkout ödeme linki oluşturur
     *
     * @return array
     */
    public function generatePaymentLink(array $params)
    {
        $linkParams = [
            'sid' => $this->getConfig('seller_id'),
            'mode' => '2CO',
            'li_0_name' => $params['description'] ?? 'Payment for order '.$params['order_id'],
            'li_0_price' => number_format($params['amount'], 2, '.', ''),
            'li_0_quantity' => 1,
            'currency_code' => $params['currency'] ?? $this->getConfig('currency', 'USD'),
            'merchant_order_id' => $params['order_id'],
        ];

        if (! empty($params['customer_email'])) {
            $linkParams['email'] = $params['customer_email'];
        }

        if (! empty($params['success_url'])) {
            $linkParams['x_receipt_link_url'] = $params['success_url'];
        }

        // Test-mode buy-link demo işareti (makePayment ile tutarlı).
        if ($this->isTestMode()) {
            $linkParams['demo'] = 'Y';
        }

        $paymentUrl = $this->checkoutUrl.'?'.http_build_query($linkParams);

        return [
            'status' => 'success',
            'payment_url' => $paymentUrl,
            'data' => [
                'payment_url' => $paymentUrl,
                'params' => $linkParams,
            ],
        ];
    }

    /**
     * API bağlantı testi
     *
     * @return array
     */
    public function testConnection(array $params = [])
    {
        $sellerId = $this->getConfig('seller_id', '');
        $apiUsername = $this->getConfig('api_username', '');
        $apiPassword = $this->getConfig('api_password', '');

        if (empty($apiUsername) || empty($apiPassword)) {
            // API credentials yoksa sadece seller_id kontrolü yap
            if (! empty($sellerId)) {
                return [
                    'status' => 'success',
                    'message' => __('admin/modules.tco_connection_partial'),
                    'data' => [
                        'seller_id' => $sellerId,
                        'note' => 'API credentials not configured - only redirect checkout available',
                    ],
                ];
            }

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

        // API credentials ile bağlantı testi (sandbox-aware — test-mode'da sandbox).
        $testUrl = $this->apiBase.'/api/acct/detail_company_info';

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $testUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_USERPWD, $apiUsername.':'.$apiPassword);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Accept: application/json',
        ]);

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

        if ($httpCode === 200) {
            return [
                'status' => 'success',
                'message' => __('admin/modules.tco_connection_success'),
                'data' => ['http_code' => $httpCode],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.tco_connection_failed'),
            'data' => [
                'http_code' => $httpCode,
            ],
        ];
    }

    /**
     * Konfigürasyon doğrulama
     *
     * @return array
     */
    public function validateConfig()
    {
        $required = ['seller_id', 'secret_key'];
        $missing = [];

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

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

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

    /**
     * Modülün desteklediği özellikleri döndürür
     */
    public function getFeatures(): array
    {
        return [
            'refund' => true,
            '3d_secure' => false,
            'save_card' => false,
            'recurring' => true,
            'fraud_check' => false,
        ];
    }

    /**
     * Desteklenen özellikleri döndürür (AbstractPayment'tan required metod)
     */
    public function getSupportedFeatures(): array
    {
        return $this->getFeatures();
    }

    /**
     * Get configuration fields for admin panel
     */
    public function getConfigFields(): array
    {
        return array_merge(parent::getConfigFields(), [
            'seller_id' => [
                'type' => 'text',
                'label' => 'Seller ID',
                'description' => '2Checkout seller/merchant ID',
                'required' => true,
                'value' => '',
                'placeholder' => 'Enter your 2Checkout Seller ID',
            ],
            'secret_key' => [
                'type' => 'password',
                'label' => 'Secret Key',
                'description' => '2Checkout secret key for hash validation',
                'required' => true,
                'value' => '',
                'placeholder' => 'Enter your 2Checkout Secret Key',
            ],
            'api_username' => [
                'type' => 'text',
                'label' => 'API Username',
                'description' => '2Checkout API username (required for refunds)',
                'required' => false,
                'value' => '',
                'placeholder' => 'Enter API username',
            ],
            'api_password' => [
                'type' => 'password',
                'label' => 'API Password',
                'description' => '2Checkout API password (required for refunds)',
                'required' => false,
                'value' => '',
                'placeholder' => 'Enter API password',
            ],
            'currency' => [
                'type' => 'select',
                'label' => 'Currency',
                'description' => 'Default payment currency',
                'required' => true,
                'value' => 'USD',
                'options' => [
                    'USD' => 'US Dollar (USD)',
                    'EUR' => 'Euro (EUR)',
                    'GBP' => 'British Pound (GBP)',
                ],
            ],
            'checkout_type' => [
                'type' => 'select',
                'label' => 'Checkout Type',
                'description' => '2Checkout checkout page type',
                'required' => false,
                'value' => 'standard',
                'options' => [
                    'standard' => 'Standard (Redirect)',
                    'inline' => 'Inline (Embedded)',
                ],
            ],
        ]);
    }

    /**
     * Redirect parametrelerini oluşturur
     */
    private function buildRedirectParams(array $params): array
    {
        $redirectParams = [
            'sid' => $this->getConfig('seller_id'),
            'mode' => '2CO',
            'li_0_name' => $params['description'] ?? 'Order #'.$params['order_id'],
            'li_0_price' => number_format($params['amount'], 2, '.', ''),
            'li_0_quantity' => 1,
            'currency_code' => $params['currency'] ?? $this->getConfig('currency', 'USD'),
            'merchant_order_id' => $params['order_id'],
            'email' => $params['customer_email'] ?? '',
        ];

        if (! empty($params['success_url'])) {
            $redirectParams['x_receipt_link_url'] = $params['success_url'];
        }

        if (! empty($params['customer_name'])) {
            $redirectParams['card_holder_name'] = $params['customer_name'];
        }

        if (! empty($params['customer_phone'])) {
            $redirectParams['phone'] = $params['customer_phone'];
        }

        if (! empty($params['billing_address'])) {
            $address = $params['billing_address'];
            $redirectParams['street_address'] = $address['address'] ?? $address['street'] ?? '';
            $redirectParams['city'] = $address['city'] ?? '';
            $redirectParams['state'] = $address['state'] ?? '';
            $redirectParams['zip'] = $address['zip'] ?? $address['postcode'] ?? '';
            $redirectParams['country'] = $address['country'] ?? '';
        }

        // Test mode parametresi
        if ($this->isTestMode()) {
            $redirectParams['demo'] = 'Y';
        }

        return $redirectParams;
    }
}
