<?php
/**
 * Class Noesia Cs Settings Binding Service.
 *
 * @package Noesia_Commerce_Suite
 */

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

/**
 * Class implementation.
 */
class Noesia_CS_Settings_Binding_Service {
	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $runtime_cache = null;

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $sections Sections.
	 * @param mixed $labels Labels.
	 */
	public function get_report( $sections = array(), $labels = array() ) {
		$defaults      = Noesia_CS_Settings::defaults();
		$section_map   = $this->build_section_map( $sections );
		$runtime_refs  = $this->get_runtime_references( array_keys( $defaults ) );
		$policy_keys   = $this->policy_keys();
		$rows          = array();
		$counts       = array(
			'total'          => count( $defaults ),
			'in_form'        => 0,
			'runtime_bound'  => 0,
			'policy_bound'   => 0,
			'needs_review'   => 0,
		);

		foreach ( $defaults as $key => $default ) {
			$in_form        = isset( $section_map[ $key ] );
			$runtime_files  = isset( $runtime_refs[ $key ] ) ? $runtime_refs[ $key ] : array();
			$is_policy      = isset( $policy_keys[ $key ] );
			$status         = 'needs-review';
			$status_label   = __( 'Needs review', 'noesia-commerce-suite' );
			$note           = __( 'No direct runtime reference was found outside settings/admin configuration files.', 'noesia-commerce-suite' );

			if ( ! empty( $runtime_files ) ) {
				$status        = 'runtime-bound';
				$status_label  = __( 'Runtime bound', 'noesia-commerce-suite' );
				$note         = sprintf(
					/* translators: %d: number of runtime files. */
					_n( 'Used by %d runtime file.', 'Used by %d runtime files.', count( $runtime_files ), 'noesia-commerce-suite' ),
					count( $runtime_files )
				);
			} elseif ( $is_policy ) {
				$status        = 'policy-bound';
				$status_label  = __( 'Policy enforced', 'noesia-commerce-suite' );
				$note          = $policy_keys[ $key ];
			}

			if ( $in_form ) {
				$counts['in_form']++;
			}
			if ( 'runtime-bound' === $status ) {
				$counts['runtime_bound']++;
			} elseif ( 'policy-bound' === $status ) {
				$counts['policy_bound']++;
			} else {
				$counts['needs_review']++;
			}

			$rows[] = array(
				'key'           => $key,
				'label'         => isset( $labels[ $key ] ) ? $labels[ $key ] : ucwords( str_replace( '_', ' ', $key ) ),
				'section'       => $in_form ? $section_map[ $key ] : __( 'Not shown in Settings', 'noesia-commerce-suite' ),
				'in_form'       => $in_form,
				'status'        => $status,
				'status_label'  => $status_label,
				'note'          => $note,
				'files'         => $runtime_files,
			);
		}

		return array(
			'counts'  => $counts,
			'rows'    => $rows,
		);
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $sections Sections.
	 */
	private function build_section_map( $sections ) {
		$map = array();
		if ( ! is_array( $sections ) ) {
			return $map;
		}
		foreach ( $sections as $section ) {
			$title   = isset( $section['title'] ) ? $section['title'] : '';
			$fields  = isset( $section['fields'] ) && is_array( $section['fields'] ) ? $section['fields'] : array();
			foreach ( $fields as $field ) {
				$map[ $field ] = $title;
			}
		}
		return $map;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $keys Keys.
	 */
	private function get_runtime_references( $keys ) {
		if ( null !== $this->runtime_cache ) {
			return $this->runtime_cache;
		}

		$references  = array_fill_keys( $keys, array() );
		$files       = $this->runtime_files();

		foreach ( $files as $file ) {
			$contents = file_get_contents( $file );
			if ( false === $contents ) {
				continue;
			}
			$relative = str_replace( NOESIA_CS_PATH, '', $file );
			foreach ( $keys as $key ) {
				$patterns = array(
					"Noesia_CS_Settings::get( '" . $key . "'",
					'Noesia_CS_Settings::get( "' . $key . '"',
					"['" . $key . "']",
					'["' . $key . '"]',
				);
				foreach ( $patterns as $pattern ) {
					if ( false !== strpos( $contents, $pattern ) ) {
						$references[ $key ][] = $relative;
						break;
					}
				}
			}
		}

		foreach ( $references as $key => $files_for_key ) {
			$references[ $key ] = array_values( array_unique( $files_for_key ) );
		}

		$this->runtime_cache = $references;
		return $references;
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function runtime_files() {
		$roots = array(
			NOESIA_CS_PATH . 'includes/services',
			NOESIA_CS_PATH . 'includes/public',
			NOESIA_CS_PATH . 'includes/repositories',
			NOESIA_CS_PATH . 'modules',
			NOESIA_CS_PATH . 'templates',
		);
		$files = array();

		foreach ( $roots as $root ) {
			if ( ! is_dir( $root ) ) {
				continue;
			}
			$iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ) );
			foreach ( $iterator as $file ) {
				if ( ! $file->isFile() || 'php' !== strtolower( $file->getExtension() ) ) {
					continue;
				}
				$path = $file->getPathname();
				if ( false !== strpos( $path, '/modules/settings/' ) || false !== strpos( $path, 'class-noesia-cs-settings-binding-service.php' ) ) {
					continue;
				}
				$files[] = $path;
			}
		}

		return $files;
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function policy_keys() {
		return array(
			'privacy_hide_full_name'       => __( 'Public templates are designed not to output full customer names.', 'noesia-commerce-suite' ),
			'privacy_hide_address'         => __( 'Public templates are designed not to output customer addresses.', 'noesia-commerce-suite' ),
			'privacy_hide_email'           => __( 'Public templates are designed not to output customer email addresses.', 'noesia-commerce-suite' ),
			'privacy_hide_phone'           => __( 'Public templates are designed not to output customer phone numbers.', 'noesia-commerce-suite' ),
			'secure_token_behavior'        => __( 'The current free core uses active non-guessable token behavior only.', 'noesia-commerce-suite' ),
			'wc_status_check'              => __( 'Controls the compatibility status panel visibility for WooCommerce checks.', 'noesia-commerce-suite' ),
			'hpos_status_check'            => __( 'Controls the compatibility status panel visibility for HPOS checks.', 'noesia-commerce-suite' ),
			'privacy_hide_revenue_public'  => __( 'Revenue is hidden publicly unless both revenue visibility settings allow it.', 'noesia-commerce-suite' ),
		);
	}
}
