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_snackbar.dart';
import 'package:on_field_work/helpers/widgets/my_text.dart';
import 'package:on_field_work/helpers/widgets/image_viewer_dialog.dart';
import 'package:on_field_work/model/document/master_document_type_model.dart';
import 'package:on_field_work/helpers/widgets/my_text_style.dart';
import 'package:url_launcher/url_launcher.dart';

class DocumentEditBottomSheet extends StatefulWidget {
  final Map<String, dynamic> documentData;
  final Function(Map<String, dynamic>) onSubmit;

  const DocumentEditBottomSheet({
    Key? key,
    required this.documentData,
    required this.onSubmit,
  }) : super(key: key);

  @override
  State<DocumentEditBottomSheet> createState() =>
      _DocumentEditBottomSheetState();
}

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

  final TextEditingController _docIdController = TextEditingController();
  final TextEditingController _docNameController = TextEditingController();
  final TextEditingController _descriptionController = TextEditingController();
  String? latestVersionUrl;

  File? selectedFile;
  bool fileChanged = false;
  @override
  void initState() {
    super.initState();

    _docIdController.text = widget.documentData["documentId"] ?? "";
    _docNameController.text = widget.documentData["name"] ?? "";
    _descriptionController.text = widget.documentData["description"] ?? "";

    // Tags
    if (widget.documentData["tags"] != null) {
      controller.enteredTags.assignAll(
        List<String>.from(
          (widget.documentData["tags"] as List)
              .map((t) => t is String ? t : t["name"]),
        ),
      );
    }

    // --- Convert category map to DocumentType ---
    if (widget.documentData["category"] != null) {
      controller.selectedCategory =
          DocumentType.fromJson(widget.documentData["category"]);
    }

    // Type (if separate)
    if (widget.documentData["type"] != null) {
      controller.selectedType =
          DocumentType.fromJson(widget.documentData["type"]);
    }
    // Fetch latest version URL if attachment exists
    final latestVersion = widget.documentData["attachment"];
    if (latestVersion != null) {
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        final url = await controller.fetchPresignedUrl(latestVersion["id"]);
        if (url != null) {
          setState(() {
            latestVersionUrl = url;
          });
        }
      });
    }
  }

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

  void _handleSubmit() async {
    if (!(_formKey.currentState?.validate() ?? false)) return;

    // ✅ Validate only if user picked a new file
    if (fileChanged && selectedFile != null) {
      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;
        }
      }
    }

    final payload = {
      "id": widget.documentData["id"],
      "documentId": _docIdController.text.trim(),
      "name": _docNameController.text.trim(),
      "description": _descriptionController.text.trim(),
      "documentTypeId": controller.selectedType?.id,
      "tags": controller.enteredTags
          .map((t) => {"name": t, "isActive": true})
          .toList(),
    };

// ✅ Always include attachment logic
    if (fileChanged) {
      if (selectedFile != null) {
        // User picked new file
        payload["attachment"] = {
          "fileName": controller.selectedFileName,
          "base64Data": controller.selectedFileBase64,
          "contentType": controller.selectedFileContentType,
          "fileSize": controller.selectedFileSize,
          "isActive": true,
        };
      } else {
        // User explicitly removed file
        payload["attachment"] = null;
      }
    } else {
      // ✅ User did NOT touch the attachment → send null explicitly
      payload["attachment"] = null;
    }

    // else: do nothing → existing attachment remains as is

    final success = await controller.editDocument(payload);
    if (success) {
      widget.onSubmit(payload);
      Navigator.pop(context);
    }
  }

  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;
        fileChanged = true;
        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) {
    return BaseBottomSheet(
      title: "Edit Document",
      onCancel: () => Navigator.pop(context),
      onSubmit: _handleSubmit,
      child: Form(
        key: _formKey,
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              MySpacing.height(16),

              /// Document ID
              LabeledInput(
                label: "Document ID",
                hint: "Enter Document ID",
                controller: _docIdController,
                validator: (v) =>
                    v == null || v.trim().isEmpty ? "Required" : null,
                isRequired: true,
              ),
              MySpacing.height(16),

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

              /// Document Category (Read-only, non-editable)
              LabeledInput(
                label: "Document Category",
                hint: "",
                controller: TextEditingController(
                    text: controller.selectedCategory?.name ?? ""),
                validator: (_) => null,
                isRequired: false,
                // Disable interaction
                readOnly: true,
              ),

              MySpacing.height(16),

              /// Document Type (Read-only, non-editable)
              LabeledInput(
                label: "Document Type",
                hint: "",
                controller: TextEditingController(
                    text: controller.selectedType?.name ?? ""),
                validator: (_) => null,
                isRequired: false,
                readOnly: true,
              ),

              MySpacing.height(24),

              /// Attachment Section
              AttachmentSectionSingle(
                attachmentFile: selectedFile,
                attachmentUrl: latestVersionUrl,
                onPick: _pickFile,
                onRemove: () => setState(() {
                  selectedFile = null;
                  fileChanged = true;
                  controller.selectedFileName = null;
                  controller.selectedFileBase64 = null;
                  controller.selectedFileContentType = null;
                  controller.selectedFileSize = null;
                  latestVersionUrl = 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 Section
              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: (v) =>
                    v == null || v.trim().isEmpty ? "Required" : null,
                isRequired: true,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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 (Rewritten) ----------------
class AttachmentSectionSingle extends StatelessWidget {
  final File? attachmentFile; // Local file
  final String? attachmentUrl; // Online latest version URL
  final VoidCallback onPick;
  final VoidCallback? onRemove;

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

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

    Widget buildTile({File? file, String? url}) {
      final isImage = file != null
          ? allowedImageExtensions
              .contains(file.path.split('.').last.toLowerCase())
          : url != null
              ? allowedImageExtensions
                  .contains(url.split('.').last.toLowerCase())
              : false;

      final fileName = file != null
          ? file.path.split('/').last
          : url != null
              ? url.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: () async {
              if (isImage && file != null) {
                showDialog(
                  context: context,
                  builder: (_) => ImageViewerDialog(
                    imageSources: [file],
                    initialIndex: 0,
                  ),
                );
              } else if (url != null) {
                final uri = Uri.parse(url);
                if (await canLaunchUrl(uri)) {
                  await launchUrl(uri, mode: LaunchMode.externalApplication);
                } else {
                  showAppSnackbar(
                    title: "Error",
                    message: "Could not open document",
                    type: SnackbarType.error,
                  );
                }
              }
            },
            child: Container(
              width: 100,
              height: 100,
              margin: const EdgeInsets.only(right: 8),
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey.shade300),
                borderRadius: BorderRadius.circular(8),
                color: Colors.grey.shade100,
              ),
              child: isImage && file != null
                  ? 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),
                      ],
                    ),
            ),
          ),
          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,
      mainAxisSize: MainAxisSize.min, // prevent overflow
      children: [
        Row(
          children: const [
            Text("Attachment", style: TextStyle(fontWeight: FontWeight.w600)),
            Text(" *",
                style:
                    TextStyle(color: Colors.red, fontWeight: FontWeight.bold))
          ],
        ),
        const SizedBox(height: 8),
        SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Row(
            children: [
              if (attachmentFile != null)
                buildTile(file: attachmentFile)
              else if (attachmentUrl != null)
                buildTile(url: attachmentUrl)
              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 bool readOnly; // <-- Add this

  const LabeledInput({
    Key? key,
    required this.label,
    required this.hint,
    required this.controller,
    required this.validator,
    this.isRequired = false,
    this.readOnly = false, // default false
  }) : 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,
            readOnly: readOnly, // <-- Use the new property here
            decoration: _inputDecoration(context, hint),
          ),
        ],
      );

  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"),
                ],
              ),
            ),
          ),
        ],
      );
}
