<?php
 
namespace App\Rules;
 
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Http;

class SafeCidr implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        // Determine if it is valid CIDR
        $valid = false;
        $simple_addr = $value;

        if(str_contains($value, '/')) {
            [$address, $mask] = explode('/', $value);

            $simple_addr = $address;
            
            if(str_contains($address, '.')) {
                $valid = boolval(filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) && $mask > 0 && $mask <= 32;
            }
            else {
                $valid = boolval(filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))  && $mask > 0 && $mask <= 128;
            }
        }
        else {
            if(str_contains($value, '.')) {
                $valid = boolval(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE));
            }
            else {
                $valid = boolval(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE));
            }
        }

        // Check if it is an allowed address...
        if($valid) {

            $hmac = hash_hmac('sha256', "$simple_addr", config('creatia.secret.bgp_forward')); 
  
            try {
                $values = Http::withHeaders([
                    'Authorization' => "$hmac",
                    'Content-Type' => 'application/json'
                  ])
                  ->retry(3, 100)
                  ->get(config('creatia.endpoint.bgp_forward') . '/validate', [
                    'addr'        => $simple_addr
                  ])
                  ->json()['results'];

                if(str_contains($values, 'Network not in table')) {
                    return true;
                }
                else {
                    \Log::debug("Attempt to redirect banned prefix...");
                }
    
            }
            catch(\Exception $ex) {
                \Log::debug($ex);
                return false;
            }
        }

        return false;
    }
 
    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be a safe CIDR.';
    }
}