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

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

/**
 * Audits the plugin service/module boundaries without performing business work.
 *
 * This is not a runtime feature for customers. It is an operational architecture
 * check used by the admin settings screen to keep the application modular and
 * avoid silent regressions back to monolithic code.
 */
class Noesia_CS_Service_Boundary_Service {
	/**
	 * Expected container services and repositories.
	 *
	 * @return array
	 */
	public function expected_services() {
		return array(
			'order_repository' => array(
				'label'             => __( 'Order Repository', 'noesia-commerce-suite' ),
				'class'             => 'Noesia_CS_Order_Repository',
				'type'              => 'repository',
				'role'              => __( 'HPOS-safe WooCommerce order access.', 'noesia-commerce-suite' ),
				'depends_on'        => array(),
			),
			'product_repository' => array(
				'label'               => __( 'Product Repository', 'noesia-commerce-suite' ),
				'class'               => 'Noesia_CS_Product_Repository',
				'type'                => 'repository',
				'role'                => __( 'Controlled WooCommerce product access.', 'noesia-commerce-suite' ),
				'depends_on'          => array(),
			),
			'passport_service' => array(
				'label'             => __( 'Passport Service', 'noesia-commerce-suite' ),
				'class'             => 'Noesia_CS_Passport_Service',
				'type'              => 'service',
				'role'              => __( 'Secure token and order care link handling.', 'noesia-commerce-suite' ),
				'depends_on'        => array( 'order_repository' ),
			),
			'warranty_service' => array(
				'label'             => __( 'Warranty Service', 'noesia-commerce-suite' ),
				'class'             => 'Noesia_CS_Warranty_Service',
				'type'              => 'service',
				'role'              => __( 'Warranty status and expiry calculation.', 'noesia-commerce-suite' ),
				'depends_on'        => array(),
			),
			'analytics_service' => array(
				'label'              => __( 'Analytics Service', 'noesia-commerce-suite' ),
				'class'              => 'Noesia_CS_Analytics_Service',
				'type'               => 'service',
				'role'               => __( 'Cached WooCommerce intelligence and payment reports.', 'noesia-commerce-suite' ),
				'depends_on'         => array( 'warranty_service', 'order_repository' ),
			),
			'doctor_service' => array(
				'label'           => __( 'Doctor Service', 'noesia-commerce-suite' ),
				'class'           => 'Noesia_CS_Doctor_Service',
				'type'            => 'service',
				'role'            => __( 'Manual capped ecommerce health scans.', 'noesia-commerce-suite' ),
				'depends_on'      => array( 'product_repository' ),
			),
			'impact_map_service' => array(
				'label'               => __( 'Impact Map Service', 'noesia-commerce-suite' ),
				'class'               => 'Noesia_CS_Impact_Map_Service',
				'type'                => 'service',
				'role'                => __( 'Cached privacy-safe impact snapshots.', 'noesia-commerce-suite' ),
				'depends_on'          => array( 'order_repository' ),
			),
			'email_service' => array(
				'label'          => __( 'Email Service', 'noesia-commerce-suite' ),
				'class'          => 'Noesia_CS_Email_Service',
				'type'           => 'service',
				'role'           => __( 'Template-based emails, previews and delivery logs.', 'noesia-commerce-suite' ),
				'depends_on'     => array( 'passport_service' ),
			),
			'reorder_service' => array(
				'label'            => __( 'Reorder Service', 'noesia-commerce-suite' ),
				'class'            => 'Noesia_CS_Reorder_Service',
				'type'             => 'service',
				'role'             => __( 'Customer reminder email scheduling, delivery records and opt-out state.', 'noesia-commerce-suite' ),
				'depends_on'       => array( 'passport_service', 'email_service', 'order_repository' ),
			),
			'data_service' => array(
				'label'         => __( 'Data Service', 'noesia-commerce-suite' ),
				'class'         => 'Noesia_CS_Data_Service',
				'type'          => 'service',
				'role'          => __( 'Retention-safe cleanup for plugin operational data.', 'noesia-commerce-suite' ),
				'depends_on'    => array(),
			),
			'feature_service' => array(
				'label'            => __( 'Feature Service', 'noesia-commerce-suite' ),
				'class'            => 'Noesia_CS_Feature_Service',
				'type'             => 'service',
				'role'             => __( 'Free/Pro-safe feature gates without premium code in Free.', 'noesia-commerce-suite' ),
				'depends_on'       => array(),
			),
			'system_status_service' => array(
				'label'                  => __( 'System Status Service', 'noesia-commerce-suite' ),
				'class'                  => 'Noesia_CS_System_Status_Service',
				'type'                   => 'service',
				'role'                   => __( 'Compatibility and endpoint diagnostics.', 'noesia-commerce-suite' ),
				'depends_on'             => array(),
			),
			'care_action_service' => array(
				'label'                => __( 'Care Action Service', 'noesia-commerce-suite' ),
				'class'                => 'Noesia_CS_Care_Action_Service',
				'type'                 => 'service',
				'role'                 => __( 'Privacy-safe care button action logging.', 'noesia-commerce-suite' ),
				'depends_on'           => array(),
			),
			'settings_binding_service' => array(
				'label'                     => __( 'Settings Binding Service', 'noesia-commerce-suite' ),
				'class'                     => 'Noesia_CS_Settings_Binding_Service',
				'type'                      => 'service',
				'role'                      => __( 'Settings runtime binding audit.', 'noesia-commerce-suite' ),
				'depends_on'                => array(),
			),
			'weather_service' => array(
				'label'            => __( 'Weather Service', 'noesia-commerce-suite' ),
				'class'            => 'Noesia_CS_Weather_Service',
				'type'             => 'service',
				'role'             => __( 'Optional external Open-Meteo dashboard forecast with caching.', 'noesia-commerce-suite' ),
				'depends_on'       => array(),
			),
			'service_boundary_service' => array(
				'label'                     => __( 'Service Boundary Service', 'noesia-commerce-suite' ),
				'class'                     => 'Noesia_CS_Service_Boundary_Service',
				'type'                      => 'service',
				'role'                      => __( 'Container, module and dependency boundary audit.', 'noesia-commerce-suite' ),
				'depends_on'                => array(),
			),
		);
	}

	/**
	 * Expected admin modules.
	 *
	 * @return array
	 */
	public function expected_modules() {
		return array(
			'dashboard'                => array( 'class' => 'Noesia_CS_Dashboard_Module', 'view' => 'modules/dashboard/views/admin.php' ),
			'order-care-hub'           => array( 'class' => 'Noesia_CS_Order_Care_Hub_Module', 'view' => 'modules/order-care-hub/views/admin.php' ),
			'reorder-reminders'        => array( 'class' => 'Noesia_CS_Reorder_Reminders_Module', 'view' => 'modules/reorder-reminders/views/admin.php' ),
			'reviews-support'          => array( 'class' => 'Noesia_CS_Reviews_Support_Module', 'view' => 'modules/reviews-support/views/admin.php' ),
			'intelligence-analytics'   => array( 'class' => 'Noesia_CS_Intelligence_Analytics_Module', 'view' => 'modules/intelligence-analytics/views/admin.php' ),
			'impact-map'               => array( 'class' => 'Noesia_CS_Impact_Map_Module', 'view' => 'modules/impact-map/views/admin.php' ),
			'ecommerce-doctor'         => array( 'class' => 'Noesia_CS_Ecommerce_Doctor_Module', 'view' => 'modules/ecommerce-doctor/views/admin.php' ),
			'emails'                   => array( 'class' => 'Noesia_CS_Emails_Module', 'view' => 'modules/emails/views/admin.php' ),
			'settings'                 => array( 'class' => 'Noesia_CS_Settings_Module', 'view' => 'modules/settings/views/admin.php' ),
		);
	}

	/**
	 * Build a full architecture boundary report.
	 *
	 * @param mixed $container Container instance.
	 * @param mixed $registry  Module registry.
	 * @return array
	 */
	public function get_report( $container = null, $registry = null ) {
		$services  = $this->audit_services( $container );
		$modules   = $this->audit_modules( $registry );
		$totals   = array(
			'services_expected'  => count( $services ),
			'services_ok'        => 0,
			'services_warning'   => 0,
			'modules_expected'   => count( $modules ),
			'modules_ok'         => 0,
			'modules_warning'    => 0,
		);

		foreach ( $services as $service ) {
			if ( 'ok' === $service['status'] ) {
				$totals['services_ok']++;
			} else {
				$totals['services_warning']++;
			}
		}

		foreach ( $modules as $module ) {
			if ( 'ok' === $module['status'] ) {
				$totals['modules_ok']++;
			} else {
				$totals['modules_warning']++;
			}
		}

		return array(
			'totals'    => $totals,
			'services'  => $services,
			'modules'   => $modules,
		);
	}

	/**
	 * Audit expected services in the container.
	 *
	 * @param mixed $container Container instance.
	 * @return array
	 */
	private function audit_services( $container = null ) {
		$rows      = array();
		$expected  = $this->expected_services();

		foreach ( $expected as $key => $definition ) {
			$instance              = ( $container && method_exists( $container, 'get' ) ) ? $container->get( $key ) : null;
			$missing_dependencies  = array();
			foreach ( $definition['depends_on'] as $dependency_key ) {
				if ( ! $container || ! method_exists( $container, 'has' ) || ! $container->has( $dependency_key ) ) {
					$missing_dependencies[] = $dependency_key;
				}
			}

			$class_ok     = class_exists( $definition['class'] );
			$instance_ok  = $instance && is_object( $instance ) && is_a( $instance, $definition['class'] );
			$status       = ( $class_ok && $instance_ok && empty( $missing_dependencies ) ) ? 'ok' : 'warning';
			$message      = __( 'Registered and isolated through the container.', 'noesia-commerce-suite' );

			if ( ! $class_ok ) {
				$message = __( 'Class is not loaded.', 'noesia-commerce-suite' );
			} elseif ( ! $instance_ok ) {
				$message = __( 'Container instance is missing or has an unexpected type.', 'noesia-commerce-suite' );
			} elseif ( ! empty( $missing_dependencies ) ) {
				$message = sprintf(
					/* translators: %s: missing dependency keys. */
					esc_html__( 'Missing dependency: %s', 'noesia-commerce-suite' ),
					implode( ', ', array_map( 'sanitize_key', $missing_dependencies ) )
				);
			}

			$rows[] = array(
				'key'         => $key,
				'label'       => $definition['label'],
				'class'       => $definition['class'],
				'type'        => $definition['type'],
				'role'        => $definition['role'],
				'depends_on'  => $definition['depends_on'],
				'status'      => $status,
				'message'     => $message,
			);
		}

		return $rows;
	}

	/**
	 * Audit registered admin modules and view isolation.
	 *
	 * @param mixed $registry Module registry.
	 * @return array
	 */
	private function audit_modules( $registry = null ) {
		$rows      = array();
		$expected  = $this->expected_modules();

		foreach ( $expected as $key => $definition ) {
			$module      = ( $registry && method_exists( $registry, 'get' ) ) ? $registry->get( $key ) : null;
			$class_ok    = class_exists( $definition['class'] );
			$view_path   = NOESIA_CS_PATH . $definition['view'];
			$view_ok     = file_exists( $view_path );
			$registered  = $module && is_object( $module );
			$status      = ( $class_ok && $view_ok && $registered ) ? 'ok' : 'warning';
			$message     = __( 'Controller and view are registered.', 'noesia-commerce-suite' );

			if ( ! $class_ok ) {
				$message = __( 'Module controller class is not loaded.', 'noesia-commerce-suite' );
			} elseif ( ! $registered ) {
				$message = __( 'Module is not registered in the module registry.', 'noesia-commerce-suite' );
			} elseif ( ! $view_ok ) {
				$message = __( 'Module view is missing; fallback output will be used.', 'noesia-commerce-suite' );
			}

			$rows[] = array(
				'key'      => $key,
				'label'    => $registered && method_exists( $module, 'label' ) ? $module->label() : ucwords( str_replace( '-', ' ', $key ) ),
				'class'    => $definition['class'],
				'view'     => $definition['view'],
				'status'   => $status,
				'message'  => $message,
			);
		}

		return $rows;
	}
}
