// ignore_for_file: use_build_context_synchronously

import 'dart:async';
import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart';
import '../../product/constant/app/app_constants.dart';

import '../../product/services/api_services.dart';
import '../../product/base/bloc/base_bloc.dart';
import '../../product/services/language_services.dart';
import '../../product/utils/response_status_utils.dart';
import 'groups/groups_model.dart';

class InterFamilyBloc extends BlocBase {
  APIServices apiServices = APIServices();

  final isLoading = StreamController<bool>.broadcast();
  StreamSink<bool> get sinkIsLoading => isLoading.sink;
  Stream<bool> get streamIsLoading => isLoading.stream;

  final titleScreen = StreamController<String>.broadcast();
  StreamSink<String> get sinkTitleScreen => titleScreen.sink;
  Stream<String> get streamTitleScreen => titleScreen.stream;

  final selectedScreen = StreamController<int>.broadcast();
  StreamSink<int> get sinkSelectedScreen => selectedScreen.sink;
  Stream<int> get streamSelectedScreen => selectedScreen.stream;

  final currentGroups = StreamController<List<Group>>.broadcast();
  StreamSink<List<Group>> get sinkCurrentGroups => currentGroups.sink;
  Stream<List<Group>> get streamCurrentGroups => currentGroups.stream;

  @override
  void dispose() {}

  void getAllGroup(String role) async {
    List<Group> groups = [];
    sinkCurrentGroups.add(groups);
    final body = await apiServices.getAllGroups();

    if (body.isNotEmpty) {
      final data = jsonDecode(body);
      List<dynamic> items = data["items"];
      groups = Group.fromJsonDynamicList(items);
      groups = sortGroupByName(groups);

      List<Group> currentGroups = groups.where(
        (group) {
          bool isPublic = group.visibility == "PUBLIC";

          if (role == ApplicationConstants.OWNER_GROUP) {
            return group.isOwner == true && isPublic;
          }

          if (role == ApplicationConstants.PARTICIPANT_GROUP) {
            return group.isOwner == null && isPublic;
          }

          return false;
        },
      ).toList();

      sinkCurrentGroups.add(currentGroups);
    } else {
      log("Get groups from API failed");
    }
    log("Inter Family Role: $role");
  }

  Future<void> createGroup(
      BuildContext context, String name, String description) async {
    APIServices apiServices = APIServices();
    Map<String, dynamic> body = {"name": name, "description": description};
    int? statusCode = await apiServices.createGroup(body);
    showSnackBarResponseByStatusCode(
        context,
        statusCode,
        appLocalization(context).notification_add_group_success,
        appLocalization(context).notification_add_group_failed);
  }

  Future<void> changeGroupInfomation(BuildContext context, String groupID,
      String name, String description) async {
    Map<String, dynamic> body = {"name": name, "description": description};
    int statusCode = await apiServices.updateGroup(body, groupID);
    showSnackBarResponseByStatusCode(
        context,
        statusCode,
        appLocalization(context).notification_update_group_success,
        appLocalization(context).notification_update_group_failed);
  }

  Future<void> joinGroup(BuildContext context, String groupID) async {
    Map<String, dynamic> body = {
      "group_id": groupID,
    };
    int statusCode = await apiServices.joinGroup(groupID, body);
    showSnackBarResponseByStatusCode(
        context,
        statusCode,
        appLocalization(context).notification_join_request_group_success,
        appLocalization(context).notification_join_request_group_failed);
  }

  Future<void> deleteGroup(BuildContext context, String groupID) async {
    int statusCode = await apiServices.deleteGroup(groupID);
    showSnackBarResponseByStatusCode(
        context,
        statusCode,
        appLocalization(context).notification_delete_group_success,
        appLocalization(context).notification_delete_group_failed);
  }

  List<Group> sortGroupByName(List<Group> groups) {
    return groups..sort((a, b) => (a.name ?? '').compareTo(b.name ?? ''));
  }
}
