"use client";

import { useState, useRef, useEffect, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import BoldIcon from "@/components/ui/BoldIcon";
import AttachmentMenu, { AttachmentType } from "./AttachmentMenu";
import TimedMessagePicker from "./TimedMessagePicker";
import ViewOnceToggle from "./ViewOnceToggle";
import ChatBoldIcon from "./ChatBoldIcon";
import { formatTimedLabel } from "@/lib/chat/timedMessages";
import { viewOnceLabel } from "@/lib/chat/viewOnce";
import { chatHeaderCircleBtn, chatHeaderGlassStyle } from "./ChatHeader";
import { glassBackdropStyle } from "@/lib/glassBackdrop";
import { useTranslation } from "react-i18next";

interface MessageInputProps {
  newMessage: string;
  setNewMessage: React.Dispatch<React.SetStateAction<string>>;
  sendMessage: () => void;
  handleFileSelection: (e: React.ChangeEvent<HTMLInputElement>) => void;
  handleVoiceUpload: (blob: Blob) => void;
  onLocationShare?: () => void;
  onTyping?: () => void;
  /** Chat thread: tab bar hidden — less bottom offset */
  isChatThread?: boolean;
  blocked_you?: boolean | undefined;
  replyingTo?: unknown;
  onCancelReply?: () => void;
  onReplyPreviewClick?: () => void;
  replyLabel?: string;
  selfDestructSeconds?: number | null;
  onSelfDestructChange?: (seconds: number | null) => void;
  viewOnceMedia?: boolean;
  onViewOnceChange?: (value: boolean) => void;
  onGiftClick?: () => void;
}

const formatTime = (seconds: number) => {
  const mins = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
};

const MessageInput = ({
  newMessage,
  setNewMessage,
  sendMessage,
  handleFileSelection,
  handleVoiceUpload,
  onLocationShare,
  onTyping,
  isChatThread = false,
  blocked_you,
  onCancelReply,
  onReplyPreviewClick,
  replyLabel,
  selfDestructSeconds = null,
  onSelfDestructChange,
  viewOnceMedia = false,
  onViewOnceChange,
  onGiftClick,
}: MessageInputProps) => {
  const { t } = useTranslation("common");
  const [isRecording, setIsRecording] = useState(false);
  const [recordingTime, setRecordingTime] = useState(0);
  const [menuOpen, setMenuOpen] = useState(false);
  const [isLocked, setIsLocked] = useState(false);
  const [dragProgress, setDragProgress] = useState(0);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const audioChunksRef = useRef<Blob[]>([]);
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const dragStartYRef = useRef<number | null>(null);
  const LOCK_THRESHOLD_PX = 80;
  const attachBtnRef = useRef<HTMLButtonElement>(null);
  const imageInputRef = useRef<HTMLInputElement>(null);
  const videoInputRef = useRef<HTMLInputElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const adjustTextareaHeight = useCallback(() => {
    const el = textareaRef.current;
    if (!el) return;
    el.style.height = "auto";
    const maxHeight = 160;
    el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
  }, []);

  useEffect(() => {
    adjustTextareaHeight();
  }, [newMessage, adjustTextareaHeight]);

  const hasText = newMessage.trim().length > 0;
  const showSend = hasText && !isRecording;

  const handleSend = useCallback(() => {
    if (hasText && !blocked_you) sendMessage();
  }, [hasText, blocked_you, sendMessage]);
  // ردیف تایمر/یک‌بارمصرف فقط هنگام ضبط ویس (برای عکس داخل پیش‌نمایش نمایش داده می‌شود)
  const showMediaOptions = isChatThread && isRecording;

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      const MAX_SIZE = 200 * 1024 * 1024;
      if (file.size > MAX_SIZE) {
        alert(t("chats.toast.fileTooLarge"));
        return;
      }
    }
    handleFileSelection(e);
    e.target.value = "";
  };

  useEffect(() => {
    if (isRecording) {
      timerRef.current = setInterval(() => {
        setRecordingTime((prev) => prev + 1);
      }, 1000);
    } else {
      if (timerRef.current) clearInterval(timerRef.current);
      setRecordingTime(0);
    }
    return () => {
      if (timerRef.current) clearInterval(timerRef.current);
    };
  }, [isRecording]);

  const stopRecording = useCallback(
    (shouldSend: boolean) => {
      if (mediaRecorderRef.current?.state === "recording") {
        mediaRecorderRef.current.stop();
      }
      setIsRecording(false);
      setIsLocked(false);
      setDragProgress(0);
      dragStartYRef.current = null;
      if (!shouldSend) {
        audioChunksRef.current = [];
      }
      streamRef.current?.getTracks().forEach((t) => t.stop());
      streamRef.current = null;
    },
    []
  );

  const startRecording = async () => {
    if (blocked_you) return;
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      streamRef.current = stream;
      const mediaRecorder = new MediaRecorder(stream);
      mediaRecorderRef.current = mediaRecorder;
      audioChunksRef.current = [];

      mediaRecorder.ondataavailable = (event) => {
        audioChunksRef.current.push(event.data);
      };

      mediaRecorder.onstop = () => {
        if (audioChunksRef.current.length > 0) {
          const audioBlob = new Blob(audioChunksRef.current, {
            type: "audio/webm",
          });
          handleVoiceUpload(audioBlob);
        }
        audioChunksRef.current = [];
      };

      mediaRecorder.start();
      setIsRecording(true);
    } catch {
      alert(t("chats.toast.micDenied"));
    }
  };

  const handleMicPointerDown = (e: React.PointerEvent<HTMLButtonElement>) => {
    if (!hasText && !blocked_you) {
      dragStartYRef.current = e.clientY;
      setIsLocked(false);
      setDragProgress(0);
      e.currentTarget.setPointerCapture(e.pointerId);
      startRecording();
    }
  };

  const handleMicPointerMove = (e: React.PointerEvent<HTMLButtonElement>) => {
    if (!isRecording || isLocked || dragStartYRef.current == null) return;
    const delta = dragStartYRef.current - e.clientY;
    setDragProgress(Math.max(0, Math.min(1, delta / LOCK_THRESHOLD_PX)));
    if (delta >= LOCK_THRESHOLD_PX) {
      setIsLocked(true);
      dragStartYRef.current = null;
    }
  };

  const handleMicPointerUp = () => {
    if (isRecording && !isLocked) stopRecording(true);
    dragStartYRef.current = null;
    setDragProgress(0);
  };

  const handleAttachmentSelect = (type: AttachmentType) => {
    switch (type) {
      case "image":
      case "camera":
        imageInputRef.current?.click();
        break;
      case "video":
        videoInputRef.current?.click();
        break;
      case "file":
        fileInputRef.current?.click();
        break;
      case "location":
        onLocationShare?.();
        break;
    }
  };

  return (
    <div
      className={`pointer-events-none fixed left-0 right-0 z-50 flex flex-col items-center bg-transparent px-3 sm:px-4 ${
        isChatThread ? "bottom-0 chat-input-area--thread" : "bottom-[5.5rem] chat-input-area"
      }`}
    >
      {(replyLabel ||
        showMediaOptions ||
        (selfDestructSeconds != null && isChatThread) ||
        (viewOnceMedia && isChatThread)) && (
        <div className="pointer-events-auto relative z-[2] mb-2 flex w-full max-w-lg flex-col gap-2">
          {showMediaOptions && (
            <div className="glass-panel flex items-center justify-between gap-2 rounded-2xl px-3 py-2 shadow-lg">
              <span className="text-[11px] font-medium text-neutral-500 dark:text-neutral-400">
                {t("chats.mediaOptions")}
              </span>
              <div className="flex items-center gap-1.5">
                {onSelfDestructChange && (
                  <TimedMessagePicker
                    value={selfDestructSeconds}
                    onChange={onSelfDestructChange}
                    disabled={blocked_you}
                  />
                )}
                {onViewOnceChange && (
                  <ViewOnceToggle
                    value={viewOnceMedia}
                    onChange={onViewOnceChange}
                    disabled={blocked_you}
                  />
                )}
              </div>
            </div>
          )}
          {replyLabel && (
            <button
              type="button"
              onClick={onReplyPreviewClick}
              className="glass-panel gentle-transition flex w-full items-center gap-2 rounded-2xl px-3 py-2.5 text-right text-xs shadow-lg active:scale-[0.99]"
            >
              <span className="flex-1 truncate text-neutral-700 dark:text-neutral-200">
                {replyLabel}
              </span>
              <span
                role="button"
                tabIndex={0}
                onClick={(e) => {
                  e.stopPropagation();
                  onCancelReply?.();
                }}
                onKeyDown={(e) => {
                  if (e.key === "Enter" || e.key === " ") {
                    e.preventDefault();
                    e.stopPropagation();
                    onCancelReply?.();
                  }
                }}
                className="shrink-0 text-[#0095f6]"
              >
                ×
              </span>
            </button>
          )}
          {selfDestructSeconds != null && isChatThread && (
            <div className="chat-timer-glass chat-timer-glass--active flex items-center gap-2 rounded-2xl px-3 py-1.5 text-[11px]">
              <ChatBoldIcon name="timer" size={14} className="shrink-0" />
              <span>
                {t("chats.timedBanner", {
                  duration: formatTimedLabel(selfDestructSeconds, t),
                })}
              </span>
            </div>
          )}
          {viewOnceMedia && isChatThread && (
            <div className="chat-timer-glass chat-timer-glass--active flex items-center gap-2 rounded-2xl px-3 py-1.5 text-[11px] text-[#ff9500]">
              <span className="font-semibold">{t("chats.viewOnceBadge")}</span>
              <span>
                {t("chats.viewOnceBanner", {
                  label: viewOnceLabel("image", t),
                })}
              </span>
            </div>
          )}
        </div>
      )}
      <div
        dir="ltr"
        className="pointer-events-auto relative z-[1] flex w-full max-w-lg items-end gap-2 sm:gap-2.5"
      >
        <div className="relative flex shrink-0 items-center gap-1.5">
          <button
            ref={attachBtnRef}
            type="button"
            disabled={blocked_you || isRecording}
            onClick={() => setMenuOpen((o) => !o)}
            className={`${chatHeaderCircleBtn} gentle-transition disabled:opacity-40`}
            style={chatHeaderGlassStyle}
            aria-label={t("chats.aria.attach")}
          >
            <ChatBoldIcon name="attachment" size={22} className="text-current" />
          </button>
          <AttachmentMenu
            open={menuOpen}
            onClose={() => setMenuOpen(false)}
            onSelect={handleAttachmentSelect}
            anchorRef={attachBtnRef}
          />
          {onGiftClick && (
            <button
              type="button"
              disabled={blocked_you || isRecording}
              onClick={onGiftClick}
              className={`${chatHeaderCircleBtn} gentle-transition disabled:opacity-40`}
              style={chatHeaderGlassStyle}
              aria-label={t("chats.aria.gift")}
            >
              <BoldIcon name="gift" size={20} tinted className="text-current" />
            </button>
          )}
        </div>

        {/* Glass input box */}
        <div
          className="glass-chat-input gentle-transition flex min-h-11 flex-1 items-center rounded-[22px] px-4 py-2"
          style={glassBackdropStyle("glass-chat-input")}
        >
          <input
            ref={imageInputRef}
            type="file"
            accept="image/*"
            multiple
            className="hidden"
            onChange={handleFileChange}
            disabled={blocked_you}
          />
          <input
            ref={videoInputRef}
            type="file"
            accept="video/*"
            className="hidden"
            onChange={handleFileChange}
            disabled={blocked_you}
          />
          <input
            ref={fileInputRef}
            type="file"
            className="hidden"
            onChange={handleFileChange}
            disabled={blocked_you}
          />

          {isRecording ? (
            <div className="flex w-full items-center justify-between gap-2 text-red-500">
              <div className="flex items-center gap-2">
                <span className="relative flex h-2 w-2">
                  <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-red-400 opacity-75" />
                  <span className="relative inline-flex h-2 w-2 rounded-full bg-red-500" />
                </span>
                <span className="font-mono text-xs font-bold">
                  {formatTime(recordingTime)}
                </span>
                {!isLocked && (
                  <span className="text-[10px] font-normal text-neutral-400">
                    {t("chats.voice.slideUpToLock")}
                  </span>
                )}
                {isLocked && (
                  <BoldIcon name="lock" size={13} tinted className="text-neutral-400" />
                )}
              </div>
              <div className="flex items-center gap-1.5">
                <button
                  type="button"
                  onClick={() => stopRecording(false)}
                  className="rounded-full p-1"
                  aria-label={t("chats.aria.cancelVoice")}
                >
                  <BoldIcon name="trash" size={18} tinted className="text-current" />
                </button>
                {isLocked && (
                  <button
                    type="button"
                    onClick={() => stopRecording(true)}
                    className="flex h-7 w-7 items-center justify-center rounded-full bg-[#0095f6] text-white"
                    aria-label={t("chats.aria.sendVoice")}
                  >
                    <ChatBoldIcon name="send" size={14} className="text-current -mr-0.5" />
                  </button>
                )}
              </div>
            </div>
          ) : (
            <textarea
              ref={textareaRef}
              rows={1}
              placeholder={
                blocked_you
                  ? t("chats.placeholder.blocked")
                  : t("chats.placeholder.message")
              }
              value={newMessage}
              onChange={(e) => {
                setNewMessage(e.target.value);
                onTyping?.();
                adjustTextareaHeight();
              }}
              onKeyDown={(e) => {
                if (e.key === "Enter" && !e.shiftKey) {
                  e.preventDefault();
                  handleSend();
                }
              }}
              disabled={blocked_you}
              className="min-h-[1.5rem] max-h-40 flex-1 resize-none overflow-y-auto bg-transparent text-[15px] leading-6 outline-none placeholder:text-neutral-400 dark:text-white"
            />
          )}
        </div>

        {/* Send / Mic — outside right */}
        <AnimatePresence mode="wait">
          {showSend ? (
            <motion.button
              key="send"
              initial={{ scale: 0.6, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.6, opacity: 0 }}
              transition={{ duration: 0.2 }}
              type="button"
              disabled={blocked_you}
              onClick={sendMessage}
              className={`${chatHeaderCircleBtn} gentle-transition active:scale-90`}
              style={chatHeaderGlassStyle}
              aria-label={t("chats.aria.send")}
            >
              <ChatBoldIcon name="send" size={20} className="text-current -mr-0.5" />
            </motion.button>
          ) : (
            <motion.div key="mic" className="relative">
              {isRecording && !isLocked && (
                <div
                  className="pointer-events-none absolute bottom-full right-1/2 mb-2 flex translate-x-1/2 flex-col items-center gap-1"
                  style={{ opacity: 0.4 + dragProgress * 0.6 }}
                >
                  <span className="flex h-7 w-7 items-center justify-center rounded-full bg-black/40 text-white backdrop-blur-sm">
                    <BoldIcon name="lock" size={14} tinted className="text-white" />
                  </span>
                  <BoldIcon name="arrow-up-2" size={12} tinted className="text-neutral-400" />
                </div>
              )}
              <motion.button
                initial={{ scale: 0.6, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                exit={{ scale: 0.6, opacity: 0 }}
                transition={{ duration: 0.2 }}
                type="button"
                disabled={blocked_you}
                onPointerDown={handleMicPointerDown}
                onPointerMove={handleMicPointerMove}
                onPointerUp={handleMicPointerUp}
                onPointerLeave={() => isRecording && !isLocked && stopRecording(true)}
                className={`${chatHeaderCircleBtn} gentle-transition ${
                  isRecording ? "scale-110 !bg-red-500 text-white" : ""
                } active:scale-90`}
                style={isRecording ? undefined : chatHeaderGlassStyle}
                aria-label={t("chats.aria.recordVoice")}
              >
                {isRecording ? <BoldIcon name="stop" size={20} tinted className="text-white" /> : <ChatBoldIcon name="microphone" size={22} className="text-current" />}
              </motion.button>
            </motion.div>
          )}
        </AnimatePresence>
      </div>
    </div>
  );
};

export default MessageInput;
