/* eslint-disable react-hooks/rules-of-hooks */
"use client";

import Container from "@/components/elements/Container";
import useAxios from "@/hooks/useAxios";
import { User } from "@/types/types";
import React, { useState, useEffect, useRef, useCallback } from "react";
import { io } from "socket.io-client";
import { SOCKET_URL } from "@/components/main/BaseUrl";
import MessageInput from "@/components/chat/MessageInput";
import MultiImageModal from "@/components/chat/MultiImageModal";
import ChatActionBar from "@/components/chat/ChatActionBar";
import { useUser } from "@/hooks/useUser";
import ChatMessageList from "@/components/chat/ChatMessageList";
import ChatHeader from "@/components/chat/ChatHeader";
import dynamic from "next/dynamic";
import type { ChatMessage } from "@/components/chat/ChatMessageCard";
import toast from "react-hot-toast";
import { optimizeMediaFile } from "@/lib/media";
import ForwardMessageModal from "@/components/chat/ForwardMessageModal";
import { AnimatePresence } from "framer-motion";
import { formatBubbleTime } from "@/lib/chat/formatMessageTime";

interface ITicketChatProps {
  params: Promise<{ id: string; username: string }>;
}

function normalizeMessage(raw: ChatMessage & { data?: ChatMessage }): ChatMessage {
  const m = (raw as { data?: ChatMessage }).data ?? raw;
  return {
    ...m,
    createdAt: formatBubbleTime(m.createdAt),
    replyTo: m.replyTo ?? undefined,
  };
}

function TicketChat({ params }: ITicketChatProps) {
  const resolvedParams = React.use(params);
  const { request } = useAxios();
  const { username } = resolvedParams;
  const [newMessage, setNewMessage] = useState("");
  const [userTwoDetail, setUserTwoDetail] = useState<User>();
  const [pendingImages, setPendingImages] = useState<File[]>([]);
  const [showMultiModal, setShowMultiModal] = useState(false);
  const [pendingMessages, setPendingMessages] = useState<ChatMessage[]>([]);
  const [replyingTo, setReplyingTo] = useState<ChatMessage | null>(null);
  const [forwardMessage, setForwardMessage] = useState<ChatMessage | null>(null);
  const [selectedMessage, setSelectedMessage] = useState<ChatMessage | null>(null);
  const [actionMode, setActionMode] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const user = useUser();
  const [receiverId, setReceiverId] = useState("");
  const [isTyping, setIsTyping] = useState(false);
  const socketRef = useRef<ReturnType<typeof io> | null>(null);
  const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const activeReplyRef = useRef<ChatMessage | null>(null);

  useEffect(() => {
    if (!user?._id || !receiverId) return;
    const socket = io(SOCKET_URL);
    socketRef.current = socket;
    socket.emit("joinChat", { userId: user._id, receiverId });
    socket.emit("joinUser", { userId: user._id });
    return () => {
      socket.disconnect();
      socketRef.current = null;
    };
  }, [user?._id, receiverId]);

  const handleTyping = useCallback(() => {
    if (!socketRef.current || !user?._id || !receiverId) return;
    socketRef.current.emit("typing", {
      senderId: user._id,
      receiverId,
    });
    if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
    typingTimeoutRef.current = setTimeout(() => {
      socketRef.current?.emit("stopTyping", {
        senderId: user._id,
        receiverId,
      });
    }, 2000);
  }, [user?._id, receiverId]);

  useEffect(() => {
    const fetchStates = async () => {
      try {
        const response = await request<{ user: User }>(
          "GET",
          `/users/get/web?user_name=${username}&_t=${Date.now()}`
        );
        setUserTwoDetail(response?.user);
      } catch (err) {
        console.error("Error fetching user:", err);
      }
    };
    fetchStates();
  }, [username, request]);

  useEffect(() => {
    setReceiverId(userTwoDetail?._id || "");
  }, [user, userTwoDetail]);

  const handleImageSelection = (e: React.ChangeEvent<HTMLInputElement>) => {
    const picked = Array.from(e.target.files || []);
    if (!picked.length) return;
    const MAX_SIZE = 200 * 1024 * 1024;
    const valid = picked.filter((f) => {
      if (f.size > MAX_SIZE) {
        toast.error(`${f.name}: حجم بیش از ۲۰۰ مگابایت`);
        return false;
      }
      return true;
    });
    if (!valid.length) return;
    setPendingImages((prev) => [...prev, ...valid].slice(0, 10));
    setShowMultiModal(true);
  };

  const handleVoiceUpload = (blob: Blob) => {
    const voiceFile = new File([blob], "voice-message.webm", {
      type: "audio/webm",
    });
    processSendMessage(voiceFile, "voice");
  };

  const handleLocationShare = () => {
    if (!navigator.geolocation) {
      toast.error("مرورگر از موقعیت مکانی پشتیبانی نمی‌کند.");
      return;
    }
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        const locationContent = JSON.stringify({
          lat: pos.coords.latitude,
          lng: pos.coords.longitude,
          label: "موقعیت من",
        });
        processSendMessage(null, "location", locationContent);
      },
      () => toast.error("دسترسی به موقعیت مکانی داده نشد.")
    );
  };

  const sendMessage = () => {
    if (pendingImages.length > 0) {
      void sendAllImages();
      return;
    }
    processSendMessage(null);
  };

  const sendAllImages = async () => {
    const batch = [...pendingImages];
    setShowMultiModal(false);
    setPendingImages([]);
    for (const file of batch) {
      await processSendMessage(file, "image");
    }
  };

  const buildReplyPayload = (source: ChatMessage | null) => {
    if (!source) return undefined;
    return {
      _id: source._id,
      content: source.content?.slice(0, 120) || "پیام",
      senderName:
        source.senderId === user?._id
          ? "شما"
          : `${userTwoDetail?.first_name || ""} ${userTwoDetail?.last_name || ""}`.trim(),
    };
  };

  const processSendMessage = async (
    fileToUpload: File | null,
    fileType?: ChatMessage["fileType"],
    contentOverride?: string
  ) => {
    const replySource = activeReplyRef.current;
    let textContent = contentOverride ?? newMessage;
    if (textContent.trim() === "" && !fileToUpload) return;

    const tempId = `temp-${Date.now()}-${Math.random()}`;
    const replyPayload = buildReplyPayload(replySource);

    const optimisticMsg: ChatMessage = {
      _id: tempId,
      content: textContent,
      senderId: user?._id || "",
      createdAt: formatBubbleTime(new Date().toISOString()),
      status: "pending",
      file: fileToUpload ? URL.createObjectURL(fileToUpload) : "",
      fileType: fileType,
      replyTo: replyPayload,
    };

    setPendingMessages((prev) => [...prev, optimisticMsg]);
    setNewMessage("");

    let fileForUpload = fileToUpload;
    if (fileToUpload && fileType !== "location") {
      try {
        toast.loading("در حال بهینه‌سازی فایل…", { id: "media-opt" });
        fileForUpload = await optimizeMediaFile(fileToUpload);
        toast.dismiss("media-opt");
      } catch {
        toast.dismiss("media-opt");
      }
    }

    const formData = new FormData();
    formData.append("content", textContent);
    formData.append("receiverId", userTwoDetail?._id || "");
    formData.append("senderId", user?._id || "");
    if (replySource?._id && !replySource._id.startsWith("temp")) {
      formData.append("replyToId", replySource._id);
    }
    if (fileForUpload) {
      formData.append("file", fileForUpload);
      if (fileType) formData.append("fileType", fileType);
    }

    try {
      const endpoint =
        fileToUpload && fileType !== "location" ? "/chat/file" : "/chat";

      const response = await request<ChatMessage | { data: ChatMessage }>(
        "post",
        endpoint,
        formData,
        { headers: { "Content-Type": "multipart/form-data" } }
      );

      const serverMsg = normalizeMessage(response as ChatMessage);
      setPendingMessages((prev) =>
        prev.map((m) =>
          m._id === tempId
            ? {
                ...serverMsg,
                status: "sent",
                replyTo: serverMsg.replyTo ?? replyPayload,
              }
            : m
        )
      );

      setReplyingTo(null);
      activeReplyRef.current = null;
    } catch (error) {
      console.error("Error sending message:", error);
      setPendingMessages((prev) => prev.filter((m) => m._id !== tempId));
      toast.error("ارسال پیام ناموفق بود.");
    }
  };

  const openActionFor = (msg: ChatMessage) => {
    setSelectedMessage(msg);
    setActionMode(true);
  };

  const closeActionMode = () => {
    setActionMode(false);
    setSelectedMessage(null);
  };

  const startReply = () => {
    if (!selectedMessage) return;
    setReplyingTo(selectedMessage);
    activeReplyRef.current = selectedMessage;
    closeActionMode();
  };

  const startForward = () => {
    if (!selectedMessage) return;
    setForwardMessage(selectedMessage);
    closeActionMode();
  };

  const handleBlockChange = () => {
    void request<{ user: User }>(
      "GET",
      `/users/get/web?user_name=${username}&_t=${Date.now()}`
    ).then((res) => setUserTwoDetail(res?.user));
  };

  return (
    <Container className="chat-page-bg flex h-[100dvh] max-h-[100dvh] flex-col overflow-hidden !px-0">
      <div className="flex min-h-0 flex-1 flex-col px-2 sm:px-4">
        <ChatHeader
          user={userTwoDetail}
          searchQuery={searchQuery}
          onSearchChange={setSearchQuery}
          onBlockChange={handleBlockChange}
        />
        <ChatMessageList
          pendingMessages={pendingMessages}
          userDetail={user as User}
          userTwoDetail={userTwoDetail}
          isTyping={isTyping}
          onTypingChange={setIsTyping}
          searchQuery={searchQuery}
          selectedMessageId={selectedMessage?._id}
          onBubbleClick={openActionFor}
        />
      </div>

      <AnimatePresence mode="wait">
        {actionMode ? (
          <ChatActionBar
            key="actions"
            onReply={startReply}
            onForward={startForward}
            onCancel={closeActionMode}
          />
        ) : (
          <MessageInput
            key="input"
            newMessage={newMessage}
            setNewMessage={setNewMessage}
            sendMessage={sendMessage}
            handleFileSelection={handleImageSelection}
            handleVoiceUpload={handleVoiceUpload}
            onLocationShare={handleLocationShare}
            onTyping={handleTyping}
            isChatThread
            blocked_you={userTwoDetail?.blocked_you}
            replyingTo={replyingTo}
            onCancelReply={() => {
              setReplyingTo(null);
              activeReplyRef.current = null;
            }}
            replyLabel={
              replyingTo
                ? replyingTo.content?.slice(0, 80) || "پیام"
                : undefined
            }
          />
        )}
      </AnimatePresence>

      <MultiImageModal
        isOpen={showMultiModal}
        files={pendingImages}
        onRemove={(i) =>
          setPendingImages((prev) => {
            const next = prev.filter((_, idx) => idx !== i);
            if (next.length === 0) setShowMultiModal(false);
            return next;
          })
        }
        onCancel={() => {
          setPendingImages([]);
          setShowMultiModal(false);
        }}
        onConfirm={sendAllImages}
      />
      {forwardMessage && user?._id && (
        <ForwardMessageModal
          open={!!forwardMessage}
          onClose={() => setForwardMessage(null)}
          message={forwardMessage}
          currentUserId={user._id}
          currentReceiverId={receiverId}
        />
      )}
    </Container>
  );
}

export default dynamic(() => Promise.resolve(TicketChat), { ssr: false });
