<?php

namespace App\Support;

use App\Models\FaceVerification;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use InvalidArgumentException;

class FaceVerificationService
{
    public function storeCapture(Request $request, User $user, string $image, string $context = 'profile', ?int $withdrawalId = null): FaceVerification
    {
        $binary = $this->decodeImage($image);
        $hash = hash('sha256', $binary);
        $duplicate = FaceVerification::where('image_hash', $hash)
            ->where('user_id', '!=', $user->id)
            ->whereIn('status', ['pending', 'approved', 'duplicate_review', 'cashout_submitted'])
            ->latest()
            ->first();

        // Stored on the private local disk (not public/storage) so face
        // captures are only reachable through the authorized image route.
        $path = 'face-verifications/'.$user->id.'/'.Str::uuid().'.png';
        Storage::disk('local')->put($path, $binary);

        return FaceVerification::create([
            'user_id' => $user->id,
            'withdrawal_id' => $withdrawalId,
            'context' => $context,
            'face_image_path' => $path,
            'image_hash' => $hash,
            'status' => $duplicate ? 'duplicate_review' : ($context === 'cashout' ? 'cashout_submitted' : 'pending'),
            'duplicate_of_user_id' => $duplicate?->user_id,
            'admin_note' => $duplicate ? 'Exact same submitted image was already used by another account. Review before approval.' : null,
            'ip' => $request->ip(),
            'user_agent' => substr((string) $request->userAgent(), 0, 255),
        ]);
    }

    public function hasApprovedProfile(User $user): bool
    {
        return FaceVerification::where('user_id', $user->id)
            ->where('context', 'profile')
            ->where('status', 'approved')
            ->exists();
    }

    private function decodeImage(string $image): string
    {
        if (!preg_match('/^data:image\/(png|jpeg|jpg);base64,/', $image)) {
            throw new InvalidArgumentException('Please capture a valid face image.');
        }

        $imageData = preg_replace('/^data:image\/(png|jpeg|jpg);base64,/', '', $image);
        $binary = base64_decode($imageData, true);

        if (!$binary || strlen($binary) < 1024 || strlen($binary) > 5 * 1024 * 1024) {
            throw new InvalidArgumentException('The captured image is invalid or too large.');
        }

        $imageInfo = @getimagesizefromstring($binary);

        if (!$imageInfo || !in_array($imageInfo[2], [IMAGETYPE_PNG, IMAGETYPE_JPEG], true)) {
            throw new InvalidArgumentException('Please capture a valid PNG or JPEG face image.');
        }

        [$width, $height] = $imageInfo;

        if ($width < 160 || $height < 160 || $width > 5000 || $height > 5000) {
            throw new InvalidArgumentException('The face image dimensions are not supported.');
        }

        return $binary;
    }
}
