<?php

namespace App\Http\Middleware;

use App\Support\PhoneNumber;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

class NormalizePhoneInputs
{
    public function handle(Request $request, Closure $next): mixed
    {
        if (in_array(strtoupper($request->method()), ['GET', 'HEAD', 'OPTIONS'], true)) {
            return $next($request);
        }

        $submittedCountryCode = $request->input('phone_country_code');
        if ($submittedCountryCode !== null && ! PhoneNumber::isValidCountryCode($submittedCountryCode)) {
            throw ValidationException::withMessages([
                'phone_country_code' => 'Enter a valid country calling code using digits only, for example 255.',
            ]);
        }

        $countryCode = PhoneNumber::sanitizeCountryCode($submittedCountryCode ?? PhoneNumber::countryCode());
        $errors = [];
        $payload = $this->normalizeArray($request->request->all(), $countryCode, $errors);

        if ($errors !== []) {
            throw ValidationException::withMessages($errors);
        }

        $request->request->replace($payload);

        return $next($request);
    }

    private function normalizeArray(array $values, string $countryCode, array &$errors, string $prefix = ''): array
    {
        foreach ($values as $key => $value) {
            $path = $prefix === '' ? (string) $key : $prefix.'.'.$key;

            if (is_array($value)) {
                $values[$key] = $this->normalizeArray($value, $countryCode, $errors, $path);
                continue;
            }

            if (! $this->isPhoneField((string) $key) || $key === 'phone_country_code') {
                continue;
            }

            if ($value === null || trim((string) $value) === '') {
                continue;
            }

            $normalized = PhoneNumber::normalize($value, $countryCode);
            if ($normalized === null) {
                $errors[$path] = 'Enter 9 digits starting with 6 or 7, or 10 digits starting with 0 followed by 6 or 7.';
                continue;
            }

            $values[$key] = $normalized;
        }

        return $values;
    }

    private function isPhoneField(string $key): bool
    {
        $key = strtolower($key);

        return $key === 'phone'
            || str_ends_with($key, '_phone')
            || (str_starts_with($key, 'phone_') && $key !== 'phone_country_code')
            || $key === 'mobile'
            || str_ends_with($key, '_mobile')
            || $key === 'telephone'
            || str_ends_with($key, '_telephone');
    }
}
