import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
import 'package:enaklo_pos/data/datasources/order_remote_datasource.dart';
import 'package:enaklo_pos/data/models/response/customer_response_model.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart';
import 'package:enaklo_pos/data/models/response/payment_methods_response_model.dart';
import 'package:enaklo_pos/data/models/response/table_model.dart';
import 'package:enaklo_pos/presentation/home/models/order_request.dart';
import 'package:enaklo_pos/presentation/home/models/order_type.dart';
import 'package:enaklo_pos/presentation/home/models/product_quantity.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'order_form_event.dart';
part 'order_form_state.dart';
part 'order_form_bloc.freezed.dart';

class OrderFormBloc extends Bloc<OrderFormEvent, OrderFormState> {
  final OrderRemoteDatasource _orderRemoteDatasource;
  OrderFormBloc(this._orderRemoteDatasource) : super(OrderFormState.initial()) {
    on<_Started>((event, emit) {
      emit(OrderFormState.loaded(order: event.order));
    });
    on<_Create>(
      (event, emit) async {
        emit(const _Loading());

        try {
          // Convert ProductQuantity list to the format expected by the API

          final userData = await AuthLocalDataSource().getAuthData();

          final orderItems = OrderRequestModel(
            customerName: event.customerName,
            notes: '',
            orderType: event.orderType.name,
            tableId: event.table?.id,
            tableNumber: event.table?.tableName,
            outletId: userData.user?.outletId,
            customerId: event.customer?.id ?? '',
            orderItems: event.items
                .map(
                  (productQuantity) => OrderItemRequest(
                    productId: productQuantity.product.id,
                    quantity: productQuantity.quantity,
                    notes: productQuantity.notes,
                    unitPrice: productQuantity.product.price,
                    productVariantId: productQuantity.variant?.id,
                  ),
                )
                .toList(),
          );

          final result = await _orderRemoteDatasource.createOrder(orderItems);

          result.fold(
            (error) => emit(_Error(error)),
            (success) => emit(_Success(success.data!)),
          );
        } catch (e) {
          log("Error in AddOrderItemsBloc: $e");
          emit(_Error("Failed to add order items: $e"));
        }
      },
    );
    on<_CreateWithPaymentMethod>(
      (event, emit) async {
        emit(const _Loading());

        try {
          // Convert ProductQuantity list to the format expected by the API

          final userData = await AuthLocalDataSource().getAuthData();

          final orderItems = OrderRequestModel(
            customerName: event.customerName,
            notes: '',
            orderType: event.orderType.name,
            tableId: event.table.id,
            tableNumber: event.table.tableName,
            outletId: userData.user?.outletId,
            customerId: event.customer?.id ?? '',
            orderItems: event.items
                .map(
                  (productQuantity) => OrderItemRequest(
                    productId: productQuantity.product.id,
                    quantity: productQuantity.quantity,
                    notes: productQuantity.notes,
                    unitPrice: productQuantity.product.price,
                    productVariantId: productQuantity.variant?.id,
                  ),
                )
                .toList(),
          );

          final result = await _orderRemoteDatasource.createOrderWithPayment(
            orderItems,
            event.paymentMethod,
          );

          result.fold(
            (error) => emit(_Error(error)),
            (success) => emit(_Success(success.data!)),
          );
        } catch (e) {
          log("Error in AddOrderItemsBloc: $e");
          emit(_Error("Failed to add order items: $e"));
        }
      },
    );
    on<_AddToOrder>(
      (event, emit) async {
        emit(const _Loading());

        try {
          final result = await _orderRemoteDatasource.addToOrder(
            orderId: event.orderId,
            orderItems: event.items
                .map(
                  (item) => OrderItemRequest(
                    productId: item.product.id,
                    quantity: item.quantity,
                    unitPrice: item.product.price,
                    notes: item.notes,
                    productVariantId: item.variant?.id,
                  ),
                )
                .toList(),
          );

          result.fold(
            (error) => emit(_Error(error)),
            (success) => emit(_Success(success.data!)),
          );
        } catch (e) {
          log("Error in AddOrderItemsBloc: $e");
          emit(_Error("Failed to add order items: $e"));
        }
      },
    );
    on<_ToggleItem>((event, emit) {
      state.maybeWhen(
        loaded: (order, selectedItems, totalVoidOrRefund, _) {
          final newList = [...selectedItems];
          final exists = newList.any((e) => e.id == event.item.id);

          if (exists) {
            newList.removeWhere((e) => e.id == event.item.id);
          } else {
            newList.add(event.item);
          }

          final isAll = newList.length == (order.orderItems?.length ?? 0);

          emit(OrderFormState.loaded(
            order: order,
            selectedItems: newList,
            isAllSelected: isAll,
          ));
        },
        orElse: () {},
      );
    });

    on<_ToggleSelectAll>((event, emit) {
      state.maybeWhen(
        loaded: (order, _, totalVoidOrRefund, __) {
          final items = event.selectAll
              ? (order.orderItems ?? <OrderItem>[])
              : <OrderItem>[];

          emit(OrderFormState.loaded(
            order: order,
            selectedItems: items,
            isAllSelected: event.selectAll,
          ));
        },
        orElse: () {},
      );
    });

    on<_Refund>((event, emit) async {
      emit(const OrderFormState.loading());

      final result = await _orderRemoteDatasource.refund(
        orderId: event.orderId,
        reason: event.reason,
        orderItems: event.items,
      );

      result.fold(
        (error) => emit(_Error(error)),
        (success) => emit(_SuccessMsg()),
      );
    });

    on<_VoidOrder>((event, emit) async {
      emit(const OrderFormState.loading());

      final result = await _orderRemoteDatasource.voidOrder(
        orderId: event.orderId,
        reason: event.reason,
        orderItems: event.items,
      );

      result.fold(
        (error) => emit(_Error(error)),
        (success) => emit(_SuccessMsg()),
      );
    });
  }
}
