Example Function Usage

/// 
/// This file demonstrates how to use the refactored AppFunction
/// with Either pattern for type-safe error handling.

import 'package:flutter/foundation.dart';
import 'package:services/function/search/search_function.dart';
import 'package:store/function/schema/error_schema.dart';
import 'package:store/function/schema/search/search_response_schema.dart';
import 'package:store/function/shared/function/search_function_type.dart';
import 'package:store/function/shared/search/search_sort_type.dart';
import 'package:store/function/shared/stripe/stripe_account_type.dart';

/// Example 1: Search Function Usage
/// 
/// The search function now returns `Either<ErrorSchema, SearchResponseSchema>`
/// instead of nullable GeneralSearchResults
Future<void> exampleSearchUsage() async {
  // Create search function
  final searchFn = SearchFunction.general(
    searchType: SearchFunctionType.generalSearch,
    sortType: SearchSortType.recent,
  );

  // Execute search
  final result = await searchFn.search(
    queryStr: 'flutter',
    pageNum: 1,
  );

  // Handle result with fold
  result.fold(
    (error) {
      // Left: Error occurred
      debugPrint('Search failed:');
      debugPrint('  Code: ${error.code}');
      debugPrint('  Title: ${error.title}');
      debugPrint('  Message: ${error.message}');
      debugPrint('  Category: ${error.category}');
      
      // Check if retryable
      if (error.code.name == 'TIMEOUT' || error.code.name == 'SERVICE_UNAVAILABLE') {
        debugPrint('  → Error is retryable, will retry...');
      }
    },
    (data) {
      // Right: Success
      debugPrint('Search succeeded:');
      debugPrint('  Query: ${data.q}');
      debugPrint('  Found: ${data.found} results');
      debugPrint('  Page: ${data.page}/${data.outOf}');
      debugPrint('  Collection: ${data.collectionName}');
      debugPrint('  Results: ${data.results.length} items');
      
      // Process results
      for (final result in data.results) {
        print('    - ${result['title']}');
      }
    },
  );

  // Alternative: Check type explicitly
  if (result.isLeft()) {
    final error = result.fold((e) => e, (_) => null)!;
    handleError(error);
  } else {
    final data = result.fold((_) => null, (d) => d)!;
    handleSearchResults(data);
  }

  // Alternative: Use pattern matching (Dart 3.0+)
  switch (result) {
    case Left(value: final error):
      debugPrint('Error: ${error.message}');
    case Right(value: final data):
      debugPrint('Success: ${data.found} results');
  }
}

/// Example 2: Stripe Function Usage
/// 
/// Demonstrates how to use typed Stripe functions with Either pattern
Future<void> exampleStripeUsage() async {
  final stripeFunction = StripeRefreshAccountFunction();

  final result = await stripeFunction.refresh(
    uid: 'user_123',
    stripeAccountId: 'acct_stripe123',
    accountType: StripeAccountType.express,
  );

  result.fold(
    (error) {
      // Handle different error types
      if (error.category.name == 'stripe') {
        debugPrint('Stripe-specific error: ${error.message}');
        // Maybe redirect to account setup
      } else if (error.code.name == 'unauthenticated') {
        debugPrint('User needs to login again');
        // Redirect to login
      } else {
        debugPrint('Generic error: ${error.message}');
      }
    },
    (data) {
      debugPrint('Stripe account refreshed successfully');
      // Update UI with new account data
    },
  );
}

/// Example 3: Error-first handling
/// 
/// Shows how to handle errors first and early-return
Future<List<Map<String, dynamic>>> exampleErrorFirstHandling(String query) async {
  final searchFn = SearchFunction.general(
    searchType: SearchFunctionType.generalSearch,
    sortType: SearchSortType.recent,
  );

  final result = await searchFn.search(queryStr: query);

  // Handle error case first
  if (result.isLeft()) {
    final error = result.getLeft().toNullable()!;
    print('Search error: ${error.message}');
    return []; // Return empty list on error
  }

  // Success case
  final data = result.getRight().toNullable()!;
  return data.results;
}

/// Example 4: Chaining operations with Either
/// 
/// Shows how to chain multiple function calls
Future<void> exampleChainingOperations() async {
  // Search for dares
  final searchResult = await SearchFunction.general(
    searchType: SearchFunctionType.generalSearch,
    sortType: SearchSortType.recent,
  ).search(queryStr: 'test');

  // Chain: only proceed if search succeeded
  final processingResult = searchResult.flatMap((searchData) async {
    // Process search results...
    if (searchData.results.isEmpty) {
      return Either.left(ErrorSchema(
        endpoint: 'processing',
        code: AppErrorCode.serverError,
        category: AppErrorCategory.processing,
        title: 'No Results',
        message: 'No search results to process',
      ));
    }

    // Do something with results...
    return Either.right('Processed ${searchData.results.length} items');
  });

  // Handle final result
  processingResult.fold(
    (error) => debugPrint('Failed: ${error.message}'),
    (success) => debugPrint('Success: $success'),
  );
}

/// Example 5: Async error recovery
/// 
/// Shows how to recover from errors with fallback logic
Future<void> exampleErrorRecovery() async {
  final searchFn = SearchFunction.general(
    searchType: SearchFunctionType.generalSearch,
    sortType: SearchSortType.recent,
  );

  final result = await searchFn.search(queryStr: 'test');

  final finalResult = result.fold(
    (error) async {
      // Try to recover from error
      if (error.code.name == 'timeout') {
        debugPrint('Timeout detected, retrying with longer timeout...');
        // Retry logic here
        return <Map<String, dynamic>>[];
      }
      debugPrint('Unrecoverable error: ${error.message}');
      return <Map<String, dynamic>>[];
    },
    (data) async => data.results,
  );

  debugPrint('Final result: ${await finalResult}');
}

// Helper functions for examples
void handleError(ErrorSchema error) {
  debugPrint('Handling error: ${error.message}');
}

void handleSearchResults(SearchResponseSchema data) {
  debugPrint('Handling ${data.results.length} results');
}

// Needed imports that would be in actual usage:
// import 'package:store/function/schema/error_schema.dart';
// import 'package:store/function/schema/search/search_response_schema.dart';
// import 'package:store/function/shared/app_error_code.dart';
// import 'package:store/function/shared/app_error_category.dart';