<?php
namespace App\Services;
use App\Models\TransferCode;
use Illuminate\Support\Str;
final class TransferCodeService
{
    public function generate(): array
    {
        $alphabet=(string)config('payment.code_alphabet');
        $length=(int)config('payment.code_length');
        do {
            $raw=$this->secureString($alphabet,$length);
            $hash=hash('sha256',$raw);
        } while (TransferCode::where('code_hash',$hash)->exists());

        return ['raw'=>$raw,'display'=>implode('-',str_split($raw,4)),'hash'=>$hash,'last4'=>substr($raw,-4),'qr_payload'=>'cbaps:v1:'.Str::random(48)];
    }

    public function normalize(string $code): string
    {
        return preg_replace('/[^A-Z0-9]/','',strtoupper($code))??'';
    }

    public function hash(string $code): string
    {
        return hash('sha256',$this->normalize($code));
    }

    private function secureString(string $alphabet,int $length): string
    {
        $size=strlen($alphabet);
        $limit=256-(256%$size);
        $value='';
        while(strlen($value)<$length){
            foreach(unpack('C*',random_bytes(max(16,$length*2))) as $byte){
                if($byte>=$limit)continue;
                $value.=$alphabet[$byte%$size];
                if(strlen($value)===$length)break;
            }
        }
        return $value;
    }
}
