import React, { useState, useRef, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/shared/common/ui/dialog";
import { Button } from "@/shared/common/ui/button";
import { Textarea } from "@/shared/common/ui/textarea";
import { Label } from "@/shared/common/ui/label";
import {
  Paperclip,
  UploadCloud,
  X,
  Send,
  Loader2,
  FileText,
  FileImage,
  FileArchive,
  Pencil,
} from "lucide-react";
import { uploadReplies } from "../services/api/newFileService";
import { AttachmentInfo } from "../dto/userRecords/userRecordsDto";
import { addReplies, editReplies } from "../services/api/recordOfficerService";

export interface ReplyToEdit {
  id: string;
  comment: string;
  attachment?: {
    fileName: string;
    contentType: string;
    size: number;
    originalname: string;
  } | null;
  attachments?: AttachmentInfo[];
}

interface ReplyModalProps {
  isOpen: boolean;
  onClose: () => void;
  recordId: string;
  onSuccess?: () => void;
  /** When provided the modal operates in edit mode */
  replyToEdit?: ReplyToEdit | null;
}

const formatFileSize = (bytes: number) => {
  if (bytes === 0) return "0 Bytes";
  const k = 1024;
  const sizes = ["Bytes", "KB", "MB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
};

export const ReplyModal: React.FC<ReplyModalProps> = ({
  isOpen,
  onClose,
  recordId,
  onSuccess,
  replyToEdit,
}) => {
  const { t } = useTranslation();
  const fileInputRef = useRef<HTMLInputElement>(null);

  const isEditMode = Boolean(replyToEdit);

  const [comment, setComment] = useState("");
  const [files, setFiles] = useState<File[]>([]);
  /** Existing server-side attachment (edit mode only) */
  const [existingAttachment, setExistingAttachment] = useState<any | null>(
    null,
  );
  const [dragActive, setDragActive] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Pre-fill form when editing
  useEffect(() => {
    if (isOpen && replyToEdit) {
      setComment(replyToEdit.comment || "");
      const att =
        replyToEdit.attachment ||
        (replyToEdit.attachments && replyToEdit.attachments[0]) ||
        null;
      setExistingAttachment(att);
      setFiles([]);
      setError(null);
    } else if (isOpen && !replyToEdit) {
      // Reset for add mode
      setComment("");
      setExistingAttachment(null);
      setFiles([]);
      setError(null);
    }
  }, [isOpen, replyToEdit]);

  const resetForm = () => {
    setComment("");
    setFiles([]);
    setExistingAttachment(null);
    setError(null);
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const handleClose = () => {
    if (isLoading) return;
    resetForm();
    onClose();
  };

  const handleDrag = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === "dragenter" || e.type === "dragover") {
      setDragActive(true);
    } else if (e.type === "dragleave") {
      setDragActive(false);
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
      setFiles([e.dataTransfer.files[0]]);
      setExistingAttachment(null);
      setError(null);
    }
  };

  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      setFiles([e.target.files[0]]);
      setExistingAttachment(null);
      setError(null);
    }
  };

  const removeFile = (index: number) => {
    setFiles((prev) => prev.filter((_, i) => i !== index));
    // Reset the input so the browser fires onChange even if the same file is picked again
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const removeExistingAttachment = () => {
    setExistingAttachment(null);
  };

  const getFileIcon = (type: string) => {
    if (type.startsWith("image/"))
      return <FileImage className="h-5 w-5 text-primary-500" />;
    if (type === "application/pdf")
      return <FileText className="h-5 w-5 text-primary-500" />;
    if (type.includes("zip") || type.includes("rar"))
      return <FileArchive className="h-5 w-5 text-primary-500" />;
    return <Paperclip className="h-5 w-5 text-primary-500" />;
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!comment.trim()) {
      setError(t("validation.commentRequired", "Comment is required"));
      return;
    }

    setIsLoading(true);
    setError(null);

    try {
      let attachmentObj = null;

      if (files.length > 0) {
        const attachments = await uploadReplies(files);
        const uploadedFile = Array.isArray(attachments)
          ? attachments[0]
          : attachments;
        if (uploadedFile) {
          attachmentObj = {
            fileName: uploadedFile.fileName,
            contentType: uploadedFile.contentType,
            size: uploadedFile.size,
            originalname: uploadedFile.originalname,
            bucket: uploadedFile.bucket,
          };
        }
      } else if (existingAttachment) {
        const fileInfo = existingAttachment.fileInfo || existingAttachment;
        attachmentObj = {
          fileName: fileInfo.fileName,
          contentType: fileInfo.contentType,
          size: fileInfo.size,
          originalname:
            fileInfo.originalname || existingAttachment.name?.en || "File",
          bucket: fileInfo.bucket,
        };
      }

      if (isEditMode && replyToEdit) {
        // --- EDIT ---
        const editPayload = {
          recordId,
          comment,
          attachment: attachmentObj,
        };
        await editReplies(replyToEdit.id, editPayload);
        toast.success(t("msg.replyEdited", "Reply updated successfully!"));
      } else {
        // --- ADD ---
        const replyPayload = {
          recordId,
          comment,
          attachment: attachmentObj,
        };
        await addReplies(replyPayload);
        toast.success(t("msg.replyAdded", "Reply added successfully!"));
      }

      resetForm();
      onClose();
      if (onSuccess) onSuccess();
    } catch (err: any) {
      const serverMessage =
        err?.response?.data?.message ||
        err?.response?.data?.exception?.response?.message ||
        err?.message ||
        null;
      setError(
        serverMessage ??
          t("msg.replyError", "An error occurred while saving the reply."),
      );
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <Dialog
      open={isOpen}
      onOpenChange={(open) => {
        if (!open) handleClose();
      }}
    >
      <DialogContent className="max-w-lg max-h-[90vh] bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow-2xl p-6 rounded-xl flex flex-col">
        <DialogHeader className="border-b border-gray-100 dark:border-gray-700 pb-3">
          <DialogTitle className="text-xl font-bold text-gray-900 dark:text-white flex items-center gap-2">
            {isEditMode ? (
              <>
                <Pencil className="h-5 w-5 text-primary-500" />
                {t("common.editReply", "Edit Reply")}
              </>
            ) : (
              <>
                <Send className="h-5 w-5 text-primary-500" />
                {t("common.addReply", "Add Reply")}
              </>
            )}
          </DialogTitle>
        </DialogHeader>

        <form
          onSubmit={handleSubmit}
          className="space-y-5 pt-3 flex-1 overflow-y-auto pr-2 pb-2"
        >
          {/* Comment input */}
          <div className="space-y-2">
            <Label
              htmlFor="reply-comment"
              className="text-sm font-semibold text-gray-700 dark:text-gray-300"
            >
              {t("common.replyMessage", "Reply Message")}{" "}
              <span className="text-red-500">*</span>
            </Label>
            <Textarea
              id="reply-comment"
              placeholder={t(
                "common.replyPlaceholder",
                "Write your reply message or comment here...",
              )}
              value={comment}
              onChange={(e) => {
                setComment(e.target.value);
                if (e.target.value.trim()) setError(null);
              }}
              rows={4}
              disabled={isLoading}
              className="resize-none border-gray-300 focus:border-primary-500 dark:border-gray-600 focus:ring-primary-500"
            />
          </div>

          {/* Drag & Drop Uploader */}
          <div className="space-y-2">
            <Label className="text-sm font-semibold text-gray-700 dark:text-gray-300">
              {t("common.attachments", "Attachments")}
            </Label>

            <p className="text-xs text-red-600 dark:text-red-400 mt-1">
              {t(
                "common.replynote",
                "Only one attachment per reply is allowed.",
              )}
            </p>

            <div
              onDragEnter={handleDrag}
              onDragOver={handleDrag}
              onDragLeave={handleDrag}
              onDrop={handleDrop}
              onClick={() => fileInputRef.current?.click()}
              className={`
                border-2 border-dashed rounded-lg p-5 text-center cursor-pointer transition-all duration-200
                ${
                  dragActive
                    ? "border-primary-500 bg-primary-50/50 dark:bg-primary-950/20"
                    : "border-gray-300 hover:border-primary-400 hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-800/40"
                }
              `}
            >
              <input
                ref={fileInputRef}
                type="file"
                onChange={handleFileSelect}
                className="hidden"
                disabled={isLoading}
              />
              <UploadCloud className="h-10 w-10 mx-auto text-gray-400 dark:text-gray-500 mb-2 animate-bounce-slow" />
              <p className="text-sm font-medium text-gray-700 dark:text-gray-300">
                {t("common.uploadMessage", "Click to upload or drag and drop")}
              </p>
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                {t("common.uploadFormats", "PDF, PNG, JPG, ZIP (max 10MB)")}
              </p>
            </div>
          </div>

          {/* Existing attachment (edit mode) */}
          {existingAttachment && (
            <div className="space-y-2">
              <Label className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                {t("common.existingAttachment", "Existing Attachment")}
              </Label>
              <div className="border border-gray-100 dark:border-gray-700 rounded-lg p-2 bg-gray-50/50 dark:bg-gray-900/30">
                <div className="flex items-center justify-between border border-gray-200 dark:border-gray-700 rounded-lg p-2 bg-white dark:bg-gray-800 text-sm shadow-sm">
                  <div className="flex items-center gap-3 min-w-0">
                    {getFileIcon(
                      existingAttachment.contentType ||
                        existingAttachment.fileInfo?.contentType ||
                        "",
                    )}
                    <div className="min-w-0">
                      <p className="font-medium text-gray-800 dark:text-gray-200 truncate max-w-[240px]">
                        {existingAttachment.originalname ||
                          existingAttachment.fileInfo?.originalname ||
                          existingAttachment.name?.en ||
                          existingAttachment.fileName ||
                          "File"}
                      </p>
                      {(existingAttachment.size != null ||
                        existingAttachment.fileInfo?.size != null) && (
                        <p className="text-xs text-gray-500 dark:text-gray-400">
                          {formatFileSize(
                            existingAttachment.size ??
                              existingAttachment.fileInfo?.size ??
                              0,
                          )}
                        </p>
                      )}
                    </div>
                  </div>
                  <button
                    type="button"
                    onClick={removeExistingAttachment}
                    disabled={isLoading}
                    className="p-1.5 rounded-full text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors"
                  >
                    <X className="h-4 w-4" />
                  </button>
                </div>
              </div>
            </div>
          )}

          {/* New file attachment list */}
          {files.length > 0 && (
            <div className="max-h-40 overflow-y-auto space-y-2 border border-gray-100 dark:border-gray-700 rounded-lg p-2 bg-gray-50/50 dark:bg-gray-900/30">
              {files.map((file, idx) => (
                <div
                  key={idx}
                  className="flex items-center justify-between border border-gray-200 dark:border-gray-700 rounded-lg p-2 bg-white dark:bg-gray-800 text-sm shadow-sm"
                >
                  <div className="flex items-center gap-3 min-w-0">
                    {getFileIcon(file.type)}
                    <div className="min-w-0">
                      <p className="font-medium text-gray-800 dark:text-gray-200 truncate max-w-[240px]">
                        {file.name}
                      </p>
                      <p className="text-xs text-gray-500 dark:text-gray-400">
                        {formatFileSize(file.size)}
                      </p>
                    </div>
                  </div>
                  <button
                    type="button"
                    onClick={() => removeFile(idx)}
                    disabled={isLoading}
                    className="p-1.5 rounded-full text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors"
                  >
                    <X className="h-4 w-4" />
                  </button>
                </div>
              ))}
            </div>
          )}

          {error && (
            <div className="text-sm font-semibold text-red-500 bg-red-50 dark:bg-red-950/20 border border-red-200 dark:border-red-900 rounded-lg px-3 py-2">
              {error}
            </div>
          )}

          <DialogFooter className="border-t border-gray-100 dark:border-gray-700 pt-3 gap-2 flex-shrink-0">
            <Button
              type="button"
              variant="outline"
              onClick={handleClose}
              disabled={isLoading}
              className="w-full sm:w-auto"
            >
              {t("common.cancel", "Cancel")}
            </Button>
            <Button
              type="submit"
              disabled={isLoading}
              className="w-full sm:w-auto flex items-center justify-center gap-2 bg-primary-600 hover:bg-primary-700 dark:bg-primary-700 dark:hover:bg-primary-600"
            >
              {isLoading ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  {t("common.submitting", "Submitting...")}
                </>
              ) : isEditMode ? (
                <>
                  <Pencil className="h-4 w-4" />
                  {t("common.update", "Update")}
                </>
              ) : (
                <>
                  <Send className="h-4 w-4" />
                  {t("common.submit", "Submit")}
                </>
              )}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
};
