import 'dart:convert';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:on_field_work/controller/document/document_upload_controller.dart';
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
import 'package:on_field_work/helpers/widgets/my_text.dart';
import 'package:on_field_work/helpers/widgets/my_text_style.dart';
import 'package:on_field_work/helpers/widgets/image_viewer_dialog.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';

class DocumentUploadBottomSheet extends StatefulWidget {
  final Function(Map<String, dynamic>) onSubmit;
  final bool isEmployee;
  const DocumentUploadBottomSheet({
    Key? key,
    required this.onSubmit,
    this.isEmployee = false,
  }) : super(key: key);

  @override
  State<DocumentUploadBottomSheet> createState() =>
      _DocumentUploadBottomSheetState();
}

class _DocumentUploadBottomSheetState extends State<DocumentUploadBottomSheet> {
  final _formKey = GlobalKey<FormState>();
  final controller = Get.put(DocumentUploadController());

  final TextEditingController _docIdController = TextEditingController();
  final TextEditingController _docNameController = TextEditingController();
  final TextEditingController _descriptionController = TextEditingController();

  File? selectedFile;

  @override
  void dispose() {
    _docIdController.dispose();
    _docNameController.dispose();
    _descriptionController.dispose();
    super.dispose();
  }

  void _handleSubmit() {
    final formState = _formKey.currentState;

    // 1️⃣ Validate form fields
    if (!(formState?.validate() ?? false)) {
      // Collect first validation error
      final errorFields = [
        {"label": "Document ID", "value": _docIdController.text.trim()},
        {"label": "Document Name", "value": _docNameController.text.trim()},
        {"label": "Description", "value": _descriptionController.text.trim()},
      ];

      for (var field in errorFields) {
        if (field["value"] == null || (field["value"] as String).isEmpty) {
          showAppSnackbar(
            title: "Error",
            message: "${field["label"]} is required",
            type: SnackbarType.error,
          );
          return;
        }
      }
      return;
    }

    // 2️⃣ Validate file attachment
    if (selectedFile == null) {
      showAppSnackbar(
        title: "Error",
        message: "Please attach a document",
        type: SnackbarType.error,
      );
      return;
    }

    // 3️⃣ Validate document category based on employee/project
    if (controller.selectedCategory != null) {
      final selectedCategoryName = controller.selectedCategory!.name;

      if (widget.isEmployee && selectedCategoryName != 'Employee Documents') {
        showAppSnackbar(
          title: "Error",
          message:
              "Only 'Employee Documents' can be uploaded from the Employee screen. Please select the correct document type.",
          type: SnackbarType.error,
        );
        return;
      } else if (!widget.isEmployee &&
          selectedCategoryName != 'Project Documents') {
        showAppSnackbar(
          title: "Error",
          message:
              "Only 'Project Documents' can be uploaded from the Project screen. Please select the correct document type.",
          type: SnackbarType.error,
        );
        return;
      }
    } else {
      showAppSnackbar(
        title: "Error",
        message: "Please select a Document Category before uploading.",
        type: SnackbarType.error,
      );
      return;
    }

    // 4️⃣ Validate file size
    final maxSizeMB = controller.selectedType?.maxSizeAllowedInMB;
    if (maxSizeMB != null && controller.selectedFileSize != null) {
      final fileSizeMB = controller.selectedFileSize! / (1024 * 1024);
      if (fileSizeMB > maxSizeMB) {
        showAppSnackbar(
          title: "Error",
          message: "File size exceeds $maxSizeMB MB limit",
          type: SnackbarType.error,
        );
        return;
      }
    }

    // 5️⃣ Validate file type
    final allowedType = controller.selectedType?.allowedContentType;
    if (allowedType != null && controller.selectedFileContentType != null) {
      if (!allowedType
          .toLowerCase()
          .contains(controller.selectedFileContentType!.toLowerCase())) {
        showAppSnackbar(
          title: "Error",
          message: "Only $allowedType files are allowed for this type",
          type: SnackbarType.error,
        );
        return;
      }
    }

    // 6️⃣ Prepare payload
    final payload = {
      "documentId": _docIdController.text.trim(),
      "name": _docNameController.text.trim(),
      "description": _descriptionController.text.trim(),
      "documentTypeId": controller.selectedType?.id,
      "attachment": {
        "fileName": controller.selectedFileName,
        "base64Data": controller.selectedFileBase64,
        "contentType": controller.selectedFileContentType,
        "fileSize": controller.selectedFileSize,
        "isActive": true,
      },
      "tags": controller.enteredTags
          .map((t) => {"name": t, "isActive": true})
          .toList(),
    };

    // 7️⃣ Submit
    widget.onSubmit(payload);

    // 8️⃣ Show success message
    showAppSnackbar(
      title: "Success",
      message: "Document submitted successfully",
      type: SnackbarType.success,
    );
  }

  Future<void> _pickFile() async {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['pdf', 'jpg', 'png', 'jpeg'],
    );

    if (result != null && result.files.single.path != null) {
      final file = File(result.files.single.path!);
      final fileName = result.files.single.name;
      final fileBytes = await file.readAsBytes();
      final base64Data = base64Encode(fileBytes);

      setState(() {
        selectedFile = file;
        controller.selectedFileName = fileName;
        controller.selectedFileBase64 = base64Data;
        controller.selectedFileContentType =
            result.files.single.extension?.toLowerCase() == "pdf"
                ? "application/pdf"
                : "image/${result.files.single.extension?.toLowerCase()}";
        controller.selectedFileSize = (fileBytes.length / 1024).round();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final sheetTitle = widget.isEmployee
        ? "Upload Employee Document"
        : "Upload Project Document";
    return BaseBottomSheet(
      title: sheetTitle,
      onCancel: () => Navigator.pop(context),
      onSubmit: _handleSubmit,
      child: Form(
        key: _formKey,
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              MySpacing.height(16),

              /// Document Category
              Obx(() {
                if (controller.isLoading.value &&
                    controller.categories.isEmpty) {
                  return const Center(child: CircularProgressIndicator());
                }

                return LabeledDropdown(
                  label: "Document Category",
                  hint: "Select Category",
                  value: controller.selectedCategory?.name,
                  items: controller.categories.map((c) => c.name).toList(),
                  onChanged: (selected) async {
                    final category = controller.categories
                        .firstWhere((c) => c.name == selected);
                    setState(() => controller.selectedCategory = category);
                    await controller.fetchDocumentTypes(category.id);
                  },
                  isRequired: true,
                );
              }),
              MySpacing.height(16),

              /// Document Type
              Obx(() {
                if (controller.documentTypes.isEmpty) {
                  return const SizedBox.shrink();
                }
                return LabeledDropdown(
                  label: "Document Type",
                  hint: "Select Type",
                  value: controller.selectedType?.name,
                  items: controller.documentTypes.map((t) => t.name).toList(),
                  onChanged: (selected) {
                    final type = controller.documentTypes
                        .firstWhere((t) => t.name == selected);
                    setState(() => controller.selectedType = type);
                  },
                  isRequired: true,
                );
              }),
              MySpacing.height(12),

              /// Document ID
              LabeledInput(
                label: "Document ID",
                hint: "Enter Document ID",
                controller: _docIdController,
                validator: (value) {
                  if (value == null || value.trim().isEmpty) {
                    return "Required";
                  }

                  // ✅ Regex validation if enabled
                  final selectedType = controller.selectedType;
                  if (selectedType != null &&
                      selectedType.isValidationRequired &&
                      selectedType.regexExpression != null &&
                      selectedType.regexExpression!.isNotEmpty) {
                    final regExp = RegExp(selectedType.regexExpression!);
                    if (!regExp.hasMatch(value.trim())) {
                      return "Invalid ${selectedType.name} format";
                    }
                  }

                  return null;
                },
                isRequired: true,
              ),

              MySpacing.height(16),

              /// Document Name
              LabeledInput(
                label: "Document Name",
                hint: "e.g., PAN Card",
                controller: _docNameController,
                validator: (value) =>
                    value == null || value.trim().isEmpty ? "Required" : null,
                isRequired: true,
              ),
              MySpacing.height(16),

              /// Single Attachment Section
              AttachmentSectionSingle(
                attachment: selectedFile,
                onPick: _pickFile,
                onRemove: () => setState(() {
                  selectedFile = null;
                  controller.selectedFileName = null;
                  controller.selectedFileBase64 = null;
                  controller.selectedFileContentType = null;
                  controller.selectedFileSize = null;
                }),
              ),

              if (controller.selectedType?.maxSizeAllowedInMB != null)
                Padding(
                  padding: const EdgeInsets.only(top: 8),
                  child: Text(
                    "Max file size: ${controller.selectedType!.maxSizeAllowedInMB} MB",
                    style: const TextStyle(color: Colors.grey, fontSize: 12),
                  ),
                ),
              MySpacing.height(16),

              /// Tags
              MyText.labelMedium("Tags"),
              MySpacing.height(8),
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SizedBox(
                    height: 56,
                    child: TextFormField(
                      controller: controller.tagCtrl,
                      onChanged: controller.filterSuggestions,
                      onFieldSubmitted: (v) {
                        controller.addEnteredTag(v);
                        controller.tagCtrl.clear();
                        controller.clearSuggestions();
                      },
                      decoration: InputDecoration(
                        hintText: "Start typing to add tags",
                        hintStyle: MyTextStyle.bodySmall(xMuted: true),
                        filled: true,
                        fillColor: Colors.grey.shade100,
                        border: _inputBorder(),
                        enabledBorder: _inputBorder(),
                        focusedBorder: _inputFocusedBorder(),
                        contentPadding: MySpacing.all(16),
                      ),
                    ),
                  ),
                  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);
                                  controller.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(),
                      )),
                ],
              ),
              MySpacing.height(16),

              /// Description
              LabeledInput(
                label: "Description",
                hint: "Enter short description",
                controller: _descriptionController,
                validator: (value) =>
                    value == null || value.trim().isEmpty ? "Required" : null,
                isRequired: true,
                maxLines: 3,
              ),
            ],
          ),
        ),
      ),
    );
  }

  OutlineInputBorder _inputBorder() => OutlineInputBorder(
        borderRadius: BorderRadius.circular(12),
        borderSide: BorderSide(color: Colors.grey.shade300),
      );

  OutlineInputBorder _inputFocusedBorder() => const OutlineInputBorder(
        borderRadius: BorderRadius.all(Radius.circular(12)),
        borderSide: BorderSide(color: Colors.blueAccent, width: 1.5),
      );
}

/// ---------------- Single Attachment Widget ----------------
class AttachmentSectionSingle extends StatelessWidget {
  final File? attachment;
  final VoidCallback onPick;
  final VoidCallback? onRemove;

  const AttachmentSectionSingle({
    Key? key,
    this.attachment,
    required this.onPick,
    this.onRemove,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final allowedImageExtensions = ['jpg', 'jpeg', 'png'];

    Widget buildTile(File file) {
      final isImage = allowedImageExtensions
          .contains(file.path.split('.').last.toLowerCase());

      final fileName = file.path.split('/').last;

      IconData fileIcon = Icons.insert_drive_file;
      Color iconColor = Colors.blueGrey;

      if (!isImage) {
        final ext = fileName.split('.').last.toLowerCase();
        switch (ext) {
          case 'pdf':
            fileIcon = Icons.picture_as_pdf;
            iconColor = Colors.redAccent;
            break;
          case 'doc':
          case 'docx':
            fileIcon = Icons.description;
            iconColor = Colors.blueAccent;
            break;
          case 'xls':
          case 'xlsx':
            fileIcon = Icons.table_chart;
            iconColor = Colors.green;
            break;
          case 'txt':
            fileIcon = Icons.article;
            iconColor = Colors.grey;
            break;
        }
      }

      return Stack(
        clipBehavior: Clip.none,
        children: [
          GestureDetector(
            onTap: () {
              if (isImage) {
                showDialog(
                  context: context,
                  builder: (_) => ImageViewerDialog(
                    imageSources: [file],
                    initialIndex: 0,
                  ),
                );
              }
            },
            child: Container(
              width: 100,
              height: 100,
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey.shade300),
                borderRadius: BorderRadius.circular(8),
                color: Colors.grey.shade100,
              ),
              child: isImage
                  ? ClipRRect(
                      borderRadius: BorderRadius.circular(8),
                      child: Image.file(file, fit: BoxFit.cover),
                    )
                  : Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(fileIcon, color: iconColor, size: 30),
                        const SizedBox(height: 4),
                        Text(
                          fileName.split('.').last.toUpperCase(),
                          style: TextStyle(
                              fontSize: 10,
                              fontWeight: FontWeight.bold,
                              color: iconColor),
                        ),
                      ],
                    ),
            ),
          ),
          if (onRemove != null)
            Positioned(
              top: -6,
              right: -6,
              child: IconButton(
                icon: const Icon(Icons.close, color: Colors.red, size: 18),
                onPressed: onRemove,
              ),
            ),
        ],
      );
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: const [
            Text("Attachment", style: TextStyle(fontWeight: FontWeight.w600)),
            Text(" *",
                style:
                    TextStyle(color: Colors.red, fontWeight: FontWeight.bold))
          ],
        ),
        const SizedBox(height: 8),
        Row(
          children: [
            if (attachment != null)
              buildTile(attachment!)
            else
              GestureDetector(
                onTap: onPick,
                child: Container(
                  width: 100,
                  height: 100,
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey.shade300),
                    borderRadius: BorderRadius.circular(8),
                    color: Colors.grey.shade100,
                  ),
                  child: const Icon(Icons.add, size: 40, color: Colors.grey),
                ),
              ),
          ],
        ),
      ],
    );
  }
}

// ---- Reusable Widgets ----

class LabeledInput extends StatelessWidget {
  final String label;
  final String hint;
  final TextEditingController controller;
  final String? Function(String?) validator;
  final bool isRequired;
  final int maxLines;

  const LabeledInput({
    Key? key,
    required this.label,
    required this.hint,
    required this.controller,
    required this.validator,
    this.isRequired = false,
    this.maxLines = 1,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) => Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              MyText.labelMedium(label),
              if (isRequired)
                const Text(
                  " *",
                  style:
                      TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
                ),
            ],
          ),
          MySpacing.height(8),
          TextFormField(
            controller: controller,
            validator: validator,
            decoration: _inputDecoration(context, hint),
            maxLines: maxLines,
          ),
        ],
      );

  InputDecoration _inputDecoration(BuildContext context, 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: const OutlineInputBorder(
          borderRadius: BorderRadius.all(Radius.circular(12)),
          borderSide: BorderSide(color: Colors.blueAccent, width: 1.5),
        ),
        contentPadding: MySpacing.all(16),
      );
}

class LabeledDropdown extends StatefulWidget {
  final String label;
  final String hint;
  final String? value;
  final List<String> items;
  final ValueChanged<String> onChanged;
  final bool isRequired;

  const LabeledDropdown({
    Key? key,
    required this.label,
    required this.hint,
    required this.value,
    required this.items,
    required this.onChanged,
    this.isRequired = false,
  }) : super(key: key);

  @override
  State<LabeledDropdown> createState() => _LabeledDropdownState();
}

class _LabeledDropdownState extends State<LabeledDropdown> {
  final GlobalKey _dropdownKey = GlobalKey();

  @override
  Widget build(BuildContext context) => Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              MyText.labelMedium(widget.label),
              if (widget.isRequired)
                const Text(
                  " *",
                  style:
                      TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
                ),
            ],
          ),
          MySpacing.height(8),
          GestureDetector(
            key: _dropdownKey,
            onTap: () async {
              final RenderBox renderBox =
                  _dropdownKey.currentContext!.findRenderObject() as RenderBox;
              final Offset offset = renderBox.localToGlobal(Offset.zero);
              final Size size = renderBox.size;
              final RelativeRect position = RelativeRect.fromLTRB(
                offset.dx,
                offset.dy + size.height,
                offset.dx + size.width,
                offset.dy,
              );
              final selected = await showMenu<String>(
                context: context,
                position: position,
                items: widget.items
                    .map((item) => PopupMenuItem<String>(
                          value: item,
                          child: Text(item),
                        ))
                    .toList(),
              );
              if (selected != null) widget.onChanged(selected);
            },
            child: AbsorbPointer(
              child: TextFormField(
                readOnly: true,
                controller: TextEditingController(text: widget.value ?? ""),
                validator: (value) =>
                    widget.isRequired && (value == null || value.isEmpty)
                        ? "Required"
                        : null,
                decoration: _inputDecoration(context, widget.hint).copyWith(
                  suffixIcon: const Icon(Icons.expand_more),
                ),
              ),
            ),
          ),
        ],
      );

  InputDecoration _inputDecoration(BuildContext context, 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: const OutlineInputBorder(
          borderRadius: BorderRadius.all(Radius.circular(12)),
          borderSide: BorderSide(color: Colors.blueAccent, width: 1.5),
        ),
        contentPadding: MySpacing.all(16),
      );
}

class FilePickerTile extends StatelessWidget {
  final String? pickedFile;
  final VoidCallback onTap;
  final bool isRequired;

  const FilePickerTile({
    Key? key,
    required this.pickedFile,
    required this.onTap,
    this.isRequired = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) => Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              MyText.labelMedium("Attachments"),
              if (isRequired)
                const Text(
                  " *",
                  style:
                      TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
                ),
            ],
          ),
          MySpacing.height(8),
          GestureDetector(
            onTap: onTap,
            child: Container(
              padding: MySpacing.all(16),
              decoration: BoxDecoration(
                color: Colors.grey.shade100,
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: Colors.grey.shade300),
              ),
              child: Row(
                children: [
                  const Icon(Icons.upload_file, color: Colors.blueAccent),
                  const SizedBox(width: 12),
                  Text(pickedFile ?? "Choose File"),
                ],
              ),
            ),
          ),
        ],
      );
}
