import 'dart:async';
import 'dart:io';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/pickup.dart';
import 'package:fcs/helpers/firebase_helper.dart';
import 'package:fcs/pages/main/model/base_model.dart';
import 'package:fcs/pagination/paginator_listener.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as Path;

class PickupModel extends BaseModel {
  final log = Logger('PickupModel');

  PaginatorListener<Pickup>? pickups;

  void initUser(user) {
    super.initUser(user);
  }

  void privilegeChanged() {
    if (user != null) {
      _initData();
    }
  }

  Future<void> _initData() async {
    logout();
    pickups = PaginatorListener<Pickup>((data, id) => Pickup.fromMap(data, id),
        onChange: () {
      notifyListeners();
    }, rowPerLoad: 30, insertNewByListener: true);
    _loadPickups();
  }

  @override
  logout() async {
    if (pickups != null) pickups!.close();
  }

  Future<void> _loadPickups() async {
    if (user == null) return;
    String path = "/$pickup_collection";

    try {
      Query listenerQuery = FirebaseFirestore.instance.collection(path);
      Query pageQuery = FirebaseFirestore.instance
          .collection(path)
          .orderBy("update_time", descending: true);

      pickups!.refresh(listeningQuery: listenerQuery, pageQuery: pageQuery);
    } catch (e) {
      log.warning("Error!! $e");
    }
  }

  Future<void> complete(
      Pickup pickup, List<File?> files, List<String?> deletedUrls) async {
    for (String? url in deletedUrls) {
      pickup.photoUrls.remove(url);
    }

    // check files count
    var count = (pickup.photoUrls.length) + files.length - (deletedUrls.length);
    if (count > uploadPhotoLimit)
      throw Exception("Exceed number of file upload");

    List<String> uploadedURLs = [];
    String path = Path.join(pickups_files_path, pickup.id);
    uploadedURLs = await uploadFiles(path, files);
    pickup.photoUrls.addAll(uploadedURLs);
    pickup.photoUrls.removeWhere((e) => deletedUrls.contains(e));

    try {
      await Services.instance.pickupService.completePickup(pickup);
    } catch (e) {
      // delete newly uploaded photos if fails
      try {
        deleteStorageFromUrls(uploadedURLs);
        pickup.photoUrls.removeWhere((i) => uploadedURLs.contains(i));
      } catch (e) {}
      throw e;
    }
    return deleteStorageFromUrls(deletedUrls);
  }

  Future<Pickup?> getPickup(String id) async {
    if (user == null) return null;
    String path = "/$pickup_collection";
    try {
      DocumentSnapshot snap =
          await FirebaseFirestore.instance.collection("$path").doc(id).get();
      if (snap.exists) {
        var package =
            Pickup.fromMap(snap.data() as Map<String, dynamic>, snap.id);
        return package;
      }
    } catch (e) {
      log.warning("Error!! $e");
    }
    return null;
  }

  Future<List<Pickup>> searchPickup(String term) async {
    Future<List<Pickup>> pickups =
        Services.instance.pickupService.searchPickup(term);
    return pickups;
  }
}
