<?php

namespace App\Http\Controllers\Public;

use App\Http\Controllers\Controller;
use App\Http\Requests\SubmitNinRequest;
use App\Http\Requests\VerifyNinByPhoneRequest;
use App\Services\NinEncryptionService;
use App\Services\NinVerificationApiService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

class NinVerificationController extends Controller
{
    public function __construct(
        private readonly NinEncryptionService $ninEncryptionService,
        private readonly NinVerificationApiService $ninVerificationApiService,
    ) {}

    /**
     * Return the RSA public key for NIN encryption.
     * Public — no authentication required.
     */
    public function publicKey(): JsonResponse
    {
        try {
            $publicKey = $this->ninEncryptionService->getPublicKey();

            return response()->json([
                'success'    => true,
                'public_key' => $publicKey,
            ]);
        } catch (\RuntimeException $e) {
            return response()->json([
                'success'      => false,
                'service_down' => true,
                'message'      => 'NIN encryption is not configured on this server.',
            ], 503);
        }
    }

    /**
     * Verify a NIN and return the identity data from the external API.
     * Public — no authentication required. Nothing is stored.
     */
    public function verify(SubmitNinRequest $request): JsonResponse
    {
        // Step 1: RSA-OAEP decrypt the NIN
        try {
            $decryptedNin = $this->ninEncryptionService->decryptWithPrivateKey($request->validated('encrypted_nin'));
        } catch (\Exception $e) {
            Log::warning('Public NIN verify: RSA decryption failed', ['error' => $e->getMessage()]);
            return response()->json([
                'success' => false,
                'message' => 'Invalid encrypted data.',
            ], 422);
        }

        // Step 2: Validate NIN format (11 digits)
        if (! $this->ninEncryptionService->validateNinFormat($decryptedNin)) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid NIN format. NIN must be 11 digits.',
            ], 422);
        }

        // Step 3: Call Dojah and return the result
        $result = $this->ninVerificationApiService->verifyNin($decryptedNin);

        if (! $result['success'] || ! $result['verified']) {
            $serviceDown = $result['service_unavailable'] ?? false;
            $status = $serviceDown ? 503 : 422;
            return response()->json(array_filter([
                'success'      => false,
                'service_down' => $serviceDown ?: null,
                'message'      => $result['message'] ?? 'NIN verification failed.',
            ]), $status);
        }

        return response()->json([
            'success' => true,
            'message' => 'NIN verified successfully.',
            'data'    => $result['data'],
        ]);
    }

    /**
     * Look up NIN data using a phone number.
     * Used for public and admin routes — auth is enforced at the route level.
     * Nothing is stored.
     */
    public function verifyByPhone(VerifyNinByPhoneRequest $request): JsonResponse
    {
        $result = $this->ninVerificationApiService->verifyNinByPhone(
            $request->validated('phone_number'),
        );

        if (! $result['success'] || ! $result['verified']) {
            $serviceDown = $result['service_unavailable'] ?? false;
            $status = $serviceDown ? 503 : 422;
            return response()->json(array_filter([
                'success'      => false,
                'service_down' => $serviceDown ?: null,
                'message'      => $result['message'] ?? 'NIN lookup by phone number failed.',
            ]), $status);
        }

        return response()->json([
            'success' => true,
            'message' => 'NIN record retrieved successfully.',
            'data'    => $result['data'],
        ]);
    }
}
