import 'dart:async';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:niogu_app/core/enums/approval_process.dart';
import 'package:niogu_app/core/enums/canceled_by.dart';
import 'package:niogu_app/core/enums/order_status.dart';
import 'package:niogu_app/features/online_store/domain/entities/online_store.dart';
import 'package:niogu_app/features/online_store/domain/repositories/i_online_store_repository.dart';
import 'package:niogu_app/features/online_store/presentation/providers/online_store_provider.dart';

class OnlineStoreController extends AutoDisposeAsyncNotifier<void> {
  late final IOnlineStoreRepository _onlineStoreRepository;

  @override
  FutureOr<void> build() {
    _onlineStoreRepository = ref.read(onlineStoreRepositoryProvider);
  }

  Future<void> updateAlreadyReadOrderOnline(String orderId) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.updateAlreadyOrderOnline(orderId);
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> configureOnlineStore(ConfigureOnlineStore configure) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.configureOnlineStore(configure);
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> updateOrder({
    required String orderId,
    required OrderStatus orderStatus,
    bool cancellationAccepted = false,
    ApprovalProcess? process,
    CanceledBy? canceledBy,
  }) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.updateOrder(
        orderId: orderId,
        orderStatus: orderStatus,
        cancellationAccepted: cancellationAccepted,
        process: process,
        canceledBy: canceledBy,
      );
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> shippingConfiguration(ShippingConfiguration configure) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.shippingConfiguration(configure);
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> paymentMethodConfiguration(
    List<ConfigurePaymentMethod> configures,
  ) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.paymentMethodConfiguration(configures);
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> ratingConfiguration(RatingConfiguration configuration) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.ratingConfiguration(configuration);
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> saveCampaign({
    required UpsertCampaign campaign,
    List<String>? deleteTargetOutlets,
  }) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.saveCampaign(
        campaign: campaign,
        deleteTargetOutlets: deleteTargetOutlets,
      );
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }

  Future<void> deleteCampaign(String campaignId) async {
    state = const AsyncValue.loading();

    final result = await AsyncValue.guard(() async {
      await _onlineStoreRepository.deleteCampaign(campaignId);
    });

    state = result;

    if (result is AsyncError) throw result.error!;
  }
}

class SelectedTargetOutletController
    extends StateNotifier<Map<String, SelectedTargetOutlet>> {
  SelectedTargetOutletController() : super({});

  void hydrate(List<SelectedTargetOutlet> oldData) {
    state = {for (final data in oldData) data.outletId: data};
  }

  void toggleSelectAll(SelectedTargetOutlet outlet) {
    if (state.containsKey(outlet.outletId)) {
      state = {...state}
        ..remove(outlet.outletId)
        ..[outlet.outletId] = outlet;
    } else {
      state = {...state, outlet.outletId: outlet};
    }
  }

  void toggle(SelectedTargetOutlet outlet) {
    if (state.containsKey(outlet.outletId)) {
      state = {...state}..remove(outlet.outletId);
    } else {
      state = {...state, outlet.outletId: outlet};
    }
  }

  void clear() {
    state = {...state}..clear();
  }

  void restore(Map<String, SelectedTargetOutlet> inititalTargets) {
    state = Map.from(inititalTargets);
  }
}
