/// Provider: Product Filter Options Provider
///
/// Merges data from 3 APIs (groups, brands, attributes) for product filtering.
library;

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:worker/features/products/presentation/providers/products_provider.dart';

part 'product_filter_options_provider.g.dart';

/// Filter Options Data Model
///
/// Combines all filter options from the 3 APIs
class ProductFilterOptions {
  const ProductFilterOptions({
    required this.groups,
    required this.brands,
    required this.attributeGroups,
  });

  /// Product groups (Item Groups)
  final List<FilterOption> groups;

  /// Product brands
  final List<FilterOption> brands;

  /// Product attribute groups (Colour, Size, Surface, etc.)
  /// Each group contains a list of attribute values
  final List<AttributeGroup> attributeGroups;
}

/// Attribute Group Model
///
/// Represents a group of attributes (e.g., Colour, Size, Surface)
/// with its associated values
class AttributeGroup {
  const AttributeGroup({
    required this.name,
    required this.attributeName,
    required this.values,
  });

  /// Internal name
  final String name;

  /// Display name
  final String attributeName;

  /// List of attribute values
  final List<AttributeValue> values;
}

/// Attribute Value Model
///
/// Represents a single attribute value within a group
class AttributeValue {
  const AttributeValue({
    required this.name,
    required this.attributeValue,
    this.abbr,
  });

  /// Internal name/ID
  final String name;

  /// Display value
  final String attributeValue;

  /// Abbreviation (optional)
  final String? abbr;
}

/// Filter Option Model
///
/// Represents a single filter option with value and label
class FilterOption {
  const FilterOption({
    required this.value,
    required this.label,
  });

  final String value;
  final String label;
}

/// Product Filter Options Provider
///
/// Fetches and combines data from 3 Frappe APIs:
/// 1. Product Groups (Item Groups)
/// 2. Product Brands
/// 3. Product Attributes
///
/// Memory footprint: ~5-15 KB (negligible)
/// Cache strategy: Keep alive for session duration
///
/// Usage:
/// ```dart
/// final filterOptionsAsync = ref.watch(productFilterOptionsProvider);
///
/// filterOptionsAsync.when(
///   data: (options) => ProductFilterDrawer(options: options),
///   loading: () => const CustomLoadingIndicator(),
///   error: (error, stack) => ErrorWidget(error),
/// );
/// ```
@Riverpod(keepAlive: true)
Future<ProductFilterOptions> productFilterOptions(Ref ref) async {
  try {
    // Get remote datasource
    final remoteDataSource = await ref.watch(productsRemoteDataSourceProvider.future);

    // Fetch all 3 APIs in parallel
    final results = await Future.wait([
      remoteDataSource.getProductGroups(),
      remoteDataSource.getProductBrands(),
      remoteDataSource.getProductAttributes(),
    ]);

    final groupsData = results[0] as List<Map<String, dynamic>>;
    final brandsData = results[1] as List<String>;
    final attributesData = results[2] as List<Map<String, dynamic>>;

    // Convert groups to FilterOption
    final groups = groupsData
        .map((group) => FilterOption(
              value: group['name'] as String,
              label: group['item_group_name'] as String? ?? group['name'] as String,
            ))
        .toList();

    // Convert brands to FilterOption
    final brands = brandsData
        .map((brand) => FilterOption(
              value: brand,
              label: brand,
            ))
        .toList();

    // Convert attributes to AttributeGroup
    // Each attribute has: name, attribute_name, and values list
    final attributeGroups = attributesData.map((attr) {
      final valuesList = attr['values'] as List? ?? [];

      final values = valuesList.map((val) {
        return AttributeValue(
          name: val['name'] as String,
          attributeValue: val['attribute_value'] as String,
          abbr: val['abbr'] as String?,
        );
      }).toList();

      return AttributeGroup(
        name: attr['name'] as String,
        attributeName: attr['attribute_name'] as String? ?? attr['name'] as String,
        values: values,
      );
    }).toList();

    return ProductFilterOptions(
      groups: groups,
      brands: brands,
      attributeGroups: attributeGroups,
    );
  } catch (e) {
    print('[ProductFilterOptionsProvider] Error fetching filter options: $e');
    rethrow;
  }
}
