<?php
/**
 * LlAllowedIpsTable — standalone class file.
 *
 * @package UltraguardPro\modules\loginlimiter\db
 */

namespace UltraguardPro\modules\loginlimiter\db;

use UltraguardPro\db\BaseTable;
use UltraguardPro\core\DatabaseCrud;

if ( ! defined( 'ABSPATH' ) ) { exit; }

/**
 * LlAllowedIpsTable — Module-owned IP allow list.
 *
 * IPs on this list are exempt from lockout enforcement and brute-force counting.
 *
 * @package UltraguardPro\modules\loginlimiter\db
 * @since   6.5.0
 */
class LlAllowedIpsTable extends BaseTable {

    protected $table_name  = 'ultraguard_ll_allowed_ips';
    protected $cache_group = 'ultraguard_ll_allowed_ips';

    public function get_defaults(): array {
        return [
            'id'         => 0,
            'ip_address' => '',
            'label'      => '',
            'added_by'   => 0,
            'created_at' => '',
            'updated_at' => '',
        ];
    }

    protected function validate_data( $data ) {
        if ( empty( $data['ip_address'] ) ) { return false; }
        if ( ! filter_var( $data['ip_address'], FILTER_VALIDATE_IP ) ) { return false; }
        return $data;
    }

    protected function sanitize_data( $data ): array {
        $out = [];
        foreach ( $data as $k => $v ) {
            $out[ $k ] = match ( $k ) {
                'added_by' => absint( $v ),
                'label'    => sanitize_text_field( substr( (string) $v, 0, 200 ) ),
                default    => is_string( $v ) ? sanitize_text_field( $v ) : $v,
            };
        }
        return $out;
    }

    protected function get_searchable_fields(): array {
        return [ 'ip_address', 'label' ];
    }

    // ── Domain methods ─────────────────────────────────────────────────────────

    /**
     * Fast check whether an IP is in the allow list.
     * Direct query — called on every failed login.
     *
     * @param  string $ip
     * @return bool
     */
    public function is_allowed( string $ip ): bool {
        return DatabaseCrud::record_exists( $this->table_name, [ 'ip_address' => $ip ] );
    }

    /**
     * Add an IP to the allow list.
     *
     * @param  string $ip
     * @param  string $label  Optional admin label.
     * @return int|false  New row ID or false on duplicate.
     */
    public function allow_ip( string $ip, string $label = '' ): int|false {
        if ( $this->is_allowed( $ip ) ) { return false; }

        return $this->insert( [
            'ip_address' => $ip,
            'label'      => $label,
            'added_by'   => get_current_user_id(),
        ] );
    }

    /**
     * Remove an IP from the allow list by row ID.
     *
     * @param  int $id
     * @return bool
     */
    public function remove( int $id ): bool {
        return $this->delete( $id );
    }
}
