"use client";

import { useEffect, useRef, useState } from "react";
import { useParams, useRouter } from "next/navigation";
import Container from "@/components/elements/Container";
import ProfileAvatar from "@/components/main/ProfileAvatar";
import LocalePageShell from "@/components/i18n/LocalePageShell";
import ChatBoldIcon from "@/components/chat/ChatBoldIcon";
import { chatHeaderCircleBtn, chatHeaderInfoPill, chatHeaderGlassStyle } from "@/components/chat/ChatHeader";
import VideoMessageBubble from "@/components/chat/VideoMessageBubble";
import IOSSpinner from "@/components/ui/IOSSpinner";
import useAxios from "@/hooks/useAxios";
import { cn } from "@/lib/utils";
import { IMAGE_BASE_URL } from "@/components/main/BaseUrl";
import { formatBubbleTime } from "@/lib/chat/formatMessageTime";
import {
  type BubbleGroupPosition,
  getBubbleRadius,
  getMessageRowSpacing,
} from "@/lib/chat/messageGrouping";
import { useTranslation } from "react-i18next";

type ShopChatMessage = {
  _id: string;
  senderRole: "shop" | "buyer";
  content: string | null;
  file?: string | null;
  fileType?: "image" | "video" | null;
  createdAt: string;
};

type Counterpart = {
  name: string;
  logo?: string | null;
};

const MAX_VIDEO_SIZE_BYTES = 100 * 1024 * 1024;

function getGroupPosition(
  messages: ShopChatMessage[],
  index: number
): BubbleGroupPosition {
  const current = messages[index];
  const sameAsPrev =
    index > 0 && messages[index - 1].senderRole === current.senderRole;
  const sameAsNext =
    index < messages.length - 1 &&
    messages[index + 1].senderRole === current.senderRole;
  if (!sameAsPrev && !sameAsNext) return "single";
  if (!sameAsPrev && sameAsNext) return "first";
  if (sameAsPrev && sameAsNext) return "middle";
  return "last";
}

export default function ShopChatPage() {
  const { t } = useTranslation("common");
  const router = useRouter();
  const params = useParams<{ shopId: string; buyerId: string }>();
  const { shopId, buyerId } = params;
  const { request } = useAxios();

  const [messages, setMessages] = useState<ShopChatMessage[] | null>(null);
  const [counterpart, setCounterpart] = useState<Counterpart | null>(null);
  const [isOwner, setIsOwner] = useState(false);
  const [text, setText] = useState("");
  const [sending, setSending] = useState(false);
  const bottomRef = useRef<HTMLDivElement>(null);
  const attachmentInputRef = useRef<HTMLInputElement>(null);

  const loadMessages = () => {
    request<{ messages: ShopChatMessage[]; counterpart: Counterpart; isOwner: boolean }>(
      "GET",
      `/shop-chat/${shopId}/messages?buyerId=${buyerId}`,
      null,
      { noToast: true }
    )
      .then((res) => {
        setMessages(res?.messages || []);
        setCounterpart(res?.counterpart || null);
        setIsOwner(Boolean(res?.isOwner));
      })
      .catch(() => setMessages([]));
  };

  useEffect(() => {
    if (!shopId || !buyerId) return;
    loadMessages();
    const id = window.setInterval(loadMessages, 8000);
    return () => window.clearInterval(id);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [shopId, buyerId]);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const handleSend = async () => {
    if (!text.trim() || sending) return;
    setSending(true);
    try {
      const res = await request<{ message: ShopChatMessage }>(
        "POST",
        `/shop-chat/${shopId}/messages`,
        { buyerId, content: text.trim() }
      );
      if (res?.message) {
        setMessages((prev) => [...(prev || []), res.message]);
      }
      setText("");
    } finally {
      setSending(false);
    }
  };

  const handleFileSelected = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    e.target.value = "";
    if (!file) return;
    const fileType: "image" | "video" = file.type.startsWith("video/") ? "video" : "image";
    if (fileType === "video" && file.size > MAX_VIDEO_SIZE_BYTES) {
      alert(t("chats.toast.shopChatVideoTooLarge"));
      return;
    }
    setSending(true);
    try {
      const formData = new FormData();
      formData.append("buyerId", buyerId);
      formData.append("fileType", fileType);
      formData.append("file", file);
      const res = await request<{ message: ShopChatMessage }>(
        "POST",
        `/shop-chat/${shopId}/messages/file`,
        formData
      );
      if (res?.message) {
        setMessages((prev) => [...(prev || []), res.message]);
      }
    } finally {
      setSending(false);
    }
  };

  const myRole = isOwner ? "shop" : "buyer";

  return (
    <LocalePageShell>
      <header className="pointer-events-none fixed left-0 right-0 top-0 z-[100] bg-transparent px-2 pb-2 pt-[max(0.5rem,env(safe-area-inset-top))] sm:px-3">
        <div
          dir="rtl"
          className="pointer-events-auto mx-auto flex max-w-lg items-center gap-2"
        >
          <button
            type="button"
            onClick={() => router.back()}
            className={chatHeaderCircleBtn}
            style={chatHeaderGlassStyle}
            aria-label={t("chats.actions.back")}
          >
            <ChatBoldIcon name="back" size={22} className="text-current" />
          </button>

          <div dir="ltr" className={chatHeaderInfoPill} style={chatHeaderGlassStyle}>
            <div dir="rtl" className="min-w-0 flex-1 text-right">
              <span className="block truncate text-[15px] font-semibold leading-tight text-neutral-900 dark:text-neutral-50">
                {counterpart?.name}
              </span>
              <span className="block truncate text-xs leading-tight text-neutral-500 dark:text-neutral-400">
                {t("chats.shopChatSubtitle")}
              </span>
            </div>
            <ProfileAvatar
              src={counterpart?.logo}
              alt={counterpart?.name || ""}
              size="xs"
              rounded="full"
              className="h-[34px] w-[34px] shrink-0"
            />
          </div>
        </div>
      </header>

      <Container className="!px-0">
        <div className="mx-auto flex h-[100dvh] max-h-[100dvh] w-full max-w-lg flex-col overflow-hidden">
          <div className="flex-1 overflow-y-auto px-3 pb-28 pt-[calc(3.75rem+env(safe-area-inset-top))]">
            {messages === null ? (
              <div className="flex justify-center py-8">
                <IOSSpinner />
              </div>
            ) : messages.length === 0 ? (
              <p className="py-8 text-center text-sm text-neutral-500">
                {t("shops.noChatMessagesYet")}
              </p>
            ) : (
              <div className="flex flex-col">
                {messages.map((m, index) => {
                  const mine = m.senderRole === myRole;
                  const position = getGroupPosition(messages, index);
                  const groupedWithPrev =
                    index > 0 && messages[index - 1].senderRole === m.senderRole;
                  const radius = getBubbleRadius(mine, position);
                  return (
                    <div
                      key={m._id}
                      dir="rtl"
                      className={cn(
                        "flex w-full",
                        getMessageRowSpacing(position, groupedWithPrev),
                        mine ? "justify-end" : "justify-start"
                      )}
                    >
                      {m.fileType === "video" && m.file ? (
                        <VideoMessageBubble
                          src={`${IMAGE_BASE_URL}${m.file}`}
                          isOutgoing={mine}
                          borderRadius={radius}
                        />
                      ) : m.fileType === "image" && m.file ? (
                        <div
                          className="max-w-[min(280px,85vw)] overflow-hidden"
                          style={{ borderRadius: radius }}
                        >
                          {/* eslint-disable-next-line @next/next/no-img-element */}
                          <img
                            src={`${IMAGE_BASE_URL}${m.file}`}
                            alt=""
                            className="max-h-96 w-full min-w-[200px] bg-black/5 object-cover"
                            style={{ borderRadius: radius }}
                          />
                        </div>
                      ) : (
                        <div
                          className={cn(
                            "chat-text-bubble max-w-[75%] px-3 py-2 text-[15px] leading-snug break-words",
                            mine ? "chat-bubble-out" : "chat-bubble-in"
                          )}
                          style={{ borderRadius: radius }}
                        >
                          <p className="chat-message-text select-text">{m.content}</p>
                          <span
                            className={cn(
                              "message-time-below mt-0.5 block text-[10px] tabular-nums",
                              mine ? "text-left" : "text-right"
                            )}
                          >
                            {formatBubbleTime(m.createdAt)}
                          </span>
                        </div>
                      )}
                    </div>
                  );
                })}
                <div ref={bottomRef} />
              </div>
            )}
          </div>
        </div>
      </Container>

      <div className="pointer-events-none fixed bottom-0 left-0 right-0 z-50 flex flex-col items-center bg-transparent px-3 sm:px-4">
        <div
          dir="ltr"
          className="pointer-events-auto relative flex w-full max-w-lg items-end gap-2 pb-5 sm:gap-2.5"
        >
          <input
            ref={attachmentInputRef}
            type="file"
            accept="image/*,video/*"
            className="hidden"
            onChange={(e) => void handleFileSelected(e)}
          />
          <div className="relative flex shrink-0 items-center gap-1.5">
            <button
              type="button"
              disabled={sending}
              onClick={() => attachmentInputRef.current?.click()}
              className={cn(chatHeaderCircleBtn, "gentle-transition disabled:opacity-40")}
              style={chatHeaderGlassStyle}
              aria-label={t("chats.aria.attach")}
            >
              <ChatBoldIcon name="attachment" size={22} className="text-current" />
            </button>
          </div>

          <div className="glass-chat-input gentle-transition flex min-h-11 flex-1 items-center rounded-[22px] px-4 py-2">
            <textarea
              rows={1}
              value={text}
              onChange={(e) => setText(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === "Enter" && !e.shiftKey) {
                  e.preventDefault();
                  void handleSend();
                }
              }}
              placeholder={t("chats.placeholder.message")}
              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>
          <button
            type="button"
            disabled={!text.trim() || sending}
            onClick={() => void handleSend()}
            className={cn(chatHeaderCircleBtn, "gentle-transition active:scale-90 disabled:opacity-40")}
            style={chatHeaderGlassStyle}
            aria-label={t("chats.aria.send")}
          >
            <ChatBoldIcon name="send" size={20} className="text-current -mr-0.5" />
          </button>
        </div>
      </div>
    </LocalePageShell>
  );
}
