<?php

namespace App\Services;

use App\Models\Payment;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

/**
 * QPay v2 API client.
 *
 * Documentation: https://developer.qpay.mn/
 *
 * Required .env:
 * QPAY_USERNAME=...
 * QPAY_PASSWORD=...
 * QPAY_INVOICE_CODE=...
 * QPAY_BASE_URL=https://merchant.qpay.mn/v2
 * QPAY_SANDBOX=false
 */
class QPayService
{
    protected string $baseUrl;
    protected string $username;
    protected string $password;
    protected string $invoiceCode;
    protected bool $sandbox;

    public function __construct()
    {
        $this->baseUrl     = rtrim(config('services.qpay.base_url', 'https://merchant.qpay.mn/v2'), '/');
        $this->username    = config('services.qpay.username', '');
        $this->password    = config('services.qpay.password', '');
        $this->invoiceCode = config('services.qpay.invoice_code', '');
        $this->sandbox     = (bool) config('services.qpay.sandbox', false);
    }

    public function isConfigured(): bool
    {
        return ! empty($this->username) && ! empty($this->password) && ! empty($this->invoiceCode);
    }

    /**
     * Access token авах (cached 50 мин).
     */
    protected function getAccessToken(): ?string
    {
        return Cache::remember('qpay_access_token', 50 * 60, function () {
            try {
                $response = Http::withBasicAuth($this->username, $this->password)
                    ->timeout(15)
                    ->post($this->baseUrl . '/auth/token');

                if (! $response->successful()) {
                    Log::error('QPay auth failed', ['status' => $response->status(), 'body' => $response->body()]);
                    return null;
                }
                return $response->json('access_token');
            } catch (\Exception $e) {
                Log::error('QPay auth exception', ['msg' => $e->getMessage()]);
                return null;
            }
        });
    }

    /**
     * Invoice үүсгэх.
     *
     * @return array|null ['invoice_id', 'qr_text', 'qr_image', 'urls']
     */
    public function createInvoice(Payment $payment): ?array
    {
        $token = $this->getAccessToken();
        if (! $token) return null;

        $senderInvoiceNo = 'NSMA-' . $payment->id . '-' . Str::random(6);

        try {
            $response = Http::withToken($token)
                ->timeout(20)
                ->post($this->baseUrl . '/invoice', [
                    'invoice_code'         => $this->invoiceCode,
                    'sender_invoice_no'    => $senderInvoiceNo,
                    'invoice_receiver_code'=> $payment->lead->phone ?: 'WEB',
                    'invoice_description'  => 'NSMA ' . strtoupper($payment->tier) . ' template захиалга',
                    'amount'               => (int) $payment->amount,
                    'callback_url'         => route('payment.webhook') . '?payment_id=' . $payment->id,
                ]);

            if (! $response->successful()) {
                Log::error('QPay invoice failed', [
                    'status' => $response->status(),
                    'body'   => $response->body(),
                    'payment_id' => $payment->id,
                ]);
                Cache::forget('qpay_access_token'); // Token expired magadgvi
                return null;
            }

            $data = $response->json();

            return [
                'invoice_id' => $data['invoice_id'] ?? null,
                'qr_text'    => $data['qr_text'] ?? '',
                'qr_image'   => $data['qr_image'] ?? '',
                'urls'       => $data['urls'] ?? [],
            ];

        } catch (\Exception $e) {
            Log::error('QPay invoice exception', ['msg' => $e->getMessage()]);
            return null;
        }
    }

    /**
     * Төлбөрийн статус шалгах.
     *
     * @return array|null ['paid' => bool, 'rows' => [...], 'count' => N]
     */
    public function checkPayment(string $qpayInvoiceId): ?array
    {
        $token = $this->getAccessToken();
        if (! $token) return null;

        try {
            $response = Http::withToken($token)
                ->timeout(15)
                ->post($this->baseUrl . '/payment/check', [
                    'object_type' => 'INVOICE',
                    'object_id'   => $qpayInvoiceId,
                    'offset'      => ['page_number' => 1, 'page_limit' => 100],
                ]);

            if (! $response->successful()) {
                Log::warning('QPay check failed', ['body' => $response->body()]);
                return null;
            }

            $data = $response->json();
            $count = $data['count'] ?? 0;
            $rows = $data['rows'] ?? [];

            // Хэрэв төлбөр амжилттай хийгдсэн PAID row байвал
            $paidRow = collect($rows)->first(fn($r) => ($r['payment_status'] ?? '') === 'PAID');

            return [
                'paid'  => (bool) $paidRow,
                'count' => $count,
                'rows'  => $rows,
                'paid_row' => $paidRow,
            ];

        } catch (\Exception $e) {
            Log::error('QPay check exception', ['msg' => $e->getMessage()]);
            return null;
        }
    }

    /**
     * Invoice цуцлах (хэрэв хэрэгцээтэй бол).
     */
    public function cancelInvoice(string $qpayInvoiceId): bool
    {
        $token = $this->getAccessToken();
        if (! $token) return false;

        try {
            $response = Http::withToken($token)
                ->timeout(10)
                ->delete($this->baseUrl . '/invoice/' . $qpayInvoiceId);
            return $response->successful();
        } catch (\Exception $e) {
            return false;
        }
    }
}
