import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.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/widgets/custom_error_screen.dart';
import 'package:niogu_app/core/router/app_route.dart';
import 'package:niogu_app/core/utils/extension_format.dart';
import 'package:niogu_app/core/enums/item_type.dart';
import 'package:niogu_app/core/widgets/custom_empty_screen.dart';
import 'package:niogu_app/features/stock_check/domain/entities/selected_checked_item.dart';
import 'package:niogu_app/features/stock_check/presentation/providers/stock_check_provider.dart';
import 'package:niogu_app/features/stock_check/presentation/widgets/stock_check_shimmer.dart';
import 'package:niogu_app/features/stock_in/domain/entities/stock_in.dart';
import 'package:niogu_app/features/stock_in/presentation/provider/stock_in_provider.dart';
import 'package:sizer/sizer.dart';

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

  @override
  ConsumerState<RawMaterialStockCheckScreen> createState() =>
      RawMaterialStockCheckScreenState();
}

class RawMaterialStockCheckScreenState
    extends ConsumerState<RawMaterialStockCheckScreen>
    with AutomaticKeepAliveClientMixin {
  final Map<String, TextEditingController> _physicalControllers = {};

  final Map<String, TextEditingController> _noteControllers = {};

  final Map<String, Color> _statusColors = {};

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

  Timer? _debounce;

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    for (final controller in _physicalControllers.values) {
      controller.dispose();
    }

    for (final controller in _noteControllers.values) {
      controller.dispose();
    }
    _debounce?.cancel();
    super.dispose();
  }

  TextEditingController _physicalController(String id) {
    return _physicalControllers.putIfAbsent(id, () => TextEditingController());
  }

  TextEditingController _noteController(String id) {
    return _noteControllers.putIfAbsent(id, () => TextEditingController());
  }

  void _calculateDifference(String value, DisplayItem rawMaterial) {
    if (_debounce?.isActive ?? false) _debounce?.cancel();

    DifferenceType differenceType = DifferenceType.suitable;

    double quantity = 0.0;

    _debounce = Timer(const Duration(milliseconds: 400), () {
      setState(() {
        if (value.isEmpty ||
            (value.isNotEmpty &&
                (double.tryParse(value) == null || double.parse(value) < 0))) {
          _statusColors[rawMaterial.id] = Colors.grey;
          _statusTexts[rawMaterial.id] = "Belum Dicek";
          return;
        }

        final double physicalStock = double.parse(value);

        if (physicalStock == rawMaterial.remainingStock) {
          _statusColors[rawMaterial.id] = Colors.green;
          _statusTexts[rawMaterial.id] = "Sesuai";
          quantity = rawMaterial.remainingStock;
          differenceType = DifferenceType.suitable;
        } else if (physicalStock < rawMaterial.remainingStock) {
          _statusColors[rawMaterial.id] = Colors.red;
          _statusTexts[rawMaterial.id] =
              "Kurang ${(physicalStock - rawMaterial.remainingStock).abs().toStringWithoutTrailingZero()} dari stok di sistem";
          quantity = (physicalStock - rawMaterial.remainingStock);
          differenceType = DifferenceType.less;
        } else {
          _statusColors[rawMaterial.id] = Colors.blue;
          _statusTexts[rawMaterial.id] =
              "Lebih ${(physicalStock - rawMaterial.remainingStock).toStringWithoutTrailingZero()} dari stok di sistem";
          quantity = (physicalStock - rawMaterial.remainingStock);
          differenceType = DifferenceType.more;
        }
      });

      final selectedItemState = ref.read(selectedCheckedItemProvider);

      final selectedItemNotifier = ref.read(
        selectedCheckedItemProvider.notifier,
      );

      if (value.isNotEmpty &&
          double.tryParse(value.trim()) != null &&
          double.parse(value.trim()) >= 0) {
        if (selectedItemState.containsKey(rawMaterial.id)) {
          final selectedItem = selectedItemState[rawMaterial.id];

          selectedItemNotifier.state = {
            ...selectedItemState,
            rawMaterial.id: selectedItem!.copyWith(quantity: quantity),
          };
        } else {
          selectedItemNotifier.state = {
            ...selectedItemState,
            rawMaterial.id: SelectedCheckedItem(
              id: rawMaterial.id,
              itemType: ItemType.raw_material,
              itemId: rawMaterial.itemId,
              differenceType: differenceType,
              costPrice: 0.0,
              purchasePrice: rawMaterial.purchasePrice,
              remainingStock: rawMaterial.remainingStock,
              quantity: quantity,
            ),
          };
        }
      } else {
        selectedItemNotifier.state = {...selectedItemState}
          ..remove(rawMaterial.id);
      }
    });
  }

  void clear() {
    for (final controller in _physicalControllers.values) {
      controller.clear();
    }

    for (final controller in _noteControllers.values) {
      controller.clear();
    }

    _statusColors.clear();

    _statusTexts.clear();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    final bool isTablet = 100.w >= 600;

    final rawMaterialState = ref.watch(
      filteredItemProvider(ItemType.raw_material),
    );

    final rawMaterialEmptyState = ref.watch(
      displayItemEmptyProvider(ItemType.raw_material),
    );

    return rawMaterialState.when(
      data: (rawMaterials) {
        switch (rawMaterialEmptyState) {
          case DisplayItemEmpty.loading:
            return const SizedBox();

          case DisplayItemEmpty.empty_database:
            return CustomEmptyScreen(
              title: "Tidak Ada Produk",
              body: "Kamu belum memiliki produk",
              textButton: "Buat Produk Pertamamu",
              onPressed: () => context.pushNamed(AppRoute.addRawMaterialScreen),
            );
          case DisplayItemEmpty.empty_search_result:
            return SingleChildScrollView(
              physics: const AlwaysScrollableScrollPhysics(),
              padding: EdgeInsets.symmetric(vertical: 3.h),
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "Produk Tidak Ditemukan",
                      style: TextStyle(
                        fontSize: AppFontSize.large.sp,
                        fontWeight: FontWeight.bold,
                        color: Colors.black,
                      ),
                    ),

                    SizedBox(height: 1.5.h),

                    Icon(
                      Icons.search_off_rounded,
                      size: 15.h,
                      color: Colors.grey.shade300,
                    ),
                  ],
                ),
              ),
            );
          case DisplayItemEmpty.has_data:
            return ListView.builder(
              padding: EdgeInsets.all(4.w),
              itemCount: rawMaterials.length,
              itemBuilder: (context, index) {
                final rawMaterial = rawMaterials[index];

                String? difference;

                String? symbol;

                Color? symbolColor;

                if (double.tryParse(
                      _physicalController(rawMaterial.id).text.trim(),
                    ) !=
                    null) {
                  final double physicalStock = double.parse(
                    _physicalController(rawMaterial.id).text.trim(),
                  );

                  difference = (physicalStock - rawMaterial.remainingStock)
                      .abs()
                      .toStringWithoutTrailingZero();
                  if (physicalStock > rawMaterial.remainingStock) {
                    symbol = "+";
                    symbolColor = Colors.green;
                  } else if (physicalStock < rawMaterial.remainingStock) {
                    symbol = "-";
                    symbolColor = Colors.red;
                  }
                }

                return Container(
                  margin: EdgeInsets.only(bottom: 1.5.h),
                  padding: EdgeInsets.all(4.w),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(2.5.w),
                    border: Border.all(color: Colors.grey.shade200),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(0.02),
                        blurRadius: 5,
                        offset: const Offset(0, 2),
                      ),
                    ],
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Container(
                            height: 15.w,
                            width: 15.w,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.grey.shade200,
                                width: 1.5,
                              ),
                              borderRadius: BorderRadius.circular(2.5.w),
                            ),
                            child: Icon(
                              Icons.inventory_2_rounded,
                              size: 8.w,
                              color: Colors.grey,
                            ),
                          ),
                          SizedBox(width: 3.w),
                          Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  rawMaterial.name,
                                  maxLines: 2,
                                  overflow: TextOverflow.ellipsis,
                                  style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    fontSize: isTablet
                                        ? AppFontSize.medium.sp
                                        : AppFontSize.small.sp,
                                  ),
                                ),
                                if (rawMaterial.variantName != null) ...[
                                  SizedBox(height: 0.5.h),
                                  Text(
                                    rawMaterial.variantName!,
                                    style: TextStyle(
                                      color: Colors.grey[600],
                                      fontSize: isTablet
                                          ? (AppFontSize.medium - 1.25).sp
                                          : (AppFontSize.small - 1.25).sp,
                                    ),
                                  ),
                                ],
                                SizedBox(height: 0.5.h),
                                Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceBetween,
                                  children: [
                                    Container(
                                      padding: EdgeInsets.symmetric(
                                        horizontal: 2.w,
                                        vertical: 0.5.w,
                                      ),
                                      decoration: BoxDecoration(
                                        color: Colors.grey[100],
                                        borderRadius: BorderRadius.circular(
                                          1.w,
                                        ),
                                      ),
                                      child: Text(
                                        "Sistem: ${rawMaterial.remainingStock.toStringWithoutTrailingZero()} ${rawMaterial.unit}",
                                        style: TextStyle(
                                          fontSize: isTablet
                                              ? (AppFontSize.medium - 1.25).sp
                                              : (AppFontSize.small - 1.25).sp,
                                          color: Colors.black87,
                                          fontWeight: FontWeight.w600,
                                        ),
                                      ),
                                    ),

                                    if (symbol != null &&
                                        symbolColor != null &&
                                        difference != null)
                                      Text(
                                        "$symbol $difference ${rawMaterial.unit}",
                                        style: TextStyle(
                                          fontSize: isTablet
                                              ? (AppFontSize.medium - 1.25).sp
                                              : (AppFontSize.small - 1.25).sp,
                                          color: symbolColor,
                                          fontWeight: FontWeight.w600,
                                        ),
                                      ),
                                  ],
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),

                      Divider(height: 2.5.h, color: Colors.grey[100]),

                      Row(
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: [
                          Expanded(
                            flex: 3,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  "Stok Fisik",
                                  style: TextStyle(
                                    fontSize: isTablet
                                        ? (AppFontSize.medium - 1.25).sp
                                        : (AppFontSize.small - 1.25).sp,
                                    color: Colors.grey[600],
                                  ),
                                ),
                                SizedBox(height: 0.8.h),
                                SizedBox(
                                  height: 5.5.h,
                                  child: TextFormField(
                                    controller: _physicalController(
                                      rawMaterial.id,
                                    ),
                                    keyboardType:
                                        const TextInputType.numberWithOptions(
                                          decimal: true,
                                        ),
                                    onChanged: (value) => _calculateDifference(
                                      value,
                                      rawMaterial,
                                    ),
                                    style: TextStyle(
                                      fontWeight: FontWeight.bold,
                                      fontSize: isTablet
                                          ? (AppFontSize.medium - 1.25).sp
                                          : (AppFontSize.small - 1.25).sp,
                                    ),
                                    decoration: InputDecoration(
                                      contentPadding: EdgeInsets.symmetric(
                                        horizontal: 3.w,
                                      ),
                                      border: OutlineInputBorder(
                                        borderRadius: BorderRadius.circular(
                                          2.w,
                                        ),
                                      ),
                                      enabledBorder: OutlineInputBorder(
                                        borderRadius: BorderRadius.circular(
                                          2.5.w,
                                        ),
                                        borderSide: BorderSide(
                                          color: Colors.grey.shade300,
                                        ),
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderRadius: BorderRadius.circular(
                                          2.w,
                                        ),
                                        borderSide: BorderSide(
                                          color: AppColor.primaryColor,
                                          width: 1.5,
                                        ),
                                      ),
                                      suffixText: rawMaterial.unit,
                                      suffixStyle: TextStyle(
                                        fontSize: isTablet
                                            ? (AppFontSize.medium - 1.25).sp
                                            : (AppFontSize.small - 1.25).sp,
                                        color: Colors.grey,
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),

                          SizedBox(width: 4.w),

                          Expanded(
                            flex: 6,
                            child: Container(
                              height: 5.5.h,
                              padding: EdgeInsets.symmetric(horizontal: 2.w),
                              decoration: BoxDecoration(
                                color:
                                    (_statusColors[rawMaterial.id] ??
                                            Colors.grey)
                                        .withOpacity(0.1),
                                borderRadius: BorderRadius.circular(2.5.w),
                                border: Border.all(
                                  color:
                                      (_statusColors[rawMaterial.id] ??
                                              Colors.grey)
                                          .withOpacity(0.3),
                                ),
                              ),
                              alignment: Alignment.centerLeft,
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    "Selisih",
                                    style: TextStyle(
                                      fontSize: isTablet
                                          ? (AppFontSize.medium - 1.25).sp
                                          : (AppFontSize.small - 1.25).sp,
                                      color:
                                          (_statusColors[rawMaterial.id] ??
                                                  Colors.grey)
                                              .withOpacity(0.8),
                                    ),
                                  ),
                                  Text(
                                    _statusTexts[rawMaterial.id] ??
                                        "Belum Dicek",
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                    style: TextStyle(
                                      fontSize: isTablet
                                          ? (AppFontSize.medium - 1.25).sp
                                          : (AppFontSize.small - 1.25).sp,
                                      fontWeight: FontWeight.bold,
                                      color:
                                          (_statusColors[rawMaterial.id] ??
                                          Colors.grey),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),

                      SizedBox(height: 1.5.h),
                      TextField(
                        controller: _noteController(rawMaterial.id),
                        onChanged: (value) {
                          final selectedItemState = ref.read(
                            selectedCheckedItemProvider,
                          );

                          final selectedItemNotifier = ref.read(
                            selectedCheckedItemProvider.notifier,
                          );

                          if (selectedItemState.containsKey(rawMaterial.id)) {
                            selectedItemNotifier.state = {
                              ...selectedItemState,
                              rawMaterial.id: selectedItemState[rawMaterial.id]!
                                  .copyWith(note: value),
                            };
                          }
                        },
                        style: TextStyle(
                          fontSize: isTablet
                              ? (AppFontSize.medium - 1.25).sp
                              : (AppFontSize.small - 1.25).sp,
                        ),
                        decoration: InputDecoration(
                          hintText: "Catatan (Opsional) - cth: Barang rusak",
                          hintStyle: TextStyle(
                            fontSize: isTablet
                                ? (AppFontSize.medium - 1.25).sp
                                : (AppFontSize.small - 1.25).sp,
                            color: Colors.grey[400],
                          ),
                          isDense: true,
                          contentPadding: EdgeInsets.symmetric(
                            horizontal: 3.w,
                            vertical: 1.2.h,
                          ),
                          filled: true,
                          fillColor: Colors.grey[50],
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(2.5.w),
                            borderSide: BorderSide.none,
                          ),
                          prefixIcon: Icon(
                            Icons.edit_note,
                            size: 4.5.w,
                            color: Colors.grey[400],
                          ),
                        ),
                      ),
                    ],
                  ),
                );
              },
            );
        }
      },
      error: (error, stackTrace) {
        return CustomErrorScreen(message: "Ups, terjadi kesalahan", onRefresh: () {});
      },
      loading: () => const StockCheckShimmer(),
    );
  }
}
