import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/account.dart';

class UserDirectoryProvider {
  late final SnNetworkProvider _sn;

  UserDirectoryProvider(BuildContext context) {
    _sn = context.read<SnNetworkProvider>();
  }

  final Map<String, int> _idCache = {};
  final Map<int, SnAccount> _cache = {};

  Future<List<SnAccount?>> listAccount(Iterable<dynamic> id) async {
    final out = List<SnAccount?>.generate(id.length, (e) => null);
    final plannedQuery = <int>{};
    for (var idx = 0; idx < out.length; idx++) {
      var item = id.elementAt(idx);
      if (item is String && _idCache.containsKey(item)) {
        item = _idCache[item];
      }
      if (_cache.containsKey(item)) {
        out[idx] = _cache[item];
      } else {
        plannedQuery.add(item);
      }
    }
    final resp = await _sn.client.get('/cgi/id/users', queryParameters: {'id': plannedQuery.join(',')});
    final respDecoded = resp.data.map((e) => SnAccount.fromJson(e)).cast<SnAccount>().toList();
    var sideIdx = 0;
    for (var idx = 0; idx < out.length; idx++) {
      if (out[idx] != null) continue;
      if (respDecoded.length <= sideIdx) {
        break;
      }
      out[idx] = respDecoded[sideIdx];
      _cache[respDecoded[sideIdx].id] = out[idx]!;
      _idCache[respDecoded[sideIdx].name] = respDecoded[sideIdx].id;
      sideIdx++;
    }
    return out;
  }

  Future<SnAccount?> getAccount(dynamic id) async {
    if (id is String && _idCache.containsKey(id)) {
      id = _idCache[id];
    }
    if (_cache.containsKey(id)) {
      return _cache[id];
    }

    try {
      final resp = await _sn.client.get('/cgi/id/users/$id');
      final account = SnAccount.fromJson(
        resp.data as Map<String, dynamic>,
      );
      _cache[account.id] = account;
      if (id is String) _idCache[id] = account.id;
      return account;
    } catch (err) {
      return null;
    }
  }

  SnAccount? getAccountFromCache(dynamic id) {
    if (id is String && _idCache.containsKey(id)) {
      id = _idCache[id];
    }
    return _cache[id];
  }
}