<?php
/**
 * File Path: includes/api/class-mbs-telemetry-failure-tracker.php
 *
 * Telemetry Failure Tracker -- My Book Showroom
 *
 * Accumulates API and import failure counts between weekly telemetry pings.
 * Counts are stored in wp_options (auto-loaded: false) and flushed
 * (read + reset) by MBS_Telemetry_Client::send_ping() after a successful ping.
 *
 * SECURITY: Only integer counts are stored -- no error messages, license keys,
 * credentials, book titles, or user-identifying data are ever written here.
 *
 * F-006 -- Sprint F006 -- 2026-04-27.
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Api
 * @since      1.1.0
 */

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

class MBS_Telemetry_Failure_Tracker { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	const OPTION_KEY = 'mbs_telemetry_failure_counts';

	const DEFAULT_COUNTS = array(
		'api'    => array(
			'license_validate' => 0,
			'update_check'     => 0,
			'telemetry_ping'   => 0,
		),
		'import' => array(
			'mybooktable' => 0,
			'wxr'         => 0,
			'json'        => 0,
			'paapi_sync'  => 0,
		),
	);

	public static function record_api_failure( string $endpoint ): void {
		self::increment( 'api', $endpoint, 1 );
	}

	public static function record_import_failure( string $importer, int $count = 1 ): void {
		if ( $count <= 0 ) {
			return;
		}
		self::increment( 'import', $importer, $count );
	}

	public static function get_counts(): array {
		$stored = get_option( self::OPTION_KEY, array() );
		return self::merge_with_defaults( is_array( $stored ) ? $stored : array() );
	}

	public static function flush_and_reset(): array {
		$counts = self::get_counts();
		update_option( self::OPTION_KEY, self::DEFAULT_COUNTS, false );
		return $counts;
	}

	private static function increment( string $category, string $key, int $by ): void {
		$counts = self::get_counts();
		$counts[ $category ][ $key ] = ( (int) ( $counts[ $category ][ $key ] ?? 0 ) ) + $by;
		update_option( self::OPTION_KEY, $counts, false );
	}

	private static function merge_with_defaults( array $stored ): array {
		$result = self::DEFAULT_COUNTS;
		foreach ( $result as $cat => $keys ) {
			foreach ( array_keys( $keys ) as $key ) {
				if ( isset( $stored[ $cat ][ $key ] ) ) {
					$result[ $cat ][ $key ] = (int) $stored[ $cat ][ $key ];
				}
			}
		}
		return $result;
	}
}
