<?php

namespace App\Core;

/**
 * بوابة الدفع - Stripe، زين كاش، آسيا باي، رابط يدوي
 */
class PaymentGateway
{
    private \PDO $db;
    private array $settings = [];
    private int $tenantId;

    public function __construct(\PDO $db, int $tenantId = 1)
    {
        $this->db = $db;
        $this->tenantId = $tenantId;
        $this->loadSettings();
    }

    private function loadSettings(): void
    {
        try {
            $stmt = $this->db->prepare(
                'SELECT setting_key, setting_value FROM settings
                 WHERE tenant_id = ? AND (setting_key LIKE "payment_%" OR setting_key LIKE "stripe_%" OR setting_key LIKE "zaincash_%" OR setting_key LIKE "asiapay_%")'
            );
            $stmt->execute([$this->tenantId]);
            foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $r) {
                $this->settings[$r['setting_key']] = $r['setting_value'] ?? '';
            }
        } catch (\Throwable $e) {}
    }

    private function get(string $key, string $default = ''): string
    {
        return trim($this->settings[$key] ?? $default);
    }

    public function getGateway(): string
    {
        $g = $this->get('payment_gateway', 'link');
        return in_array($g, ['link', 'stripe', 'zaincash', 'asiapay'], true) ? $g : 'link';
    }

    public function isEnabled(): bool
    {
        $g = $this->getGateway();
        if ($g === 'link') return $this->get('payment_link') !== '';
        if ($g === 'stripe') return $this->get('stripe_secret_key') !== '';
        if ($g === 'zaincash') return $this->get('zaincash_merchant_id') !== '' && $this->get('zaincash_secret') !== '';
        if ($g === 'asiapay') return $this->get('asiapay_app_key') !== '' && $this->get('asiapay_app_secret') !== '';
        return false;
    }

    /**
     * إنشاء رابط أو تحويل للدفع
     * @return array{url: string, method: string, error?: string}
     */
    public function createPayment(array $invoice, string $successUrl, string $cancelUrl): array
    {
        $remaining = max(0, (float)$invoice['net_amount'] - (float)$invoice['paid_amount']);
        $gateway = $this->getGateway();

        if ($gateway === 'link') {
            $link = $this->get('payment_link');
            if ($link === '') return ['url' => '', 'method' => 'redirect', 'error' => 'لم يُضبط رابط الدفع'];
            $sep = strpos($link, '?') !== false ? '&' : '?';
            $url = $link . $sep . 'invoice=' . urlencode($invoice['invoice_number']) . '&amount=' . $remaining;
            return ['url' => $url, 'method' => 'redirect'];
        }

        if ($gateway === 'stripe') {
            return $this->createStripePayment($invoice, $remaining, $successUrl, $cancelUrl);
        }

        if ($gateway === 'zaincash') {
            return $this->createZainCashPayment($invoice, $remaining, $successUrl, $cancelUrl);
        }

        if ($gateway === 'asiapay') {
            return $this->createAsiaPayPayment($invoice, $remaining, $successUrl, $cancelUrl);
        }

        return ['url' => '', 'method' => 'redirect', 'error' => 'بوابة غير مدعومة'];
    }

    private function createStripePayment(array $invoice, float $amount, string $successUrl, string $cancelUrl): array
    {
        $secret = $this->get('stripe_secret_key');
        if ($secret === '') return ['url' => '', 'method' => 'redirect', 'error' => 'مفتاح Stripe غير مضبوط'];

        $currency = ($invoice['currency'] ?? '') === 'IQD' ? 'iqd' : 'usd';
        $amountCents = $currency === 'usd' ? (int)round($amount * 100) : (int)round($amount);
        if ($amountCents < 1) return ['url' => '', 'method' => 'redirect', 'error' => 'المبلغ صفر'];

        $payload = [
            'mode' => 'payment',
            'payment_method_types' => ['card'],
            'line_items' => [[
                'price_data' => [
                    'currency' => $currency,
                    'unit_amount' => $amountCents,
                    'product_data' => [
                        'name' => 'فاتورة ' . ($invoice['invoice_number'] ?? ''),
                        'description' => 'طلب ' . ($invoice['order_number'] ?? '') . ' - ' . ($invoice['patient_name'] ?? ''),
                    ]
                ],
                'quantity' => 1
            ]],
            'success_url' => $successUrl . (strpos($successUrl, '?') !== false ? '&' : '?') . 'session_id={CHECKOUT_SESSION_ID}',
            'cancel_url' => $cancelUrl,
            'metadata' => ['invoice_id' => (string)($invoice['id'] ?? ''), 'invoice_number' => $invoice['invoice_number'] ?? '']
        ];

        $ch = curl_init('https://api.stripe.com/v1/checkout/sessions');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $secret,
                'Content-Type: application/x-www-form-urlencoded'
            ],
            CURLOPT_POSTFIELDS => http_build_query([
                'mode' => 'payment',
                'payment_method_types[]' => 'card',
                'line_items[0][price_data][currency]' => $currency,
                'line_items[0][price_data][unit_amount]' => $amountCents,
                'line_items[0][price_data][product_data][name]' => 'فاتورة ' . ($invoice['invoice_number'] ?? ''),
                'line_items[0][quantity]' => 1,
                'success_url' => $successUrl . (strpos($successUrl, '?') !== false ? '&' : '?') . 'session_id={CHECKOUT_SESSION_ID}',
                'cancel_url' => $cancelUrl,
                'metadata[invoice_id]' => (string)($invoice['id'] ?? ''),
                'metadata[invoice_number]' => $invoice['invoice_number'] ?? ''
            ])
        ]);
        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($code !== 200) {
            $err = json_decode($response, true);
            return ['url' => '', 'method' => 'redirect', 'error' => $err['error']['message'] ?? 'فشل Stripe'];
        }
        $data = json_decode($response, true);
        $url = $data['url'] ?? '';
        return ['url' => $url, 'method' => 'redirect'];
    }

    private function createZainCashPayment(array $invoice, float $amount, string $successUrl, string $cancelUrl): array
    {
        $mid = $this->get('zaincash_merchant_id');
        $msisdn = $this->get('zaincash_msisdn');
        $secret = $this->get('zaincash_secret');
        $prod = $this->get('zaincash_is_production') === '1';
        if ($mid === '' || $secret === '') return ['url' => '', 'method' => 'redirect', 'error' => 'إعدادات زين كاش ناقصة'];

        $baseUrl = $prod ? 'https://api.zaincash.iq' : 'https://sandbox.zaincash.iq';
        $orderId = 'INV' . ($invoice['id'] ?? time()) . rand(100, 999);
        $amountIQD = (int)round($amount);

        $data = [
            'amount' => $amountIQD,
            'orderId' => $orderId,
            'msisdn' => $msisdn,
            'redirectUrl' => $successUrl,
            'iat' => time(),
            'exp' => time() + 3600
        ];
        $token = $this->jwtEncode($data, $secret);

        return [
            'url' => $baseUrl . '/transaction/pay?id=' . urlencode($token),
            'method' => 'redirect',
            'order_id' => $orderId
        ];
    }

    private function createAsiaPayPayment(array $invoice, float $amount, string $successUrl, string $cancelUrl): array
    {
        $appKey = $this->get('asiapay_app_key');
        $appSecret = $this->get('asiapay_app_secret');
        $merchant = $this->get('asiapay_merchant_code');
        if ($appKey === '' || $appSecret === '') return ['url' => '', 'method' => 'redirect', 'error' => 'إعدادات Asia Pay ناقصة'];

        $baseUrl = $this->get('asiapay_is_production') === '1' ? 'https://api.asiapay.iq' : 'https://apitest.asiapay.iq:5443';
        $amountIQD = (int)round($amount);

        $ch = curl_init($baseUrl . '/apiaccess/payment/gateway/payment/v1/token');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_POSTFIELDS => json_encode([
                'appKey' => $appKey,
                'appSecret' => $appSecret
            ])
        ]);
        $tokenRes = curl_exec($ch);
        curl_close($ch);
        $tokenData = json_decode($tokenRes, true);
        $accessToken = $tokenData['data']['token'] ?? $tokenData['token'] ?? '';
        if ($accessToken === '') return ['url' => '', 'method' => 'redirect', 'error' => 'فشل الحصول على رمز Asia Pay'];

        $orderId = 'INV' . ($invoice['id'] ?? time()) . rand(100, 999);
        $ch2 = curl_init($baseUrl . '/apiaccess/payment/gateway/payment/v1/create');
        curl_setopt_array($ch2, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $accessToken
            ],
            CURLOPT_POSTFIELDS => json_encode([
                'merchantCode' => $merchant,
                'amount' => $amountIQD,
                'orderId' => $orderId,
                'callbackUrl' => $successUrl,
                'invoiceNumber' => $invoice['invoice_number'] ?? ''
            ])
        ]);
        $orderRes = curl_exec($ch2);
        curl_close($ch2);
        $orderData = json_decode($orderRes, true);
        $payUrl = $orderData['data']['paymentUrl'] ?? $orderData['paymentUrl'] ?? '';
        if ($payUrl === '') return ['url' => '', 'method' => 'redirect', 'error' => 'فشل إنشاء طلب Asia Pay'];

        return ['url' => $payUrl, 'method' => 'redirect', 'order_id' => $orderId];
    }

    private function jwtEncode(array $payload, string $secret): string
    {
        $header = ['alg' => 'HS256', 'typ' => 'JWT'];
        $b64 = function ($d) {
            return rtrim(strtr(base64_encode(json_encode($d)), '+/', '-_'), '=');
        };
        $sign = hash_hmac('sha256', $b64($header) . '.' . $b64($payload), $secret, true);
        return $b64($header) . '.' . $b64($payload) . '.' . rtrim(strtr(base64_encode($sign), '+/', '-_'), '=');
    }

    public function getPaymentLink(): ?string
    {
        $link = $this->get('payment_link');
        return $link !== '' ? $link : null;
    }

    public function getPaymentNumber(): ?string
    {
        $n = $this->get('payment_number');
        return $n !== '' ? $n : null;
    }
}
