<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use App\Services\Contracts\AikDigitalClientInterface;

/**
 * Drop-in mock for AikDigitalApiClient.
 *
 * Activated when AIKDIGITAL_MOCK=true in .env.
 * Returns realistic fake responses — no network calls made.
 *
 * Bind in AppServiceProvider:
 *
 *   if (config('aikdigital.mock')) {
 *       $this->app->bind(AikDigitalApiClient::class, MockAikDigitalApiClient::class);
 *   }
 */
class MockAikDigitalApiClient implements AikDigitalClientInterface

{
    private const MOCK_TOKEN      = 'mock-access-token-aik-digital-dev-only';
    private const MOCK_TOKEN_KEY  = 'aik_digital_mock_token';

    // ─────────────────────────────────────────────────────────────────────────
    // TOKEN MANAGEMENT
    // ─────────────────────────────────────────────────────────────────────────

    public function getAccessToken(): string
    {
        if (Cache::has(self::MOCK_TOKEN_KEY)) {
            return Cache::get(self::MOCK_TOKEN_KEY);
        }

        return $this->applyToken();
    }

    public function applyToken(): string
    {
        $token = self::MOCK_TOKEN;
        Cache::put(self::MOCK_TOKEN_KEY, $token, 86400);

        Log::info('[MOCK] AIK Digital: mock access token cached.');

        return $token;
    }

    public function revokeToken(): array
    {
        Cache::forget(self::MOCK_TOKEN_KEY);

        Log::info('[MOCK] AIK Digital: mock token revoked.');

        return [
            'result' => [
                'resultStatus'  => 'S',
                'resultCode'    => 'SUCCESS',
                'resultMessage' => 'Token revoked successfully (mock).',
            ],
        ];
    }

    // ─────────────────────────────────────────────────────────────────────────
    // USER INFO
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Mimics POST /v2/users/inquireUserInfo
     *
     * Pass a special UUID ending in 'fail' to simulate a failure response,
     * e.g. "00000000-0000-0000-0000-000000000001-fail" — useful for testing
     * error-handling paths without hitting the real gateway.
     */
    public function inquireUserInfo(string $uuid): array
    {
        Log::info("[MOCK] AIK Digital: inquireUserInfo called with uuid={$uuid}");

        // Simulate failure scenario when UUID ends with known test value
        if (str_ends_with($uuid, 'ffff-ffffffffffff')) {
            return [
                'result' => [
                    'resultStatus'  => 'F',
                    'resultCode'    => 'USER_NOT_FOUND',
                    'resultMessage' => 'User not found (mock failure scenario).',
                ],
            ];
        }

        return [
            'result' => [
                'resultStatus'  => 'S',
                'resultCode'    => 'SUCCESS',
                'resultMessage' => 'User info retrieved successfully (mock).',
            ],
            'userInfo' => [
                'openId'     => $uuid,
                'unionId'    => 'mock-union-id-' . substr($uuid, 0, 8),
                'userMsisdn' => '+923001234567',
                'userName'   => 'Ahmed Raza',
                'Email'      => 'ahmed.raza@example.com',
                'Dob'        => '1990-05-15',
                'CNIC'       => '42201-1234567-1',
                'Gender'     => 'MALE',
            ],
        ];
    }

    // ─────────────────────────────────────────────────────────────────────────
    // PAYMENT
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Mimics POST /v2/payments/createPayment
     *
     * Set payload['amount'] to '0.00' to trigger a mock payment failure.
     */
    public function createPayment(array $payload): array
    {
        Log::info('[MOCK] AIK Digital: createPayment called', $payload);

        // Simulate payment failure for zero/empty amount
        $amount = (float) ($payload['amount'] ?? 0);

        if ($amount <= 0) {
            return [
                'result' => [
                    'resultStatus'  => 'F',
                    'resultCode'    => 'INVALID_AMOUNT',
                    'resultMessage' => 'Payment amount must be greater than zero (mock failure scenario).',
                ],
            ];
        }

        $orderId       = 'MOCK-ORD-' . strtoupper(substr(md5(uniqid()), 0, 10));
        $transactionId = 'MOCK-TXN-' . strtoupper(substr(md5(uniqid()), 0, 12));

        return [
            'result' => [
                'resultStatus'  => 'S',
                'resultCode'    => 'SUCCESS',
                'resultMessage' => 'Payment created successfully (mock).',
            ],
            'paymentInfo' => [
                'orderId'         => $orderId,
                'transactionId'   => $transactionId,
                'amount'          => $payload['amount']   ?? '0.00',
                'currency'        => $payload['currency'] ?? 'PKR',
                'status'          => 'PENDING',
                'paymentUrl'      => 'https://mock-gateway.aikdigital.dev/pay/' . $orderId,
                'expiresAt'       => now()->addMinutes(15)->toIso8601String(),
                'createdAt'       => now()->toIso8601String(),
            ],
        ];
    }
}
