import 'package:concierge/data/remote/models/area_details.dart';
import 'package:concierge/data/remote/models/product.dart';
import 'package:concierge/domain/models/data_state.dart';
import 'package:concierge/domain/models/delivery_location.dart';
import 'package:concierge/presentation/app/concierge_cubit.dart';
import 'package:concierge/presentation/base/base_cubit.dart';
import 'package:concierge/domain/models/app_error.dart';
import 'package:flutter/cupertino.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

import '../../domain/models/product_in_cart.dart';

part '../../_generated/presentation/app/cart_cubit.freezed.dart';

class CartCubit extends BaseCubit<CartState> {
  final ConciergeCubit _conciergeCubit;

  CartCubit(this._conciergeCubit) : super(const CartState());

  final orderCommentController = TextEditingController();

  void updateProduct(int productId, Map<int, int> variantId, int quantity) {
    final copy = Map.of(state.productsWithQuantity);
    copy[productId] = ProductInCart(productId, variantId, quantity);
    safeEmit(state.copyWith(productsWithQuantity: copy));
  }

  ProductInCart? getProduct(int productId) {
    final product = state.productsWithQuantity[productId];
    if (product == null) return null;
    if (product.quantity == 0) return null;
    return product;
  }

  int getQuantity(int productId) => state.productsWithQuantity[productId]?.quantity ?? 0;

  void updateComment(String comment) {
    safeEmit(state.copyWith(comment: comment));
  }

  void updateDelivery(bool isDelivery) {
    safeEmit(state.copyWith(isDelivery: isDelivery));
  }

  void updateReadyTime(String time) {
    safeEmit(state.copyWith(readyTime: time));
  }

  void updateSelectedArea(AreaDetails area) {
    safeEmit(state.copyWith(selectedArea: area, productsWithQuantity: {}));
  }

  void updatePaymentMethod(bool chargeToRoom) {
    safeEmit(state.copyWith(chargeToRoom: chargeToRoom));
  }

  void updateLocation(DeliveryLocation deliveryLocation) {
    safeEmit(state.copyWith(deliveryLocation: deliveryLocation));
  }

  void updateLocationCode(String code) {
    safeEmit(state.copyWith(deliveryLocationCode: code));
  }

  int get totalItems {
    if (state.productsWithQuantity.isEmpty) return 0;
    return state.productsWithQuantity.values
        .map((p) => p.quantity)
        .reduce((prev, curr) => prev + curr);
  }

  double get totalPrice {
    double price = 0;
    for (final product in products) {
      final quantity = getProduct(product.id)?.quantity ?? 0;
      price += product.price * quantity;
    }
    return price;
  }

  Iterable<Product> get products sync* {
    for (final productId in state.productsWithQuantity.keys) {
      final dataState = _conciergeCubit.getProductState(productId);
      if (dataState is Success<Product> && getQuantity(productId) > 0) yield dataState.data;
    }
  }
}

@freezed
abstract class CartState with _$CartState {
  const factory CartState({
    @Default(false) bool isLoading,
    @Default(AppError.none) AppError error,
    @Default({}) Map<int, ProductInCart> productsWithQuantity,
    @Default(false) bool isDelivery,
    @Default(true) bool chargeToRoom,
    @Default("") String comment,
    @Default("") String readyTime,
    @Default("") String deliveryLocationCode,
    @Default(DeliveryLocation.room) DeliveryLocation deliveryLocation,
    AreaDetails? selectedArea,
  }) = _CartState;

  const CartState._();
}