<?php
/**
 * Settings reader.
 *
 * Settings live one row per key in the zinv_settings table, with the value
 * JSON-encoded. This is the read-side counterpart to ZINV_REST_Settings,
 * used by core CRUD code that needs a saved preference (invoice prefix,
 * default template, etc.) without going through the REST layer.
 *
 * @since 1.0.0
 */

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

class ZINV_Settings {

	/**
	 * Per-request cache of every settings row, keyed by setting_key.
	 *
	 * @var array<string,mixed>|null
	 */
	private static ?array $cache = null;

	/**
	 * Get a single setting value.
	 *
	 * @param string $key     Setting key (e.g. 'invoice_prefix').
	 * @param mixed  $default Returned when the key has no stored row.
	 * @return mixed
	 */
	public static function get( string $key, $default = '' ) {
		$all = self::all();
		return array_key_exists( $key, $all ) ? $all[ $key ] : $default;
	}

	/**
	 * Load and cache all settings rows for this request.
	 *
	 * @return array<string,mixed>
	 */
	private static function all(): array {
		if ( null !== self::$cache ) {
			return self::$cache;
		}

		// Check persistent object cache first (populated on previous requests).
		$cached = wp_cache_get( 'zinv_settings_all', 'zoventic-invoices' );
		if ( is_array( $cached ) ) {
			self::$cache = $cached;
			return self::$cache;
		}

		global $wpdb;
		$table = ( new ZINV_Database( 'zinv_settings' ) )->get_table_name();

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
		$rows = $wpdb->get_results( "SELECT setting_key, setting_value FROM {$table}" );

		$out = [];
		foreach ( (array) $rows as $row ) {
			$value = json_decode( $row->setting_value, true );
			if ( JSON_ERROR_NONE !== json_last_error() ) {
				$value = $row->setting_value;
			}
			$out[ $row->setting_key ] = $value;
		}

		wp_cache_set( 'zinv_settings_all', $out, 'zoventic-invoices', 5 * MINUTE_IN_SECONDS );
		self::$cache = $out;
		return self::$cache;
	}

	/**
	 * Drop the per-request cache and the persistent object cache entry.
	 * Call after a settings write so a later read in the same request sees fresh values.
	 */
	public static function flush_cache(): void {
		self::$cache = null;
		wp_cache_delete( 'zinv_settings_all', 'zoventic-invoices' );
	}
}
