import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:collection/collection.dart';
import 'package:marco/controller/directory/add_contact_controller.dart';
import 'package:marco/helpers/widgets/my_spacing.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/my_text_style.dart';
import 'package:marco/model/directory/contact_model.dart';
import 'package:marco/helpers/utils/contact_picker_helper.dart';
import 'package:marco/helpers/utils/base_bottom_sheet.dart';

class AddContactBottomSheet extends StatefulWidget {
  final ContactModel? existingContact;
  const AddContactBottomSheet({super.key, this.existingContact});

  @override
  State<AddContactBottomSheet> createState() => _AddContactBottomSheetState();
}

class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
  final controller = Get.put(AddContactController());
  final formKey = GlobalKey<FormState>();

  final nameCtrl = TextEditingController();
  final orgCtrl = TextEditingController();
  final addrCtrl = TextEditingController();
  final descCtrl = TextEditingController();
  final tagCtrl = TextEditingController();

  final showAdvanced = false.obs;
  final bucketError = ''.obs;

  final emailCtrls = <TextEditingController>[].obs;
  final emailLabels = <RxString>[].obs;

  final phoneCtrls = <TextEditingController>[].obs;
  final phoneLabels = <RxString>[].obs;

  @override
  void initState() {
    super.initState();
    controller.resetForm();
    _initFields();
  }

  void _initFields() {
    final c = widget.existingContact;
    if (c != null) {
      nameCtrl.text = c.name;
      orgCtrl.text = c.organization;
      addrCtrl.text = c.address;
      descCtrl.text = c.description;

      emailCtrls.assignAll(c.contactEmails.isEmpty
          ? [TextEditingController()]
          : c.contactEmails
              .map((e) => TextEditingController(text: e.emailAddress)));
      emailLabels.assignAll(c.contactEmails.isEmpty
          ? ['Office'.obs]
          : c.contactEmails.map((e) => e.label.obs));

      phoneCtrls.assignAll(c.contactPhones.isEmpty
          ? [TextEditingController()]
          : c.contactPhones
              .map((p) => TextEditingController(text: p.phoneNumber)));
      phoneLabels.assignAll(c.contactPhones.isEmpty
          ? ['Work'.obs]
          : c.contactPhones.map((p) => p.label.obs));

      controller.enteredTags.assignAll(c.tags.map((e) => e.name));

      ever(controller.isInitialized, (bool ready) {
        if (ready) {
          final projectIds = c.projectIds;
          final bucketId = c.bucketIds.firstOrNull;
          final category = c.contactCategory?.name;

          if (category != null) controller.selectedCategory.value = category;

          if (projectIds != null) {
            controller.selectedProjects.assignAll(
              projectIds
                  .map((id) => controller.projectsMap.entries
                      .firstWhereOrNull((e) => e.value == id)
                      ?.key)
                  .whereType<String>()
                  .toList(),
            );
          }

          if (bucketId != null) {
            final name = controller.bucketsMap.entries
                .firstWhereOrNull((e) => e.value == bucketId)
                ?.key;
            if (name != null) controller.selectedBucket.value = name;
          }
        }
      });
    } else {
      emailCtrls.add(TextEditingController());
      emailLabels.add('Office'.obs);
      phoneCtrls.add(TextEditingController());
      phoneLabels.add('Work'.obs);
    }
  }

  @override
  void dispose() {
    nameCtrl.dispose();
    orgCtrl.dispose();
    addrCtrl.dispose();
    descCtrl.dispose();
    tagCtrl.dispose();
    emailCtrls.forEach((c) => c.dispose());
    phoneCtrls.forEach((c) => c.dispose());
    Get.delete<AddContactController>();
    super.dispose();
  }

  InputDecoration _inputDecoration(String hint) => InputDecoration(
        hintText: hint,
        hintStyle: MyTextStyle.bodySmall(xMuted: true),
        filled: true,
        fillColor: Colors.grey.shade100,
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide(color: Colors.grey.shade300),
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide(color: Colors.grey.shade300),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: const BorderSide(color: Colors.blueAccent, width: 1.5),
        ),
        contentPadding:
            const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
        isDense: true,
      );

  Widget _textField(String label, TextEditingController ctrl,
      {bool required = false, int maxLines = 1}) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        MyText.labelMedium(label),
        MySpacing.height(8),
        TextFormField(
          controller: ctrl,
          maxLines: maxLines,
          decoration: _inputDecoration("Enter $label"),
          validator: required
              ? (v) =>
                  (v == null || v.trim().isEmpty) ? "$label is required" : null
              : null,
        ),
      ],
    );
  }

  Widget _popupSelector(RxString selected, List<String> options, String hint) =>
      Obx(() {
        return GestureDetector(
          onTap: () async {
            final selectedItem = await showMenu<String>(
              context: context,
              position: RelativeRect.fromLTRB(100, 300, 100, 0),
              items: options
                  .map((e) => PopupMenuItem<String>(value: e, child: Text(e)))
                  .toList(),
            );
            if (selectedItem != null) selected.value = selectedItem;
          },
          child: Container(
            height: 48,
            padding: const EdgeInsets.symmetric(horizontal: 16),
            decoration: BoxDecoration(
              color: Colors.grey.shade100,
              borderRadius: BorderRadius.circular(12),
              border: Border.all(color: Colors.grey.shade300),
            ),
            alignment: Alignment.centerLeft,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(selected.value.isNotEmpty ? selected.value : hint,
                    style: const TextStyle(fontSize: 14)),
                const Icon(Icons.expand_more, size: 20),
              ],
            ),
          ),
        );
      });

  Widget _dynamicList(
      RxList<TextEditingController> ctrls,
      RxList<RxString> labels,
      String labelType,
      List<String> labelOptions,
      TextInputType type) {
    return Obx(() {
      return Column(
        children: List.generate(ctrls.length, (i) {
          return Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      MyText.labelMedium("$labelType Label"),
                      MySpacing.height(8),
                      _popupSelector(labels[i], labelOptions, "Label"),
                    ],
                  ),
                ),
                MySpacing.width(12),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      MyText.labelMedium(labelType),
                      MySpacing.height(8),
                      TextFormField(
                        controller: ctrls[i],
                        keyboardType: type,
                        maxLength: type == TextInputType.phone ? 10 : null,
                        inputFormatters: type == TextInputType.phone
                            ? [FilteringTextInputFormatter.digitsOnly]
                            : [],
                        decoration:
                            _inputDecoration("Enter $labelType").copyWith(
                          counterText: "",
                          suffixIcon: type == TextInputType.phone
                              ? IconButton(
                                  icon: const Icon(Icons.contact_phone,
                                      color: Colors.blue),
                                  onPressed: () async {
                                    final phone = await ContactPickerHelper
                                        .pickIndianPhoneNumber(context);
                                    if (phone != null) ctrls[i].text = phone;
                                  },
                                )
                              : null,
                        ),
                        validator: (value) {
                          if (value == null || value.trim().isEmpty)
                            return null;
                          final trimmed = value.trim();
                          if (type == TextInputType.phone &&
                              !RegExp(r'^[1-9][0-9]{9}$').hasMatch(trimmed)) {
                            return "Enter valid phone number";
                          }
                          if (type == TextInputType.emailAddress &&
                              !RegExp(r'^[\w.-]+@([\w-]+\.)+[\w-]{2,4}$')
                                  .hasMatch(trimmed)) {
                            return "Enter valid email";
                          }
                          return null;
                        },
                      ),
                    ],
                  ),
                ),
                if (ctrls.length > 1)
                  Padding(
                    padding: const EdgeInsets.only(top: 24),
                    child: IconButton(
                      icon: const Icon(Icons.remove_circle_outline,
                          color: Colors.red),
                      onPressed: () {
                        ctrls.removeAt(i);
                        labels.removeAt(i);
                      },
                    ),
                  ),
              ],
            ),
          );
        }),
      );
    });
  }

  Widget _tagInput() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          height: 48,
          child: TextField(
            controller: tagCtrl,
            onChanged: controller.filterSuggestions,
            onSubmitted: (v) {
              controller.addEnteredTag(v);
              tagCtrl.clear();
              controller.clearSuggestions();
            },
            decoration: _inputDecoration("Start typing to add tags"),
          ),
        ),
        Obx(() => controller.filteredSuggestions.isEmpty
            ? const SizedBox.shrink()
            : Container(
                margin: const EdgeInsets.only(top: 4),
                decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border.all(color: Colors.grey.shade300),
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: const [
                    BoxShadow(color: Colors.black12, blurRadius: 4)
                  ],
                ),
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: controller.filteredSuggestions.length,
                  itemBuilder: (_, i) {
                    final suggestion = controller.filteredSuggestions[i];
                    return ListTile(
                      dense: true,
                      title: Text(suggestion),
                      onTap: () {
                        controller.addEnteredTag(suggestion);
                        tagCtrl.clear();
                        controller.clearSuggestions();
                      },
                    );
                  },
                ),
              )),
        MySpacing.height(8),
        Obx(() => Wrap(
              spacing: 8,
              children: controller.enteredTags
                  .map((tag) => Chip(
                        label: Text(tag),
                        onDeleted: () => controller.removeEnteredTag(tag),
                      ))
                  .toList(),
            )),
      ],
    );
  }

  void _handleSubmit() {
    bool valid = formKey.currentState?.validate() ?? false;

    if (controller.selectedBucket.value.isEmpty) {
      bucketError.value = "Bucket is required";
      valid = false;
    } else {
      bucketError.value = "";
    }

    if (!valid) return;

    final emails = emailCtrls
        .asMap()
        .entries
        .where((e) => e.value.text.trim().isNotEmpty)
        .map((e) => {
              "label": emailLabels[e.key].value,
              "emailAddress": e.value.text.trim()
            })
        .toList();

    final phones = phoneCtrls
        .asMap()
        .entries
        .where((e) => e.value.text.trim().isNotEmpty)
        .map((e) => {
              "label": phoneLabels[e.key].value,
              "phoneNumber": e.value.text.trim()
            })
        .toList();

    controller.submitContact(
      id: widget.existingContact?.id,
      name: nameCtrl.text.trim(),
      organization: orgCtrl.text.trim(),
      emails: emails,
      phones: phones,
      address: addrCtrl.text.trim(),
      description: descCtrl.text.trim(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Obx(() {
      if (!controller.isInitialized.value) {
        return const Center(child: CircularProgressIndicator());
      }

      return BaseBottomSheet(
        title: widget.existingContact != null
            ? "Edit Contact"
            : "Create New Contact",
        onCancel: () => Get.back(),
        onSubmit: _handleSubmit,
        isSubmitting: controller.isSubmitting.value,
        child: Form(
          key: formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              _textField("Name", nameCtrl, required: true),
              MySpacing.height(16),
              _textField("Organization", orgCtrl, required: true),
              MySpacing.height(16),
              MyText.labelMedium("Select Bucket"),
              MySpacing.height(8),
              Stack(
                children: [
                  _popupSelector(controller.selectedBucket, controller.buckets,
                      "Select Bucket"),
                  Positioned(
                    left: 0,
                    right: 0,
                    top: 56,
                    child: Obx(() => bucketError.value.isEmpty
                        ? const SizedBox.shrink()
                        : Padding(
                            padding:
                                const EdgeInsets.symmetric(horizontal: 8.0),
                            child: Text(bucketError.value,
                                style: const TextStyle(
                                    color: Colors.red, fontSize: 12)),
                          )),
                  ),
                ],
              ),
              MySpacing.height(24),
              Obx(() => GestureDetector(
                    onTap: () => showAdvanced.toggle(),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        MyText.labelLarge("Advanced Details (Optional)",
                            fontWeight: 600),
                        Icon(showAdvanced.value
                            ? Icons.expand_less
                            : Icons.expand_more),
                      ],
                    ),
                  )),
              Obx(() => showAdvanced.value
                  ? Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        MySpacing.height(24),
                        _dynamicList(
                            emailCtrls,
                            emailLabels,
                            "Email",
                            ["Office", "Personal", "Other"],
                            TextInputType.emailAddress),
                        TextButton.icon(
                          onPressed: () {
                            emailCtrls.add(TextEditingController());
                            emailLabels.add("Office".obs);
                          },
                          icon: const Icon(Icons.add),
                          label: const Text("Add Email"),
                        ),
                        _dynamicList(phoneCtrls, phoneLabels, "Phone",
                            ["Work", "Mobile", "Other"], TextInputType.phone),
                        TextButton.icon(
                          onPressed: () {
                            phoneCtrls.add(TextEditingController());
                            phoneLabels.add("Work".obs);
                          },
                          icon: const Icon(Icons.add),
                          label: const Text("Add Phone"),
                        ),
                        MySpacing.height(16),
                        MyText.labelMedium("Category"),
                        MySpacing.height(8),
                        _popupSelector(controller.selectedCategory,
                            controller.categories, "Select Category"),
                        MySpacing.height(16),
                        MyText.labelMedium("Tags"),
                        MySpacing.height(8),
                        _tagInput(),
                        MySpacing.height(16),
                        _textField("Address", addrCtrl),
                        MySpacing.height(16),
                        _textField("Description", descCtrl),
                      ],
                    )
                  : const SizedBox.shrink()),
            ],
          ),
        ),
      );
    });
  }
}
