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

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:niogu_app/core/constants/app_color.dart';
import 'package:niogu_app/core/constants/app_font_size.dart';
import 'package:niogu_app/core/utils/login_required.dart';
import 'package:niogu_app/core/widgets/custom_error_screen.dart';
import 'package:niogu_app/core/providers/app_provider.dart';
import 'package:niogu_app/core/router/app_route.dart';
import 'package:niogu_app/core/utils/currency_format.dart';
import 'package:niogu_app/core/utils/extension_format.dart';
import 'package:niogu_app/core/utils/image_service.dart';
import 'package:niogu_app/core/utils/log_message.dart';
import 'package:niogu_app/core/enums/stock_type.dart';
import 'package:niogu_app/core/system/system_setting.dart';
import 'package:niogu_app/core/widgets/custom_empty_screen.dart';
import 'package:niogu_app/core/widgets/custom_not_login.dart';
import 'package:niogu_app/core/widgets/custom_snackbar.dart';
import 'package:niogu_app/features/goods/products/domain/entities/product.dart';
import 'package:niogu_app/features/pos/domain/entities/pos.dart';
import 'package:niogu_app/features/pos/presentation/providers/pos_provider.dart';
import 'package:niogu_app/features/pos/presentation/widgets/cart_bottom_sheet.dart';
import 'package:niogu_app/features/pos/presentation/widgets/decimal_quantity.dart';
import 'package:niogu_app/features/pos/presentation/widgets/insufficient_stock_dialog.dart';
import 'package:niogu_app/features/pos/presentation/widgets/pos_shimmer.dart';
import 'package:niogu_app/features/pos/presentation/widgets/product_card.dart';
import 'package:niogu_app/features/report/transaction/presentation/providers/transaction_report_provider.dart';
import 'package:sizer/sizer.dart';

class PosScreen extends ConsumerStatefulWidget {
  const PosScreen({super.key});

  @override
  ConsumerState<PosScreen> createState() => _PosScreenState();
}

class _PosScreenState extends ConsumerState<PosScreen> {
  final FocusNode _searchFocusNode = FocusNode();

  Color _searchIconColor = Colors.grey;

  final DraggableScrollableController _sheetController =
      DraggableScrollableController();

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final TextEditingController _discountController = TextEditingController();

  final TextEditingController _taxController = TextEditingController();

  final TextEditingController _noteController = TextEditingController();

  final TextEditingController _nameController = TextEditingController();

  final TextEditingController _phoneNumberController = TextEditingController();

  final TextEditingController _addressController = TextEditingController();

  final TextEditingController _payController = TextEditingController();

  final List<String?> _imagePathTemps = [];

  final ImagePicker _picker = ImagePicker();

  Timer? _debounce;

  bool _isOtherFormVisible = false;

  bool _isCustomerFormVisible = false;

  bool _validateChange = false;

  double _changeAmount = 0.0;

  String? _imagePath;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _searchFocusNode.addListener(() {
      setState(() {
        _searchIconColor = _searchFocusNode.hasFocus
            ? Colors.black
            : Colors.grey;
      });
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _searchFocusNode.dispose();
    _discountController.dispose();
    _taxController.dispose();
    _noteController.dispose();
    _nameController.dispose();
    _phoneNumberController.dispose();
    _addressController.dispose();
    _payController.dispose();
    _debounce?.cancel();
    super.dispose();
  }

  void _expandSheet() {
    FocusManager.instance.primaryFocus?.unfocus();

    Future.delayed(const Duration(milliseconds: 100), () {
      if (_sheetController.isAttached) {
        _sheetController.animateTo(
          0.9,
          duration: const Duration(milliseconds: 300),
          curve: Curves.easeOut,
        );
      } else {
        LogMessage.log.i("Sheet controller is not attached");
      }
    });
  }

  void _onSearchChanged(String value) {
    if (_debounce?.isActive ?? false) _debounce?.cancel();
    _debounce = Timer(const Duration(milliseconds: 800), () {
      ref.read(displayProductPosBySearchProvider.notifier).state = value;
    });
  }

  int _calculateProductAmount(List<CartItems> cartItems) {
    return cartItems.length;
  }

  double _calculateTotalQty(List<CartItems> cartItems) {
    return cartItems.fold(0.0, (sum, cartItem) {
      return sum + cartItem.quantity;
    });
  }

  double _calculateShoppingAmount(List<CartItems> cartItems) {
    return cartItems.fold(0.0, (sum, cartItem) {
      return sum + cartItem.quantity * cartItem.sellingPrice;
    });
  }

  void _discountOnChanged(String value) {
    final currentOutletId = ref.read(currentOutletIdProvider);

    final cartItemState = ref.read(cartItemsControllerProvider);

    final cartItems = cartItemState.values.where((cartItem) {
      return cartItem.currentOutletId == currentOutletId;
    }).toList();

    final double payAmount = double.tryParse(_payController.text.trim()) ?? 0.0;

    if (_debounce?.isActive ?? false) _debounce?.cancel();
    _debounce = Timer(const Duration(milliseconds: 400), () {
      setState(() {
        _validateChange = payAmount < _calculateTotalBill(cartItems);
        _discountController.text = value;
      });
    });

    if (_payController.text.trim().isNotEmpty) {
      _calculateChange(_payController.text);
    }
  }

  void _taxOnChanged(String value) {
    final currentOutletId = ref.read(currentOutletIdProvider);

    final cartItemState = ref.read(cartItemsControllerProvider);

    final cartItems = cartItemState.values.where((cartItem) {
      return cartItem.currentOutletId == currentOutletId;
    }).toList();

    final double payAmount = double.tryParse(_payController.text.trim()) ?? 0.0;

    if (_debounce?.isActive ?? false) _debounce?.cancel();
    _debounce = Timer(const Duration(milliseconds: 400), () {
      setState(() {
        _validateChange = payAmount < _calculateTotalBill(cartItems);
        _taxController.text = value;
      });
    });

    if (_payController.text.trim().isNotEmpty) {
      _calculateChange(_payController.text);
    }
  }

  void _calculateChange(String value) {
    final currentOutletId = ref.read(currentOutletIdProvider);

    final cartItemState = ref.read(cartItemsControllerProvider);

    final cartItems = cartItemState.values.where((cartItem) {
      return cartItem.currentOutletId == currentOutletId;
    }).toList();

    final double payAmount = double.tryParse(value) ?? 0.0;

    final double totalBill = _calculateTotalBill(cartItems);

    _validateChange = payAmount < totalBill;
    _payController.text = value;
    if (payAmount >= totalBill && cartItems.isNotEmpty) {
      _changeAmount = payAmount - totalBill;
    }
  }

  double _calculateTotalBill(List<CartItems> cartItems) {
    final double discount =
        double.tryParse(_discountController.text.trim()) ?? 0.0;

    final double tax = double.tryParse(_taxController.text.trim()) ?? 0.0;

    final double totalBiil = _calculateShoppingAmount(cartItems);

    return totalBiil - discount + tax;
  }

  void _handleDecrement(DisplayProductPos product) {
    final cartItemsNotifier = ref.read(cartItemsControllerProvider.notifier);

    cartItemsNotifier.decrement(product.productVariantId);

    if (_payController.text.trim().isNotEmpty) {
      _calculateChange(_payController.text);
    }
  }

  Future<void> _handleIncrement(DisplayProductPos product) async {
    final cartItemsNotifier = ref.read(cartItemsControllerProvider.notifier);

    if (product.stockType == StockType.fixed) {
      if (product.remainingStock == 0) {
        CustomSnackbar.showError(context, "Stok habis");
        return;
      }

      if (cartItemsNotifier.quantityOf(product.productVariantId) >=
          product.remainingStock) {
        CustomSnackbar.showError(context, "Stok tidak cukup");
        return;
      }
    }

    await cartItemsNotifier.increment(product);

    if (_payController.text.isNotEmpty) {
      _calculateChange(_payController.text);
    }
  }

  void _handleDeleteItem(CartItems cartItem) {
    final cartItemsNotifier = ref.read(cartItemsControllerProvider.notifier);

    cartItemsNotifier.delete(cartItem.id);

    if (_payController.text.trim().isNotEmpty) {
      _calculateChange(_payController.text);
    }
  }

  void _clear() {
    _discountController.clear();
    _taxController.clear();
    _noteController.clear();
    _nameController.clear();
    _phoneNumberController.clear();
    _addressController.clear();
    _payController.clear();
  }

  void _showInsufficientStockDialog({
    required String id,
    required String name,
    required double currentStock,
    required double totalNeeded,
    required double missingAmount,
    required String unit,
    required String triggerProductName,
    required int otherProductsCount,
  }) {
    showDialog(
      context: context,
      builder: (context) {
        return InsufficientStockDialog(
          materialName: name,
          currentStock: currentStock.toStringWithoutTrailingZero(),
          totalNeeded: totalNeeded.toStringWithoutTrailingZero(),
          missingAmount: missingAmount.toStringWithoutTrailingZero(),
          unit: unit,
          triggerProductName: triggerProductName,
          otherProductsCount: otherProductsCount,

          onAddStockPressed: () {
            context.pushNamed(AppRoute.stockInScreen);
          },
          onEditUsagePressed: () {
            context.pushNamed(
              AppRoute.editRawMaterialScreen,
              pathParameters: {"id": id},
            );
          },
        );
      },
    );
  }

  Future<void> _showPickerOptions() async {
    final bool isTablet = 100.w >= 600;
    showModalBottomSheet(
      context: context,
      backgroundColor: Colors.white,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(2.5.w)),
      ),
      constraints: const BoxConstraints(maxWidth: double.infinity),
      builder: (BuildContext context) {
        return SafeArea(
          child: Container(
            width: 100.w,
            padding: EdgeInsets.symmetric(vertical: 2.h, horizontal: 5.w),
            clipBehavior: Clip.hardEdge,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.vertical(top: Radius.circular(6.w)),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                ListTile(
                  leading: Icon(Icons.photo_library, size: 6.w),
                  title: Text(
                    'Galeri',
                    style: TextStyle(
                      fontSize: isTablet
                          ? AppFontSize.medium.sp
                          : AppFontSize.small.sp,
                    ),
                  ),
                  onTap: () async {
                    await _getImage(ImageSource.gallery);
                    context.pop();
                  },
                ),

                SizedBox(height: 2.h),

                ListTile(
                  leading: Icon(Icons.photo_camera, size: 6.w),
                  title: Text(
                    'Kamera',
                    style: TextStyle(
                      fontSize: isTablet
                          ? AppFontSize.medium.sp
                          : AppFontSize.small.sp,
                    ),
                  ),
                  onTap: () async {
                    await _getImage(ImageSource.camera);
                    context.pop();
                  },
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Future<void> _getImage(ImageSource ImageSource) async {
    try {
      final XFile? pickedFile = await _picker.pickImage(
        source: ImageSource,
        imageQuality: 70,
      );

      if (pickedFile != null) {
        File tempFile = File(pickedFile.path);

        String? imagePath = await ImageService.saveImageToLocalDirectory(
          tempFile,
          "payment_proof_orders",
        );

        if (imagePath != null) {
          _imagePathTemps.add(imagePath);
          setState(() {
            _imagePath = imagePath;
          });
        }
      }
    } catch (e, st) {
      LogMessage.log.w(e.toString(), error: e, stackTrace: st);
      CustomSnackbar.showWarning(context, "Akses ditolak");
    }
  }

  Future<void> _removeImage() async {
    setState(() {
      _imagePath = null;
    });
  }

  Future<void> _cleanUpImages() async {
    for (final path in _imagePathTemps) {
      if (path != null) {
        await ImageService.deleteLocalImage(path);
      }
    }
  }

  Future<void> _addSale() async {
    final cartItemState = ref.read(cartItemsControllerProvider);

    final currentOutletId = await SystemSetting.getCurrentOutletId();

    final cartItems = cartItemState.values.where((cartItem) {
      return cartItem.currentOutletId == currentOutletId;
    }).toList();

    if (cartItems.isEmpty) {
      CustomSnackbar.showError(context, "Tambah minimal 1 produk");
      return;
    }

    final Map<String, Set<String>> usedByProducts = {};

    final Map<String, double> requiredMaterials = {};

    final Map<String, String> materialNames = {};

    final Map<String, double> currentStocks = {};

    final Map<String, String> materialUnits = {};

    for (final cartItem in cartItems) {
      final rawMaterials = await ref
          .read(posRepositoryProvider)
          .getProductUseMaterials(cartItem.id, cartItem.quantity);

      for (final rawMaterial in rawMaterials) {
        if (!usedByProducts.containsKey(rawMaterial.rawMaterialId)) {
          usedByProducts[rawMaterial.rawMaterialId] = {};
        }

        usedByProducts[rawMaterial.rawMaterialId]!.add(
          cartItem.variantName ?? cartItem.name,
        );

        final double needForThisItem =
            rawMaterial.productQuantity * rawMaterial.quantity;

        if (requiredMaterials.containsKey(rawMaterial.rawMaterialId)) {
          requiredMaterials[rawMaterial.rawMaterialId] =
              requiredMaterials[rawMaterial.rawMaterialId]! + needForThisItem;
        } else {
          requiredMaterials[rawMaterial.rawMaterialId] = needForThisItem;
        }
        cartItem.variantName ?? cartItem.name;
        materialNames[rawMaterial.rawMaterialId] = rawMaterial.name;
        currentStocks[rawMaterial.rawMaterialId] = rawMaterial.stock;
        materialUnits[rawMaterial.rawMaterialId] = rawMaterial.unit;
      }
    }

    for (final entry in requiredMaterials.entries) {
      final String id = entry.key;

      final double totalNeeded = entry.value;

      final double currentStock = currentStocks[id] ?? 0.0;

      final String name = materialNames[id] ?? 'Bahan Baku';

      final String unit = materialUnits[id] ?? '';

      final products = usedByProducts[id]!.toList();

      final String triggerProductName = products.first;

      final int otherProductsCount = products.length - 1;

      if (currentStock < totalNeeded) {
        final double missingAmount = totalNeeded - currentStock;
        _showInsufficientStockDialog(
          id: id,
          name: name,
          currentStock: currentStock,
          totalNeeded: totalNeeded,
          missingAmount: missingAmount,
          unit: unit,
          triggerProductName: triggerProductName,
          otherProductsCount: otherProductsCount,
        );
        return;
      }
    }

    if (!_formKey.currentState!.validate()) return;

    try {
      if (_discountController.text.isNotEmpty) {
        final double discount = double.parse(_discountController.text.trim());

        if (discount <= 0) {
          CustomSnackbar.showError(context, "Diskon harus lebih dari 0");
          return;
        }
      }
    } catch (e) {
      CustomSnackbar.showError(context, "Nominal diskon tidak valid");
      return;
    }

    try {
      if (_taxController.text.isNotEmpty) {
        final double tax = double.parse(_taxController.text.trim());

        if (tax <= 0) {
          CustomSnackbar.showError(context, "Pajak harus lebih dari 0");
          return;
        }
      }
    } catch (e) {
      CustomSnackbar.showError(context, "Nominal pajak tidak valid");
      return;
    }

    try {
      if (_payController.text.isNotEmpty && _validateChange) {
        final double payAmount = double.parse(_payController.text.trim());

        if (payAmount <= 0) {
          CustomSnackbar.showError(
            context,
            "Nominal pembayaran harus lebih dari 0",
          );
          return;
        }

        final double totalBill = _calculateTotalBill(cartItems);

        if (totalBill > payAmount) {
          CustomSnackbar.showError(
            context,
            "Kurang ${CurrencyFormat.formatToIdr((totalBill - payAmount), 0)}",
          );
          return;
        }
      }
    } catch (e) {
      CustomSnackbar.showError(context, "Nominal pembayaran tidak valid");
      return;
    }

    CustomerInformation? customer;

    final Map<String, dynamic> customerAddressSnapshot = {};

    final bool customerInfoIsNotEmpty =
        _nameController.text.isNotEmpty ||
        _phoneNumberController.text.isNotEmpty ||
        _addressController.text.isNotEmpty;

    if (customerInfoIsNotEmpty) {
      if (_nameController.text.isEmpty) {
        CustomSnackbar.showError(context, "Nama pelanggan belum diisi");
        return;
      }

      final name = _nameController.text.trim();
      final phoneNumber = _phoneNumberController.text.trim();
      final address = _addressController.text.trim();

      customer = CustomerInformation(
        name: name,
        phoneNumber: phoneNumber,
        address: address,
      );

      if (address.isNotEmpty) {
        customerAddressSnapshot.putIfAbsent("full_address", () => address);
      }
    }

    final selectedCustomerState = ref.read(selectedCustomerProvider);

    SelectedCustomer? selectedCustomer;

    if (selectedCustomerState?.outletId == currentOutletId) {
      selectedCustomer = selectedCustomerState;
    }

    if (selectedCustomer != null && selectedCustomer.address.isNotEmpty) {
      customerAddressSnapshot.putIfAbsent(
        "full_address",
        () => selectedCustomer!.address,
      );
    }

    String? customerId;

    String? customerName;

    String? customerPhoneNumber;

    if (selectedCustomer != null) {
      customerId = selectedCustomer.id;
      customerName = selectedCustomer.name;
      customerPhoneNumber = selectedCustomer.phoneNumber;
    } else if (customer != null) {
      customerId = customer.id;
      customerName = customer.name;
      customerPhoneNumber = customer.phoneNumber;
    }

    final newSale = NewSale(
      customerId: customerId,
      customerNameSnapshot: customerName,
      customerPhoneNumberSnapshot: customerPhoneNumber,
      totalOrder: _calculateShoppingAmount(cartItems),
      otherInformation: OtherInformation(
        discount: double.tryParse(_discountController.text.trim()) ?? 0.0,
        tax: double.tryParse(_taxController.text.trim()) ?? 0.0,
        note: _noteController.text.trim(),
      ),
      totalAmount: _calculateTotalBill(cartItems),
      amountPaid: double.tryParse(_payController.text.trim()) ?? 0.0,
      changeAmount: _changeAmount,
      paymentProofPath: _imagePath,
      customerAddressSnapshot: customerAddressSnapshot,
    );

    final itemSales = cartItems.map((item) {
      return ItemSale(
        orderId: newSale.localId,
        outletInventoryId: item.outletInventoryId,
        productVariantId: item.id,
        stockType: item.stockType,
        stock: item.remainingStock,
        currentSold: item.currentSold,
        quantity: item.quantity,
        costPrice: item.costPrice,
        productImageSnapshot: item.imagePath,
        productNameSnapshot: item.name,
        productVariantNameSnapshot: item.variantName,
        sellingPriceSnapshot: item.sellingPrice,
        subtotal: item.quantity * item.sellingPrice,
      );
    }).toList();

    try {
      await ref
          .read(posControllerProvider.notifier)
          .addSale(customer, newSale, itemSales);

      if (!mounted) return;

      CustomSnackbar.showSuccess(context, "Penjualan baru berhasil dibuat");

      _clear();

      for (final path in _imagePathTemps) {
        if (path != null && _imagePath != null && path != _imagePath) {
          await ImageService.deleteLocalImage(path);
        }
      }

      setState(() {
        _imagePath = null;
        _imagePathTemps.clear();
      });

      ref.invalidate(selectedCustomerProvider);

      ref.invalidate(cartItemsControllerProvider);

      final orderDetail = await ref
          .read(transactionReportRepositoryProvider)
          .getOrderDetail(newSale.localId);

      context.pushNamed(
        AppRoute.transactionReportOrderDetailScreen,
        extra: orderDetail,
      );
    } catch (e, st) {
      LogMessage.log.e(e.toString(), error: e, stackTrace: st);
      CustomSnackbar.showError(context, "Ups, terjadi kesalahan");
    }
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final bool isTablet = 100.w >= 600;

        final bool isLandscape =
            MediaQuery.of(context).orientation == Orientation.landscape;

        const greyColor = Color(0xFFF5F5F5);

        final isLoggedIn = ref.watch(currentStatusLoginProvider);

        final currentUserName = ref.watch(currentUserNameProvider);

        final currentOutletId = ref.watch(currentOutletIdProvider);

        final currentOutletName = ref.watch(currentOutletNameProvider);

        final currentUserRole = ref.watch(currentUserRoleProvider);

        final productState = isLoggedIn
            ? ref.watch(filteredDisplayProductPosProvider)
            : AsyncValue<List<DisplayProductPos>>.data([]);

        final productEmptyState = isLoggedIn
            ? ref.watch(displayProductPosEmptyProvider)
            : ProductEmpty.empty_database;

        final selectedCustomerState = ref.watch(selectedCustomerProvider);

        final selectedCustomer =
            selectedCustomerState?.outletId == currentOutletId
            ? selectedCustomerState
            : null;

        final posControllerState = ref.watch(posControllerProvider);

        return PopScope(
          canPop: false,
          onPopInvokedWithResult: (didPop, result) async {
            if (didPop) return;

            await _cleanUpImages();

            context.goNamed(AppRoute.homeScreen);

            WidgetsBinding.instance.addPostFrameCallback((_) {
              setState(() {
                _imagePath = null;
              });
            });
          },
          child: SafeArea(
            top: false,
            bottom: true,
            right: false,
            left: false,
            child: Scaffold(
              backgroundColor: Colors.grey[50],
              resizeToAvoidBottomInset: false,
              appBar: AppBar(
                backgroundColor: Colors.white,
                surfaceTintColor: Colors.white,
                elevation: 0,
                toolbarHeight: 10.h,

                titleSpacing: 0,
                automaticallyImplyLeading: false,
                title: Padding(
                  padding: EdgeInsets.symmetric(horizontal: 4.w),
                  child: Row(
                    children: [
                      IconButton(
                        onPressed: () async {
                          await _cleanUpImages();

                          context.goNamed(AppRoute.homeScreen);

                          WidgetsBinding.instance.addPostFrameCallback((_) {
                            setState(() {
                              _imagePath = null;
                            });
                          });
                        },
                        icon: Icon(
                          Icons.close_rounded,
                          color: AppColor.primaryColor,
                          size: 7.w,
                        ),
                        padding: EdgeInsets.zero,
                        constraints: const BoxConstraints(),
                      ),

                      SizedBox(width: 3.w),

                      Expanded(
                        child: Container(
                          height: isTablet && isLandscape ? 12.h : 6.h,
                          padding: isTablet
                              ? EdgeInsets.symmetric(
                                  vertical: isLandscape ? 2.h : 1.h,
                                  horizontal: 2.w,
                                )
                              : EdgeInsets.zero,
                          decoration: BoxDecoration(
                            color: greyColor,
                            borderRadius: BorderRadius.circular(2.5.w),
                          ),
                          child: TextField(
                            focusNode: _searchFocusNode,
                            onChanged: (value) => _onSearchChanged(value),
                            textAlignVertical: TextAlignVertical.center,
                            style: TextStyle(
                              fontSize: isTablet
                                  ? AppFontSize.medium.sp
                                  : AppFontSize.small.sp,
                            ),
                            decoration: InputDecoration(
                              hintText: "Cari produk...",
                              hintStyle: TextStyle(
                                color: _searchIconColor,
                                fontSize: isTablet
                                    ? AppFontSize.medium.sp
                                    : AppFontSize.small.sp,
                              ),
                              prefixIcon: Icon(
                                Icons.search,
                                color: _searchIconColor,
                                size: 5.w,
                              ),
                              border: InputBorder.none,
                              contentPadding: EdgeInsets.zero,
                              isDense: true,
                            ),
                          ),
                        ),
                      ),

                      SizedBox(width: 3.w),

                      /**
                    if (isTablet) ...[
                      IconButton(
                        tooltip: isLandscape
                            ? "Ubah ke Potrait"
                            : "Ubah ke Landscape",
                        icon: Icon(
                          isLandscape
                              ? Icons.phone_iphone_rounded
                              : Icons.tablet_mac_rounded,
                          size: 5.w,
                          color: AppColor.primaryColor,
                        ),
                        onPressed: () {
                          if (isLandscape) {
                            SystemChrome.setPreferredOrientations([
                              DeviceOrientation.portraitUp,
                            ]);
                          } else {
                            SystemChrome.setPreferredOrientations([
                              DeviceOrientation.landscapeLeft,
                              DeviceOrientation.landscapeRight,
                            ]);
                          }
                        },
                      ),

                      SizedBox(width: 3.w),
                    ],
                    */

                      /** Notification 
                      Stack(
                        children: [
                          IconButton(
                            onPressed: () {},
                            icon: Icon(
                              Icons.notifications_outlined,
                              color: AppColor.primaryColor,
                              size: 7.w,
                            ),
                            padding: EdgeInsets.zero,
                          ),
                          Positioned(
                            right: isTablet
                                ? 10
                                : 100.w > 360
                                ? 12.5
                                : 15,
                            top: isTablet
                                ? 10
                                : 100.w > 360
                                ? 12.5
                                : 15,
                            child: Container(
                              padding: EdgeInsets.all(0.5.w),
                              decoration: const BoxDecoration(
                                color: Colors.red,
                                shape: BoxShape.circle,
                              ),
                              constraints: BoxConstraints(
                                minWidth: 2.5.w,
                                minHeight: 2.5.w,
                              ),
                            ),
                          ),
                        ],
                      ),
                      */
                    ],
                  ),
                ),
              ),

              body: productState.when(
                data: (products) {
                  final cartItemsNotifier = ref.watch(
                    cartItemsControllerProvider.notifier,
                  );

                  final cartItemState = ref.watch(cartItemsControllerProvider);

                  final cartItems = cartItemState.values.where((cartItem) {
                    return cartItem.currentOutletId == currentOutletId;
                  }).toList();

                  return Stack(
                    children: [
                      !isLoggedIn
                          ? const CustomNotLogin()
                          : Padding(
                              padding: EdgeInsets.only(
                                left: 4.w,
                                right: 4.w,
                                top: 2.h,
                                bottom: 20.h,
                              ),
                              child: switch (productEmptyState) {
                                ProductEmpty.loading => const SizedBox(),
                                ProductEmpty.empty_database =>
                                  CustomEmptyScreen(
                                    title: "Tidak Ada Produk",
                                    body: "Kamu belum memiliki produk",
                                    textButton: "Buat Produk Pertamamu",
                                    onPressed: () => context.pushNamed(
                                      AppRoute.addProductScreen,
                                    ),
                                  ),
                                ProductEmpty.empty_search_result =>
                                  const CustomEmptyScreen(
                                    body: "Produk Tidak Ditemukan",
                                  ),
                                ProductEmpty.has_data => GridView.builder(
                                  itemCount: products.length,
                                  gridDelegate:
                                      SliverGridDelegateWithFixedCrossAxisCount(
                                        crossAxisCount: 2,
                                        childAspectRatio: 0.75,
                                        crossAxisSpacing: 4.w,
                                        mainAxisSpacing: 2.h,
                                      ),
                                  itemBuilder: (context, index) {
                                    final product = products[index];

                                    final bool isInCart = cartItemsNotifier
                                        .isInCart(product.productVariantId);

                                    final double quantity = cartItemsNotifier
                                        .quantityOf(product.productVariantId);

                                    return ProductCard(
                                      product: product,
                                      isInCart: isInCart,
                                      quantity: quantity,
                                      onPressed: () async =>
                                          await _handleIncrement(product),
                                      onDecrementTap: () =>
                                          _handleDecrement(product),
                                      onIncrementTap: () async =>
                                          await _handleIncrement(product),
                                    );
                                  },
                                ),
                              },
                            ),
                      CartBottomSheet(
                        isLoggedIn: isLoggedIn,
                        sheetController: _sheetController,
                        formKey: _formKey,
                        currentUserName: currentUserName,
                        currentOutletName: currentOutletName,
                        currentUserRole: currentUserRole,
                        cartItems: cartItems,
                        shoppingAmount: _calculateShoppingAmount(cartItems),
                        productAmount: _calculateProductAmount(cartItems),
                        totalQty: _calculateTotalQty(cartItems),
                        discountController: _discountController,
                        taxController: _taxController,
                        noteController: _noteController,
                        nameController: _nameController,
                        phoneNumberController: _phoneNumberController,
                        addressController: _addressController,
                        validateChange: _validateChange,
                        totalBill: _calculateTotalBill(cartItems),
                        onViewOrderPressed: _expandSheet,
                        onOtherFormTap: () {
                          setState(() {
                            _isOtherFormVisible = !_isOtherFormVisible;
                          });
                        },
                        onCustomerFormTap: () {
                          setState(() {
                            _isCustomerFormVisible = !_isCustomerFormVisible;
                          });
                        },
                        isOtherFormVisible: _isOtherFormVisible,
                        isCustomerFormVisible: _isCustomerFormVisible,
                        selectedCustomer: selectedCustomer,
                        onTapCloseSelectedCustomer: selectedCustomer == null
                            ? null
                            : () {
                                ref
                                        .read(selectedCustomerProvider.notifier)
                                        .state =
                                    null;
                              },
                        payController: _payController,
                        calculateChange: (value) {
                          if (_debounce?.isActive ?? false) _debounce?.cancel();

                          _debounce = Timer(
                            const Duration(milliseconds: 400),
                            () {
                              final currentOutletId = ref.read(
                                currentOutletIdProvider,
                              );

                              final cartItemState = ref.read(
                                cartItemsControllerProvider,
                              );

                              final cartItems = cartItemState.values.where((
                                cartItem,
                              ) {
                                return cartItem.currentOutletId ==
                                    currentOutletId;
                              }).toList();

                              final double payAmount =
                                  double.tryParse(value) ?? 0.0;

                              final double totalBill = _calculateTotalBill(
                                cartItems,
                              );

                              setState(() {
                                _validateChange = payAmount < totalBill;
                                _payController.text = value;
                                if (payAmount >= totalBill &&
                                    cartItems.isNotEmpty) {
                                  _changeAmount = payAmount - totalBill;
                                }
                              });
                            },
                          );
                        },
                        changeAmount: _changeAmount,
                        imagePath: _imagePath,
                        onDecrementTap: (cartItem) {
                          final product = products.firstWhere(
                            (p) => p.productVariantId == cartItem.id,
                          );

                          _handleDecrement(product);
                        },
                        onIncrementTap: (cartItem) async {
                          final product = products.firstWhere(
                            (p) => p.productVariantId == cartItem.id,
                          );

                          await _handleIncrement(product);
                        },
                        onEditPressed: (cartItem) {
                          final String name = cartItem.name;

                          final String variantName =
                              cartItem.variantName ?? '-';

                          final stockType = cartItem.stockType;

                          final String remainingStock = cartItem.remainingStock
                              .toStringWithoutTrailingZero();
                          final String unit = cartItem.unit;

                          final String initialQuantity = cartItem.quantity
                              .toStringWithoutTrailingZero();

                          final String sellingPrice =
                              CurrencyFormat.formatToIdr(
                                cartItem.sellingPrice,
                                0,
                              );

                          showDialog(
                            context: context,
                            builder: (_) => DecimalQuantity(
                              name: name,
                              variantName: variantName,
                              stockType: stockType,
                              remainingStock: remainingStock,
                              unit: unit,
                              initialQuantity: initialQuantity,
                              sellingPrice: sellingPrice,
                              onPressed: (value) {
                                try {
                                  final double stock = double.parse(
                                    remainingStock,
                                  );

                                  final double quantity = double.parse(value);

                                  if (stockType == StockType.fixed &&
                                      quantity > stock) {
                                    CustomSnackbar.showError(
                                      context,
                                      "Stok tidak cukup",
                                    );
                                    return;
                                  }

                                  final cartItemsNotifier = ref.read(
                                    cartItemsControllerProvider.notifier,
                                  );

                                  cartItemsNotifier.customQuantity(
                                    cartItem.id,
                                    quantity,
                                  );

                                  if (_payController.text.trim().isNotEmpty) {
                                    _calculateChange(_payController.text);
                                  }
                                } catch (e) {
                                  CustomSnackbar.showError(
                                    context,
                                    "Stok tidak valid",
                                  );
                                }
                              },
                            ),
                          );
                        },
                        onDeletePressed: _handleDeleteItem,
                        discountOnChanged: _discountOnChanged,
                        taxOnChanged: _taxOnChanged,
                        onTapImageAdd: !isLoggedIn
                            ? () => LoginRequired.showLoginRequired(context)
                            : _showPickerOptions,
                        onTapImageRemove: _removeImage,
                        onProccessPressed:
                            !isLoggedIn || posControllerState.isLoading
                            ? null
                            : _addSale,
                      ),
                    ],
                  );
                },
                error: (error, stackTrace) {
                  return CustomErrorScreen(
                    message: "Ups, terjadi kesalahan",
                    onRefresh: () {},
                  );
                },
                loading: () => const PosShimmer(),
              ),
            ),
          ),
        );
      },
    );
  }
}
