<?php

declare(strict_types=1);

namespace App\Services;

use App\Services\Dto\RossvyazRecord;
use Illuminate\Support\Facades\DB;

/**
 * Локальный fallback резолва региона/оператора по телефону через реестр
 * нумерации Россвязи (`phone_ranges`).
 *
 * Используется LeadRegionResolver когда DaData недоступна/неуверена (qc=1,
 * timeout, бюджет исчерпан). Алгоритм (spec §3.7):
 *   - def_code = 3 цифры кода ABC/DEF (позиции 1..3 нормализованного номера);
 *   - subscriber = остаток номера как BIGINT;
 *   - выбираем самый УЗКИЙ диапазон, накрывающий номер (ORDER BY width ASC),
 *     т.к. узкие переопределения операторов точнее широких региональных блоков.
 *
 * Запрос идёт через `pgsql_supplier` (BYPASSRLS на проде, как LeadRouter):
 * `phone_ranges` — SaaS-level публичные данные без RLS.
 */
class RossvyazPrefixLookup
{
    /** Connection для чтения реестра (на проде BYPASSRLS, на dev/test — superuser fallback). */
    public const CONNECTION = 'pgsql_supplier';

    public function find(string $phone): ?RossvyazRecord
    {
        $digits = preg_replace('/\D+/', '', $phone) ?? '';

        // Российский номер: 7|8 + ABC/DEF (3) + абонент (7) = 11 цифр.
        if (strlen($digits) !== 11) {
            return null;
        }

        $defCode = (int) substr($digits, 1, 3);
        $subscriber = (int) substr($digits, 4);

        $row = DB::connection(self::CONNECTION)->selectOne(
            'SELECT region, operator, subject_code
               FROM phone_ranges
              WHERE def_code = ? AND from_num <= ? AND to_num >= ?
              ORDER BY (to_num - from_num) ASC
              LIMIT 1',
            [$defCode, $subscriber, $subscriber],
        );

        if ($row === null) {
            return null;
        }

        return new RossvyazRecord(
            subjectCode: $row->subject_code !== null ? (int) $row->subject_code : null,
            region: (string) $row->region,
            operator: (string) $row->operator,
        );
    }
}
