<?php

namespace UltraguardPro\modules\api_security\db;

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

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- API request logging intentionally writes and prunes live request rows.
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- API request log maintenance uses validated internal table identifiers only.

use UltraguardPro\db\BaseTable;

class ApiRequestLogTable extends BaseTable {

    protected $table_name  = 'ultraguard_api_request_log';
    protected $cache_group = 'ultraguard_api_request_log';

    public function get_defaults(): array {
        return [
            'id'            => 0,
            'endpoint'      => '',
            'method'        => 'GET',
            'ip_address'    => '',
            'auth_type'     => 'none',
            'key_id'        => 0,
            'response_code' => 200,
            'was_blocked'   => 0,
            'block_reason'  => '',
            'request_type'  => 'rest',
            'created_at'    => '',
        ];
    }

    protected function validate_data( $data ) {
        return $this->validate_required( (array) $data, [ 'endpoint', 'method', 'ip_address' ] ) ? $data : false;
    }

    protected function sanitize_data( $data ): array {
        $out = [];
        foreach ( (array) $data as $key => $value ) {
            if ( in_array( $key, [ 'key_id', 'response_code', 'was_blocked' ], true ) ) {
                $out[ $key ] = absint( $value );
            } else {
                $out[ $key ] = is_string( $value ) ? sanitize_text_field( $value ) : $value;
            }
        }

        return $out;
    }

    public function insert( array $data ) {
        global $wpdb;

        $data = $this->prepare_request_log_row( $data );
        if ( ! $data ) {
            return false;
        }

        $table = $wpdb->prefix . $this->table_name;
        $ok    = $wpdb->insert( $table, $data );

        if ( false === $ok ) {
            return false;
        }

        $id = ! empty( $wpdb->insert_id ) ? (int) $wpdb->insert_id : 0;
        if ( $id > 0 ) {
            $this->after_insert( $id, $data );
            do_action( "ultraguard_{$this->table_name}_inserted", $id, $data );
            return $id;
        }

        return false;
    }

    public function get_recent_requests( int $limit = 50, int $page = 1 ): array {
        $offset = max( 0, ( $page - 1 ) * $limit );
        return (array) $this->get_by( [], max( 1, min( 250, $limit ) ), 'created_at', 'DESC', $offset );
    }

    public function prune_records( int $days = 90 ): int {
        global $wpdb;

        $days   = max( 1, absint( $days ) );
        $cutoff = gmdate( 'Y-m-d H:i:s', strtotime( "-{$days} days" ) );
        $table  = $wpdb->prefix . $this->table_name;

        $deleted = $wpdb->query(  // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- query built via prepare(); table name is a validated internal identifier.
            $wpdb->prepare(
                "DELETE FROM `{$table}` WHERE `created_at` < %s",
                $cutoff
            )
        );

        return max( 0, (int) $deleted );
    }

    private function prepare_request_log_row( array $data ) {
        $data = wp_parse_args( $data, $this->get_defaults() );
        $data = $this->validate_data( $data );
        if ( ! $data ) {
            return false;
        }

        $data = $this->sanitize_data( $data );
        unset( $data['id'] );

        if ( empty( $data['created_at'] ) ) {
            $data['created_at'] = current_time( 'mysql', true );
        }

        return $this->before_insert( $data );
    }
}
