import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:niogu_app/core/components/top_back_bar_app.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/providers/app_provider.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/utils/log_message.dart';
import 'package:niogu_app/core/enums/stock_card_type.dart';
import 'package:niogu_app/core/enums/stock_type.dart';
import 'package:niogu_app/core/system/system_setting.dart';
import 'package:niogu_app/core/enums/user_role.dart';
import 'package:niogu_app/core/widgets/custom_selector.dart';
import 'package:niogu_app/core/widgets/custom_snackbar.dart';
import 'package:niogu_app/core/widgets/custom_text_form_field.dart';
import 'package:niogu_app/core/widgets/pop_up_notification.dart';
import 'package:niogu_app/features/goods/domain/entities/stock_card.dart';
import 'package:niogu_app/features/goods/presentation/widgets/dropdown_with_action.dart';
import 'package:niogu_app/features/goods/raw_materials/domain/entities/raw_material.dart';
import 'package:niogu_app/features/goods/raw_materials/presentation/providers/raw_material_provider.dart';
import 'package:niogu_app/features/goods/raw_materials/presentation/widgets/edit_raw_material_shimmer.dart';
import 'package:niogu_app/features/goods/units/domain/entities/unit.dart';
import 'package:niogu_app/features/goods/units/presentation/providers/unit_provider.dart';
import 'package:niogu_app/features/goods/units/presentation/screens/add_unit_screen.dart';
import 'package:niogu_app/features/goods/units/presentation/screens/edit_unit_screen.dart';
import 'package:niogu_app/features/goods/domain/entities/outlet_inventory.dart';
import 'package:niogu_app/features/outlets/presentation/providers/outlet_provider.dart';
import 'package:sizer/sizer.dart';

class EditRawMaterialScreen extends ConsumerStatefulWidget {
  final String rawMaterialId;
  final bool isMainOutlet;
  final bool isEditing;
  const EditRawMaterialScreen({
    super.key,
    required this.rawMaterialId,
    this.isMainOutlet = false,
    this.isEditing = true,
  });

  @override
  ConsumerState<EditRawMaterialScreen> createState() =>
      _EditRawMaterialScreenState();
}

class _EditRawMaterialScreenState extends ConsumerState<EditRawMaterialScreen> {
  late final String _rawMaterialId;

  late final bool _isMainOutlet;

  late final bool _isEditing;

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

  final TextEditingController _nameController = TextEditingController();

  final TextEditingController _purchasePriceController =
      TextEditingController();

  final TextEditingController _stockController = TextEditingController();

  String? _selectedUnit;

  String? _outletInventoryId;

  bool _isLoading = true;

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

    _rawMaterialId = widget.rawMaterialId;

    _isMainOutlet = widget.isMainOutlet;

    _isEditing = widget.isEditing;

    WidgetsBinding.instance.addPostFrameCallback((_) {
      Future.microtask(() {
        ref.invalidate(receiptItemIdProvider);

        ref.invalidate(deleteProductUsageMaterialProvider);
      });

      Future.delayed(const Duration(milliseconds: 800), () {
        _fetchRawMaterial();
      });
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _nameController.dispose();
    _purchasePriceController.dispose();
    _stockController.dispose();
    super.dispose();
  }

  Future<void> _fetchRawMaterial() async {
    try {
      final rawMaterialRepository = ref.read(rawMaterialRepositoryProvider);

      final rawMaterial = await rawMaterialRepository.fetchRawMaterialById(
        _rawMaterialId,
        _isEditing,
      );

      if (!mounted) return;

      _nameController.text = rawMaterial.name;

      _purchasePriceController.text = rawMaterial.purchasePrice
          .toStringWithoutTrailingZero();

      _stockController.text = rawMaterial.stock.toStringWithoutTrailingZero();

      _selectedUnit = rawMaterial.unitId;

      _outletInventoryId = rawMaterial.outletInventoryId;

      ref
          .read(selectedProductUsageMaterialProvider.notifier)
          .hydrate(rawMaterial.productUsages);

      final Map<String, String?> receiptItemIds = {
        for (final data in rawMaterial.productUsages)
          data.productUsageId: data.receiptItemId,
      };

      ref.read(receiptItemIdProvider.notifier).state = receiptItemIds;

      setState(() {
        _isLoading = false;
      });
    } catch (e, st) {
      if (!mounted) return;

      setState(() {
        _isLoading = false;
      });

      LogMessage.log.e(e.toString(), error: e, stackTrace: st);
      CustomSnackbar.showError(context, "Ups, terjadi kesalahan");
      context.pop();
    }
  }

  String? _validator({
    String? value,
    required String message1,
    String? message2,
    bool isNumber = false,
    bool isPurchasePrice = false,
    bool isStock = false,
    String? errorMessage,
  }) {
    if (value == null || value.isEmpty) {
      return message1;
    }

    try {
      if (isNumber && double.parse(value) <= 0) {
        if (isPurchasePrice) return message2;

        if (isStock) return message2;
      }
    } catch (e) {
      return errorMessage;
    }

    return null;
  }

  Future<void> _saveRawMaterial() async {
    if (!_formKey.currentState!.validate()) {
      return;
    }

    if (_selectedUnit == null) {
      CustomSnackbar.showError(context, "Satuan bahan baku belum dipilih");
      return;
    }

    final String name = _nameController.text.trim();
    final String unitId = _selectedUnit!;
    final rawMaterial = UpsertRawMaterial(
      localId: _rawMaterialId,
      unitId: unitId,
      name: name,
    );

    final selectProductUsageMaterials = ref
        .read(selectedProductUsageMaterialProvider)
        .values
        .toList();

    final List<UpsertReceiptItem> receiptItems = selectProductUsageMaterials
        .map((selectProductUsage) {
          return UpsertReceiptItem(
            localId: selectProductUsage.receiptItemId,
            productUsageId: selectProductUsage.productUsageId,
            rawMaterialId: rawMaterial.localId,
            quantity: selectProductUsage.quantity,
          );
        })
        .toList();
    
    final userId = await SystemSetting.getCurrentUserId();

    final outletId = await SystemSetting.getCurrentOutletId();

    try {
      final double stock = double.parse(_stockController.text.trim());

      final double purchasePrice = double.parse(
        _purchasePriceController.text.trim(),
      );

      final List<UpsertOutletInventory> outletInventories = [
        UpsertOutletInventory(
          localId: !_isEditing ? null : _outletInventoryId,
          outletId: outletId!,
          itemType: ItemType.raw_material,
          itemId: rawMaterial.localId,
          stockType: StockType.fixed,
          stock: stock,
          costPrice: 0.0,
          sellingPrice: 0.0,
          purchasePrice: purchasePrice,
        ),
      ];

      final deleteItems = ref.read(deleteProductUsageMaterialProvider);

      final List<StockCard> stockCards = [
        StockCard(
          outletInventoryId: outletInventories.single.localId,
          userId: userId!,
          stockCardType: StockCardType.initial_stock,
          qtyChange: stock,
          currentStock: stock,
          costPrice: purchasePrice,
          stockType: StockType.fixed,
        ),
      ];

      final selectProductUsageMaterial = ref.read(
        selectedProductUsageMaterialProvider,
      );

      if (selectProductUsageMaterial.values.isEmpty) {
        CustomSnackbar.showError(context, "Penggunaan bahan baku belum diatur");
        return;
      }

      try {
        await ref
            .read(rawMaterialControllerProvider.notifier)
            .saveRawMaterial(
              rawMaterial: rawMaterial,
              receiptItems: receiptItems,
              deleteItems: deleteItems,
              outletInventories: outletInventories,
              stockCards: _isEditing ? [] : stockCards,
            );

        if (!mounted) return;

        ref.invalidate(receiptItemIdProvider);

        ref.invalidate(deleteProductUsageMaterialProvider);

        CustomSnackbar.showSuccess(
          context,
          _isEditing ? "Bahan baku diperbarui" : "Bahan baku berhasil disimpan",
        );

        context.pop();
      } catch (e, st) {
        LogMessage.log.e(e.toString(), error: e, stackTrace: st);

        CustomSnackbar.showError(context, "Ups, terjadi kesalahan");
      }
    } catch (e) {
      CustomSnackbar.showError(context, "Format angka tidak valid");
    }
  }

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

        final messageActivity = ref.watch(messageActivityProvider);

        final currentUserRole = ref.watch(currentUserRoleProvider);

        final List<Unit> units = [];

        final unitState = ref.watch(unitStreamProvider);

        unitState.whenData((u) => units.addAll(u));

        final selectProductUsageMaterialState = ref.watch(
          selectedProductUsageMaterialProvider,
        );

        final rawMaterialControllerState = ref.watch(
          rawMaterialControllerProvider,
        );

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

            ref.invalidate(receiptItemIdProvider);

            ref.invalidate(deleteProductUsageMaterialProvider);

            context.pop();
          },
          child: SafeArea(
            top: false,
            bottom: true,
            right: false,
            left: false,
            child: Stack(
              children: [
                Scaffold(
                  backgroundColor: const Color(0xFFF9FAFB),
                  appBar: TopBackBarApp(
                    title: "Edit Bahan Baku",
                    onTap: () {
                      ref.invalidate(receiptItemIdProvider);

                      ref.invalidate(deleteProductUsageMaterialProvider);

                      context.pop();
                    },
                  ),

                  body: _isLoading
                      ? const EditRawMaterialShimmer()
                      : SingleChildScrollView(
                          padding: EdgeInsets.symmetric(
                            horizontal: 5.w,
                            vertical: 3.h,
                          ),
                          child: Form(
                            key: _formKey,
                            child: Column(
                              children: [
                                CustomTextFormField(
                                  label: "Nama Bahan Baku",
                                  hint: "Contoh: Kopi Susu Gula Aren",
                                  controller: _nameController,
                                  validator: (value) => _validator(
                                    value: value,
                                    message1: "Nama produk belum diisi",
                                  ),
                                  readOnly:
                                      (currentUserRole == UserRole.owner &&
                                          !_isMainOutlet) ||
                                      currentUserRole == UserRole.admin,
                                ),

                                SizedBox(height: 3.h),

                                CustomTextFormField(
                                  label: "Harga Beli",
                                  hint: "0",
                                  keyboardType: TextInputType.number,
                                  controller: _purchasePriceController,
                                  validator: (value) => _validator(
                                    value: value,
                                    message1: "Harga beli belum diisi",
                                    message2: "Harga beli harus lebih dari 0",
                                    isNumber: true,
                                    isPurchasePrice: true,
                                    errorMessage: "Harga beli tidak valid ",
                                  ),
                                ),

                                SizedBox(height: 3.h),

                                CustomTextFormField(
                                  label: _isEditing ? "Sisa Stok" : "Stok Awal",
                                  hint: "100",
                                  keyboardType: TextInputType.number,
                                  controller: _stockController,
                                  validator: (value) => _validator(
                                    value: value,
                                    message1: "Stok belum diisi",
                                    message2: "Stok harus lebih dari 0",
                                    isNumber: true,
                                    isStock: true,
                                    errorMessage: "Stok tidak valid",
                                  ),
                                  readOnly: _isEditing,
                                  onTapReadOnlyMessage:
                                      "Tambah stok di menu stok masuk",
                                ),

                                SizedBox(height: 3.h),

                                if (currentUserRole == UserRole.owner &&
                                    _isMainOutlet)
                                  DropdownWithAction(
                                    label: "Satuan",
                                    value: _selectedUnit,
                                    items: units,
                                    onChanged: (val) =>
                                        setState(() => _selectedUnit = val),
                                    onAdd: () async {
                                      FocusScope.of(context).unfocus();

                                      await Future.delayed(
                                        const Duration(milliseconds: 400),
                                      );

                                      showDialog(
                                        context: context,
                                        builder: (_) => const AddUnitScreen(),
                                      );
                                    },
                                    onEdit: () async {
                                      if (_selectedUnit == null) {
                                        CustomSnackbar.showError(
                                          context,
                                          "Satuan belum dipilih",
                                        );
                                      } else {
                                        final unitRepository = ref.read(
                                          unitRepositoryProvider,
                                        );

                                        final unit = await unitRepository
                                            .fetchUnitById(_selectedUnit!);

                                        if (unit != null) {
                                          showDialog(
                                            context: context,
                                            builder: (_) {
                                              return EditUnitScreen(unit: unit);
                                            },
                                          );
                                        } else {
                                          CustomSnackbar.showError(
                                            context,
                                            "Satuan produk tidak tersedia",
                                          );
                                        }
                                      }
                                    },
                                  )
                                else
                                  CustomTextFormField(
                                    label: "Satuan",
                                    controller: TextEditingController(
                                      text: units
                                          .firstWhere(
                                            (unit) => unit.id == _selectedUnit!,
                                          )
                                          .name,
                                    ),
                                    readOnly: true,
                                  ),
                                SizedBox(height: 3.h),

                                CustomSelector(
                                  isTablet: isTablet,
                                  title:
                                      selectProductUsageMaterialState
                                          .values
                                          .isEmpty
                                      ? "Atur penggunaan bahan baku"
                                      : "Lihat ${selectProductUsageMaterialState.values.length} penggunaan bahan baku",
                                  padding: EdgeInsets.symmetric(
                                    horizontal: 4.w,
                                    vertical: 2.h,
                                  ),
                                  fontSize: isTablet
                                      ? AppFontSize.medium.sp
                                      : AppFontSize.small.sp,
                                  onTap: () async {
                                    FocusScope.of(context).unfocus();

                                    await Future.delayed(
                                      const Duration(milliseconds: 400),
                                    );

                                    final isMainOutlet = await ref
                                        .read(outletRepositoryProvider)
                                        .fetchIsMainOutlet();

                                    if (_selectedUnit == null) {
                                      CustomSnackbar.showError(
                                        context,
                                        "Satuan belum dipilih",
                                      );
                                    } else {
                                      final unitRepository = ref.read(
                                        unitRepositoryProvider,
                                      );

                                      final unit = await unitRepository
                                          .fetchUnitById(_selectedUnit!);

                                      if (unit != null) {
                                        context.pushNamed(
                                          AppRoute
                                              .productUsageRawMaterialScreen,
                                          extra: {
                                            "raw-material-id": _rawMaterialId,
                                            "unit-name": unit.name,
                                            "is_main_outlet": isMainOutlet,
                                            "is_editing": _isEditing,
                                          },
                                        );
                                      } else {
                                        CustomSnackbar.showError(
                                          context,
                                          "Satuan produk tidak tersedia",
                                        );
                                      }
                                    }
                                  },
                                ),

                                SizedBox(height: 3.h),

                                SizedBox(
                                  width: double.infinity,
                                  height: 6.5.h,
                                  child: ElevatedButton(
                                    onPressed:
                                        rawMaterialControllerState.isLoading
                                        ? null
                                        : _saveRawMaterial,
                                    style: ElevatedButton.styleFrom(
                                      backgroundColor: AppColor.primaryColor,
                                      shape: RoundedRectangleBorder(
                                        borderRadius: BorderRadius.circular(
                                          2.5.w,
                                        ),
                                      ),
                                      disabledBackgroundColor:
                                          Colors.grey.shade300,
                                      elevation: 4,
                                    ),
                                    child: Text(
                                      "Simpan",
                                      style: TextStyle(
                                        color: Colors.white,
                                        fontSize: AppFontSize.medium.sp,
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                ),

                if (messageActivity != null)
                  PopupNotification(
                    isOwner: currentUserRole == UserRole.owner,
                    messages: messageActivity.messages,
                    type: messageActivity.type,
                  ),
              ],
            ),
          ),
        );
      },
    );
  }
}
