// coverage:ignore-file
// ๐Ÿ“„ PAGE STATE TEMPLATE: Standardized Riverpod page state management pattern
//
// This template provides a consistent approach for managing page-specific state
// with automatic persistence using SharedPreferences. Unlike services that manage
// business logic, page state providers focus on UI state preservation.
//
// Key Features:
// โœ… Automatic state persistence and restoration
// โœ… Standardized naming conventions
// โœ… Convenience providers for easy access
// โœ… Utility methods for common operations
// โœ… Error handling with graceful fallbacks
// โœ… Testing support with provider overrides

import 'package:presentation/_prelude.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'dart:convert';

part '_page_state_template.g.dart';

// =============================================================================
// ๐ŸŽฏ TEMPLATE: Replace 'PageName' with your actual page name (e.g., 'Home', 'Stripe')
// ๐ŸŽฏ TEMPLATE: Replace 'PageState' with your actual state class (e.g., 'FilterState', 'StripeOnboardStartState')
// =============================================================================

/// ๐Ÿ† SHARED PREFERENCES PROVIDER
/// Provides access to SharedPreferences for persistence
@riverpod
SharedPreferences sharedPreferences(Ref ref) {
  final prefs = ScreenTemplateState.sharedPreferences;
  if (prefs == null) {
    throw StateError(
      'SharedPreferences not yet initialized. Make sure you navigate to a screen that extends ScreenTemplate first.',
    );
  }
  return prefs;
}

/// ๐Ÿ”„ PERSISTENCE SERVICE: Handles saving/loading page state
@riverpod
PageNamePersistenceService pageNamePersistenceService(Ref ref) {
  final prefs = ref.watch(sharedPreferencesProvider);
  return PageNamePersistenceService(prefs);
}

/// ๐Ÿ“ฆ PERSISTENCE SERVICE CLASS
class PageNamePersistenceService {
  final SharedPreferences _prefs;
  static const String _pageStateKey = 'page_name_state';
  static const String _allStatesKey = 'all_page_states';

  PageNamePersistenceService(this._prefs);

  /// Save page state to persistent storage
  Future<void> savePageState(PageState pageState) async {
    try {
      final json = pageState.toJson(); // Assumes your state has toJson()
      await _prefs.setString(_pageStateKey, jsonEncode(json));

      // Track this key for bulk clearing
      final allStates = _prefs.getStringList(_allStatesKey) ?? [];
      if (!allStates.contains(_pageStateKey)) {
        allStates.add(_pageStateKey);
        await _prefs.setStringList(_allStatesKey, allStates);
      }
    } catch (e) {
      LOG.e('Failed to save page state: $e');
      // Don't rethrow - persistence failure shouldn't break the app
    }
  }

  /// Load page state from persistent storage
  PageState? loadPageState() {
    try {
      final jsonString = _prefs.getString(_pageStateKey);
      if (jsonString != null) {
        final json = jsonDecode(jsonString) as Map<String, dynamic>;
        return PageState.fromJson(json); // Assumes your state has fromJson()
      }
    } catch (e) {
      LOG.e('Failed to load page state: $e');
      // Return null to use default state
    }
    return null;
  }

  /// Clear persisted page state
  Future<void> clearPageState() async {
    try {
      await _prefs.remove(_pageStateKey);
    } catch (e) {
      LOG.e('Failed to clear page state: $e');
    }
  }

  /// Clear all persisted page states
  Future<void> clearAllPersistedStates() async {
    try {
      final allStates = _prefs.getStringList(_allStatesKey) ?? [];
      for (final key in allStates) {
        await _prefs.remove(key);
      }
      await _prefs.remove(_allStatesKey);
    } catch (e) {
      LOG.e('Failed to clear all page states: $e');
    }
  }
}

/// ๐Ÿš€ PAGE STATE SERVICE: Main state management with persistence
@riverpod
class PageNameStateService extends _$PageNameStateService {
  PageNamePersistenceService? _persistenceService;

  @override
  PageState build() {
    _persistenceService ??= ref.read(pageNamePersistenceServiceProvider);

    // Try to load persisted state
    try {
      final persistedState = _persistenceService!.loadPageState();
      if (persistedState != null) {
        LOG.i('Loaded persisted page state');
        return persistedState;
      }
    } catch (e) {
      LOG.e('Failed to load persisted page state: $e');
    }

    // Return default state
    LOG.i('Using default page state');
    return PageState.defaultState(); // Define this in your state class
  }

  // =============================================================================
  // ๐ŸŽฏ STANDARDIZED UTILITY METHODS
  // =============================================================================

  /// Update the entire page state and persist it
  Future<void> updateState(PageState newState) async {
    state = newState;
    await _persistState();
  }

  /// Reset to default state and persist
  Future<void> resetToDefault() async {
    final defaultState = PageState.defaultState();
    await updateState(defaultState);
  }

  /// Clear error state (if your state has error handling)
  void clearError() {
    // Implement based on your state structure
    // state = state.copyWith(error: null);
  }

  /// Refresh/reload state data
  Future<void> refresh() async {
    // Implement refresh logic based on your needs
    // This might reload from persistence or reset to default
    await resetToDefault();
  }

  /// Reset to initial state without persistence
  void reset() {
    state = PageState.defaultState();
  }

  // =============================================================================
  // ๐Ÿ”ง PRIVATE HELPER METHODS
  // =============================================================================

  /// Persist current state
  Future<void> _persistState() async {
    try {
      await _persistenceService?.savePageState(state);
    } catch (e) {
      LOG.e('Failed to persist page state: $e');
      // Don't rethrow - persistence failure shouldn't break the app
    }
  }

  /// Check if state has been modified from default
  bool get isModified {
    final defaultState = PageState.defaultState();
    return !_areStatesEqual(state, defaultState);
  }

  /// Compare two states for equality
  bool _areStatesEqual(PageState state1, PageState state2) {
    // Implement based on your state structure
    // This might use == operator or custom comparison logic
    return state1 == state2;
  }
}

// =============================================================================
// ๐ŸŽฏ CONVENIENCE PROVIDERS: Easy access to specific state aspects
// =============================================================================

/// Check if page state is loading (if applicable)
@riverpod
bool pageNameIsLoading(Ref ref) {
  final state = ref.watch(pageNameStateServiceProvider);
  // Implement based on your state structure
  // return state.isLoading ?? false;
  return false; // Default implementation
}

/// Get current error state (if applicable)
@riverpod
String? pageNameError(Ref ref) {
  final state = ref.watch(pageNameStateServiceProvider);
  // Implement based on your state structure
  // return state.error;
  return null; // Default implementation
}

/// Check if state has been modified from default
@riverpod
bool pageNameIsModified(Ref ref) {
  final notifier = ref.watch(pageNameStateServiceProvider.notifier);
  return notifier.isModified;
}

/// Get specific data from state (customize based on your needs)
@riverpod
DataType? pageNameSpecificData(Ref ref) {
  final state = ref.watch(pageNameStateServiceProvider);
  // return state.specificField;
  return null; // Implement based on your state structure
}

// =============================================================================
// ๐Ÿงน CACHE MANAGEMENT: For clearing persisted page states
// =============================================================================

/// Page cache manager for clearing persisted data
@riverpod
class PageNameCacheManager extends _$PageNameCacheManager {
  @override
  void build() {
    // Service provider - no state needed
  }

  /// Clear all page state cache
  Future<void> clearAllPageCache() async {
    try {
      final persistenceService = ref.read(pageNamePersistenceServiceProvider);
      await persistenceService.clearAllPersistedStates();

      // Reset the page state provider
      ref.invalidate(pageNameStateServiceProvider);

      LOG.i('Cleared all page cache');
    } catch (e) {
      LOG.e('Error clearing page cache: $e');
      rethrow;
    }
  }

  /// Clear only this page's cache
  Future<void> clearPageCache() async {
    try {
      final persistenceService = ref.read(pageNamePersistenceServiceProvider);
      await persistenceService.clearPageState();

      // Reset the page state provider
      ref.invalidate(pageNameStateServiceProvider);

      LOG.i('Cleared page cache');
    } catch (e) {
      LOG.e('Error clearing page cache: $e');
      rethrow;
    }
  }
}

// =============================================================================
// ๐ŸŽฏ USAGE EXAMPLES AND DOCUMENTATION
// =============================================================================


// USAGE IN WIDGETS:

class MyPageWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Watch the entire state
    final pageState = ref.watch(pageNameStateServiceProvider);
    
    // Watch specific aspects
    final isLoading = ref.watch(pageNameIsLoadingProvider);
    final error = ref.watch(pageNameErrorProvider);
    final isModified = ref.watch(pageNameIsModifiedProvider);
    
    // Update state
    if (someCondition) {
      ref.read(pageNameStateServiceProvider.notifier).updateState(newState);
    }
    
    return YourWidgetTree();
  }
}

// TESTING:

testWidgets('page state test', (tester) async {
  await tester.pumpWidget(
    ProviderScope(
      overrides: [
        pageNameStateServiceProvider.overrideWith(() => MockPageStateService()),
      ],
      child: MyApp(),
    ),
  );
  
  expect(container.read(pageNameIsModifiedProvider), false);
  // ... rest of test
});

// MIGRATION FROM HYDRATED_BLOC:
// 
// Before:
// - class MyPageCubit extends HydratedCubit<MyPageState>
// - context.read<MyPageCubit>().updateState(newState)
// - BlocBuilder<MyPageCubit, MyPageState>
// 
// After:
// - @riverpod class MyPageStateService extends _$MyPageStateService
// - ref.read(myPageStateServiceProvider.notifier).updateState(newState)
// - Consumer(builder: (context, ref, child) { final state = ref.watch(...) })