import 'package:flutter/material.dart';

import 'package:pshared/provider/organizations.dart';
import 'package:pshared/provider/resource.dart';
import 'package:pshared/utils/exception.dart';

import 'package:pweb/models/wallet.dart';
import 'package:pweb/services/wallets.dart';


class WalletsProvider with ChangeNotifier {
  final WalletsService _service;
  late OrganizationsProvider _organizations;

  WalletsProvider(this._service);

  Resource<List<Wallet>> _resource = Resource(data: []);
  Resource<List<Wallet>> get resource => _resource;

  List<Wallet> get wallets => _resource.data ?? [];
  bool get isLoading => _resource.isLoading;
  Exception? get error => _resource.error;

  Wallet? _selectedWallet;
  Wallet? get selectedWallet => _selectedWallet;
  final bool _isHidden = true;
  bool get isHidden => _isHidden;

  bool _isRefreshingBalances = false;
  bool get isRefreshingBalances => _isRefreshingBalances;

  void update(OrganizationsProvider organizations) {
    _organizations = organizations;
    if (_organizations.isOrganizationSet) loadWalletsWithBalances();
  }

  Future<Wallet> updateWallet(Wallet newWallet) {
    throw Exception('update wallet is not implemented');
  }

  void selectWallet(Wallet wallet) {
    _selectedWallet = wallet;
    notifyListeners();
  }

  Future<void> loadWalletsWithBalances() async {
    _setResource(_resource.copyWith(isLoading: true, error: null));
    try {
      final base = await _service.getWallets(_organizations.current.id);
      final withBalances = <Wallet>[];
      for (final wallet in base) {
        try {
          final balance = await _service.getBalance(_organizations.current.id, wallet.id);
          withBalances.add(wallet.copyWith(balance: balance));
        } catch (e) {
          _setResource(_resource.copyWith(error: toException(e)));
          withBalances.add(wallet);
        }
      }
      _setResource(Resource(data: withBalances, isLoading: false, error: _resource.error));
    } catch (e) {
      _setResource(_resource.copyWith(isLoading: false, error: toException(e)));
    }
  }

  Future<void> refreshBalances() async {
    if (wallets.isEmpty) return;
    _isRefreshingBalances = true;
    notifyListeners();

    try {
      final updated = <Wallet>[];
      for (final wallet in wallets) {
        final balance = await _service.getBalance(_organizations.current.id, wallet.id);
        updated.add(wallet.copyWith(balance: balance));
      }
      _setResource(_resource.copyWith(data: updated));
    } catch (e) {
      _setResource(_resource.copyWith(error: toException(e)));
    } finally {
      _isRefreshingBalances = false;
      notifyListeners();
    }
  }

  void toggleVisibility(String walletId) {
    final index = wallets.indexWhere((w) => w.id == walletId);
    if (index < 0) return;
    final wallet = wallets[index];
    final updated = wallet.copyWith(isHidden: !wallet.isHidden);
    final next = List<Wallet>.from(wallets);
    next[index] = updated;
    _setResource(_resource.copyWith(data: next));
    if (_selectedWallet?.id == walletId) {
      _selectedWallet = updated;
    }
  }

  void _setResource(Resource<List<Wallet>> newResource) {
    _resource = newResource;
    notifyListeners();
  }
}
