import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:uuid/uuid.dart';

import '../models/payment_card_model.dart';

class PaymentCardProvider extends ChangeNotifier {
  late Box<PaymentCardModel> _cardBox;
  final List<PaymentCardModel> _cards = [];

  List<PaymentCardModel> get cards => List.unmodifiable(_cards);

  PaymentCardModel? get defaultCard {
    try {
      return _cards.firstWhere((card) => card.isDefault);
    } catch (_) {
      return _cards.isNotEmpty ? _cards.first : null;
    }
  }

  Future<void> init() async {
    _cardBox = await Hive.openBox<PaymentCardModel>('payment_cards');
    _cards
      ..clear()
      ..addAll(_cardBox.values);
    _sortCards();
    notifyListeners();
  }

  Future<PaymentCardModel> addCard({
    required String issuerName,
    required String last4,
    required String colorHex,
    required String iconName,
    bool isDefault = false,
  }) async {
    if (isDefault) {
      await _unsetDefaultCard();
    }

    final card = PaymentCardModel(
      id: const Uuid().v4(),
      issuerName: issuerName,
      last4: last4,
      colorHex: colorHex,
      iconName: iconName,
      isDefault: isDefault,
    );

    await _cardBox.put(card.id, card);
    _cards.add(card);
    _sortCards();
    notifyListeners();
    return card;
  }

  Future<void> updateCard(PaymentCardModel updated) async {
    final index = _cards.indexWhere((card) => card.id == updated.id);
    if (index == -1) return;

    if (updated.isDefault) {
      await _unsetDefaultCard(exceptId: updated.id);
    }

    _cards[index] = updated;
    await _cardBox.put(updated.id, updated);
    _sortCards();
    notifyListeners();
  }

  Future<void> deleteCard(String id) async {
    await _cardBox.delete(id);
    _cards.removeWhere((card) => card.id == id);

    if (!_cards.any((card) => card.isDefault) && _cards.isNotEmpty) {
      _cards.first.isDefault = true;
      await _cardBox.put(_cards.first.id, _cards.first);
    }

    _sortCards();
    notifyListeners();
  }

  Future<void> setDefaultCard(String id) async {
    final index = _cards.indexWhere((card) => card.id == id);
    if (index == -1) return;

    await _unsetDefaultCard(exceptId: id);
    _cards[index].isDefault = true;
    await _cardBox.put(id, _cards[index]);
    _sortCards();
    notifyListeners();
  }

  PaymentCardModel? getCardById(String? id) {
    if (id == null) return null;
    try {
      return _cards.firstWhere((card) => card.id == id);
    } catch (_) {
      return null;
    }
  }

  void _sortCards() {
    _cards.sort((a, b) {
      if (a.isDefault != b.isDefault) {
        return a.isDefault ? -1 : 1;
      }
      final issuerCompare =
          a.issuerName.toLowerCase().compareTo(b.issuerName.toLowerCase());
      if (issuerCompare != 0) return issuerCompare;
      return a.last4.compareTo(b.last4);
    });
  }

  Future<void> _unsetDefaultCard({String? exceptId}) async {
    for (final card in _cards) {
      if (card.isDefault && card.id != exceptId) {
        card.isDefault = false;
        await _cardBox.put(card.id, card);
      }
    }
  }
}
