import 'package:flutter/material.dart';

import '../l10n/app_localizations.dart';
import '../models/payment_card_model.dart';
import '../models/subscription_model.dart';
import '../providers/category_provider.dart';
import '../providers/payment_card_provider.dart';
import 'subscription_category_helper.dart';

enum SubscriptionGroupingMode { category, paymentCard }

class SubscriptionGroupData {
  final String id;
  final String title;
  final List<SubscriptionModel> subscriptions;
  final SubscriptionGroupingMode mode;
  final PaymentCardModel? paymentCard;
  final bool isUnassignedCard;
  final String? categoryKey;
  final String? subtitle;

  const SubscriptionGroupData({
    required this.id,
    required this.title,
    required this.subscriptions,
    required this.mode,
    this.paymentCard,
    this.isUnassignedCard = false,
    this.categoryKey,
    this.subtitle,
  });
}

class SubscriptionGroupingHelper {
  static const _unassignedCardKey = '__unassigned__';

  static List<SubscriptionGroupData> buildGroups({
    required BuildContext context,
    required List<SubscriptionModel> subscriptions,
    required SubscriptionGroupingMode mode,
    required CategoryProvider categoryProvider,
    required PaymentCardProvider paymentCardProvider,
  }) {
    if (mode == SubscriptionGroupingMode.paymentCard) {
      return _groupByPaymentCard(
        context: context,
        subscriptions: subscriptions,
        paymentCardProvider: paymentCardProvider,
      );
    }

    return _groupByCategory(
      context: context,
      subscriptions: subscriptions,
      categoryProvider: categoryProvider,
    );
  }

  static List<SubscriptionGroupData> _groupByCategory({
    required BuildContext context,
    required List<SubscriptionModel> subscriptions,
    required CategoryProvider categoryProvider,
  }) {
    final localizedMap = SubscriptionCategoryHelper.categorizeSubscriptions(
        subscriptions, categoryProvider, context);

    final orderMap = <String, int>{};
    for (var i = 0; i < categoryProvider.categories.length; i++) {
      orderMap[categoryProvider.categories[i].name] = i;
    }

    final groups = localizedMap.entries.map((entry) {
      final title =
          categoryProvider.getLocalizedCategoryName(context, entry.key);
      return SubscriptionGroupData(
        id: entry.key,
        title: title,
        subscriptions: entry.value,
        mode: SubscriptionGroupingMode.category,
        categoryKey: entry.key,
      );
    }).toList();

    groups.sort((a, b) {
      final ai = orderMap[a.categoryKey] ?? 999;
      final bi = orderMap[b.categoryKey] ?? 999;
      if (ai != bi) {
        return ai.compareTo(bi);
      }
      return a.title.compareTo(b.title);
    });

    return groups;
  }

  static List<SubscriptionGroupData> _groupByPaymentCard({
    required BuildContext context,
    required List<SubscriptionModel> subscriptions,
    required PaymentCardProvider paymentCardProvider,
  }) {
    final map = <String, List<SubscriptionModel>>{};

    for (final sub in subscriptions) {
      final key = sub.paymentCardId ?? _unassignedCardKey;
      map.putIfAbsent(key, () => []).add(sub);
    }

    final loc = AppLocalizations.of(context);
    final groups = <SubscriptionGroupData>[];

    map.forEach((key, subs) {
      if (key == _unassignedCardKey) {
        groups.add(
          SubscriptionGroupData(
            id: key,
            title: loc.paymentCardUnassigned,
            subtitle: loc.paymentCardUnassigned,
            subscriptions: subs,
            mode: SubscriptionGroupingMode.paymentCard,
            isUnassignedCard: true,
          ),
        );
      } else {
        final card = paymentCardProvider.getCardById(key);
        final title = card?.issuerName ?? loc.paymentCardUnassigned;
        final subtitle =
            card != null ? '****${card.last4}' : loc.paymentCardUnassigned;
        groups.add(
          SubscriptionGroupData(
            id: key,
            title: title,
            subtitle: subtitle,
            subscriptions: subs,
            mode: SubscriptionGroupingMode.paymentCard,
            paymentCard: card,
          ),
        );
      }
    });

    groups.sort((a, b) {
      if (a.isUnassignedCard != b.isUnassignedCard) {
        return a.isUnassignedCard ? 1 : -1;
      }
      final aDefault = a.paymentCard?.isDefault ?? false;
      final bDefault = b.paymentCard?.isDefault ?? false;
      if (aDefault != bDefault) {
        return aDefault ? -1 : 1;
      }
      return a.title.toLowerCase().compareTo(b.title.toLowerCase());
    });

    return groups;
  }
}
