/// Shared [InheritedWidget] that exposes [KcAppServices] and [KcAppConfig]
/// to the widget tree.
///
/// Both `kell_web` and `kell_mobile` use this widget at the root of their
/// widget tree so that any descendant can retrieve services and configuration.
library;

import 'package:flutter/widgets.dart';

import 'kc_app_config.dart';
import 'kc_app_services.dart';

/// An [InheritedWidget] that exposes [KcAppServices] and [KcAppConfig] to the
/// widget tree.
///
/// Wrap the app (or a subtree) with [KcAppScope] and retrieve the services
/// anywhere below via [KcAppScope.of<T>(context)].
///
/// The type parameter [T] allows each app target to retrieve its concrete
/// services subclass without casting:
///
/// ```dart
/// // In kell_web:
/// final services = KcAppScope.of<WebAppServices>(context);
/// services.inventoryRepository; // ← strongly typed
/// ```
class KcAppScope<T extends KcAppServices> extends InheritedWidget {
  /// The concrete services for this app target.
  final T services;

  /// The effective runtime configuration.
  final KcAppConfig config;

  const KcAppScope({super.key, required this.services, required this.config, required super.child});

  /// Returns the nearest [T] (concrete services) from the widget tree.
  ///
  /// Throws if no [KcAppScope] ancestor is found.
  static T of<T extends KcAppServices>(BuildContext context) {
    final scope = context.dependOnInheritedWidgetOfExactType<KcAppScope<T>>();
    assert(scope != null, 'No KcAppScope<$T> found in the widget tree');
    return scope!.services;
  }

  /// Returns the nearest [KcAppConfig] from the widget tree.
  ///
  /// This is a convenience accessor that works regardless of the concrete
  /// services type — it looks for any [KcAppScope] with any type parameter.
  ///
  /// For apps that know their concrete type, prefer using the typed overload.
  static KcAppConfig configOf<T extends KcAppServices>(BuildContext context) {
    final scope = context.dependOnInheritedWidgetOfExactType<KcAppScope<T>>();
    assert(scope != null, 'No KcAppScope<$T> found in the widget tree');
    return scope!.config;
  }

  @override
  bool updateShouldNotify(KcAppScope<T> oldWidget) =>
      services != oldWidget.services || config != oldWidget.config;
}
