<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Helpers para ler valores do request (GET/POST) de forma segura.
 *
 * Evitam o uso directo de $_GET/$_POST (PHPCS warnings) e centralizam sanitização.
 *
 * Alterações principais:
 * - Nonce values and superglobal reads are explicitly sanitized immediately after access
 *   so static analyzers detect proper sanitization.
 * - Prefer FILTER_SANITIZE_FULL_SPECIAL_CHARS when using filter_input for strings.
 */

/**
 * Obter um inteiro do request (GET ou POST).
 *
 * @param string $key         Nome do parâmetro.
 * @param string $method      'GET' ou 'POST'.
 * @param int    $default     Valor por omissão.
 * @param string $nonce_field (opcional) nome do campo nonce (ex: 'newssync_nonce').
 * @param string $nonce_action (opcional) action usada no nonce (ex: 'newssync_save_settings').
 * @return int
 */
function newssync_request_int( $key, $method = 'GET', $default = 0, $nonce_field = '', $nonce_action = '' ) {
    $method = strtoupper( (string) $method );

    // Nonce optional check: retorna default em caso de falha
    if ( $nonce_field !== '' && $nonce_action !== '' ) {
        $nonce_val = '';
        if ( 'POST' === $method && isset( $_POST[ $nonce_field ] ) ) {
            // sanitize nonce input explicitly to satisfy static analyzers
            $nonce_val = sanitize_text_field( wp_unslash( $_POST[ $nonce_field ] ) );
        } elseif ( 'GET' === $method && isset( $_GET[ $nonce_field ] ) ) {
            $nonce_val = sanitize_text_field( wp_unslash( $_GET[ $nonce_field ] ) );
        } elseif ( isset( $_REQUEST[ $nonce_field ] ) ) {
            $nonce_val = sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_field ] ) );
        }

        if ( ! wp_verify_nonce( $nonce_val, $nonce_action ) ) {
            return intval( $default );
        }
    }

    // Prefer filter_input quando disponível (mantém compatibilidade), senão usa superglobals.
    if ( function_exists( 'filter_input' ) ) {
        if ( 'POST' === $method ) {
            $val = filter_input( INPUT_POST, $key, FILTER_VALIDATE_INT );
            if ( false !== $val && null !== $val ) {
                return intval( $val );
            }
            return intval( $default );
        }

        // GET
        $val = filter_input( INPUT_GET, $key, FILTER_VALIDATE_INT );
        if ( false !== $val && null !== $val ) {
            return intval( $val );
        }
        return intval( $default );
    }

    // Fallback seguro: leia & sanitize das superglobals imediatamente para satisfazer PHPCS.
	if ( 'POST' === $method ) {
		if ( isset( $_POST[ $key ] ) ) {
			// unslash + sanitize on read (static analyzers require sanitization at read site)
			$raw = sanitize_text_field( wp_unslash( $_POST[ $key ] ) );
		} else {
			$raw = null;
		}
	} else { // GET por omissão
		if ( isset( $_GET[ $key ] ) ) {
			$raw = sanitize_text_field( wp_unslash( $_GET[ $key ] ) );
		} else {
			$raw = null;
		}
	}

	if ( $raw === null || $raw === '' ) {
		return intval( $default );
	}

	// Já sanitizado como texto; agora converte para int
	return intval( $raw );
	}

/**
 * Obter uma string do request (GET ou POST).
 *
 * Por omissão aplica sanitize_text_field(). Se esperares HTML válido,
 * passa 'wp_kses_post' como $sanitize_cb.
 *
 * @param string        $key          Nome do parâmetro.
 * @param string        $method       'GET' ou 'POST'.
 * @param string        $default      Valor por omissão.
 * @param string        $nonce_field  (opcional) nome do campo nonce (ex: 'newssync_nonce').
 * @param string        $nonce_action (opcional) action usada no nonce (ex: 'newssync_save_settings').
 * @param callable|null $sanitize_cb  (opcional) função de sanitização (ex: 'sanitize_text_field' | 'wp_kses_post').
 * @return string
 */
function newssync_request_string( $key, $method = 'GET', $default = '', $nonce_field = '', $nonce_action = '', $sanitize_cb = 'sanitize_text_field' ) {
    $method = strtoupper( (string) $method );

    // Nonce optional check: retorna default se falhar
    if ( $nonce_field !== '' && $nonce_action !== '' ) {
        $nonce_val = '';
        if ( 'POST' === $method && isset( $_POST[ $nonce_field ] ) ) {
            $nonce_val = sanitize_text_field( wp_unslash( $_POST[ $nonce_field ] ) );
        } elseif ( 'GET' === $method && isset( $_GET[ $nonce_field ] ) ) {
            $nonce_val = sanitize_text_field( wp_unslash( $_GET[ $nonce_field ] ) );
        } elseif ( isset( $_REQUEST[ $nonce_field ] ) ) {
            $nonce_val = sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_field ] ) );
        }

        if ( ! wp_verify_nonce( $nonce_val, $nonce_action ) ) {
            return (string) $default;
        }
    }

    // Prefer filter_input se existir - use a sanitizing filter when possible so static analyzers are happy
    if ( function_exists( 'filter_input' ) ) {
        // prefer a sanitizing filter for strings if available; avoid FILTER_UNSAFE_RAW as a fallback
        if ( defined( 'FILTER_SANITIZE_FULL_SPECIAL_CHARS' ) ) {
            $string_filter = FILTER_SANITIZE_FULL_SPECIAL_CHARS;
        } elseif ( defined( 'FILTER_SANITIZE_SPECIAL_CHARS' ) ) {
            $string_filter = FILTER_SANITIZE_SPECIAL_CHARS;
        } else {
            $string_filter = FILTER_SANITIZE_STRING;
        }

        if ( 'POST' === $method ) {
            $val = filter_input( INPUT_POST, $key, $string_filter );
            if ( $val !== null && $val !== false ) {
                $val = wp_unslash( (string) $val );
                if ( is_callable( $sanitize_cb ) ) {
                    return call_user_func( $sanitize_cb, $val );
                }
                return (string) $val;
            }
            return (string) $default;
        }

        // GET
        $val = filter_input( INPUT_GET, $key, $string_filter );
        if ( $val !== null && $val !== false ) {
            $val = wp_unslash( (string) $val );
            if ( is_callable( $sanitize_cb ) ) {
                return call_user_func( $sanitize_cb, $val );
            }
            return (string) $val;
        }
        return (string) $default;
    }

    // Fallback: leia & sanitize das superglobals imediatamente para satisfazer PHPCS.
    // Aplicamos sanitização apropriada no ponto da leitura; se um sanitize_cb específico for pedido,
    // usamos esse callback (para preservar HTML quando 'wp_kses_post' for solicitado).
    if ( 'POST' === $method ) {
        if ( isset( $_POST[ $key ] ) ) {
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_unslash applied here and sanitize_cb applied immediately afterwards
            $val_raw = wp_unslash( $_POST[ $key ] );
        } else {
            $val_raw = null;
        }
    } else { // GET por omissão
        if ( isset( $_GET[ $key ] ) ) {
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_unslash applied here and sanitize_cb applied immediately afterwards
            $val_raw = wp_unslash( $_GET[ $key ] );
        } else {
            $val_raw = null;
        }
    }

    if ( $val_raw === null ) {
        return (string) $default;
    }

    // If a specific sanitize callback is requested, apply it now (so static analyzers see immediate sanitization).
    if ( is_callable( $sanitize_cb ) ) {
        return (string) call_user_func( $sanitize_cb, (string) $val_raw );
    }

    // Default sanitization for general strings
    return sanitize_text_field( (string) $val_raw );
}

    /**
     * Return a plugin-identifying User-Agent string.
     *
     * Use a constant if available, otherwise fall back to a stable value.
     *
     * @return string
     */
    function newssync_get_user_agent() {
        $version = defined( 'NEWSYNC_VERSION' ) ? NEWSYNC_VERSION : '1.0';
        return 'NewsSync/' . $version . ' (+https://daazlabs.com/)';
    }

    /**
     * Wrapper for wp_remote_get with sane defaults (timeout, User-Agent) and header merge.
     *
     * @param string $url  URL to request.
     * @param array  $args Optional args passed to wp_remote_get.
     * @return WP_Error|array Response
     */
    function newssync_http_get( $url, $args = array() ) {
        $defaults = array(
            'timeout' => 15,
            'headers' => array(
                'User-Agent' => newssync_get_user_agent(),
            ),
        );

        if ( ! empty( $args['headers'] ) && is_array( $args['headers'] ) ) {
            $args['headers'] = array_merge( $defaults['headers'], $args['headers'] );
            $defaults['headers'] = array();
        }

        $args = wp_parse_args( $args, $defaults );
        return wp_remote_get( $url, $args );
    }

    /**
     * Wrapper for wp_remote_post with sane defaults (timeout, User-Agent) and header merge.
     *
     * @param string $url  URL to request.
     * @param array  $args Optional args passed to wp_remote_post.
     * @return WP_Error|array Response
     */
    function newssync_http_post( $url, $args = array() ) {
        $defaults = array(
            'timeout' => 20,
            'headers' => array(
                'User-Agent' => newssync_get_user_agent(),
            ),
        );

        if ( ! empty( $args['headers'] ) && is_array( $args['headers'] ) ) {
            $args['headers'] = array_merge( $defaults['headers'], $args['headers'] );
            $defaults['headers'] = array();
        }

        $args = wp_parse_args( $args, $defaults );
        return wp_remote_post( $url, $args );
    }
