"use client";

import { useState, useEffect, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  Terminal,
  Send,
  Loader2,
  ShieldCheck,
  ShieldAlert,
} from "lucide-react";
import { pb } from "@/lib/pb";
import { Dictionary } from "@/lib/IDict";

/**
 * Полноэкранная версия гостевой книги (аналог TerminalGuestbook на главной, но
 * без ограничения в 50 последних сообщений — здесь есть постраничная подгрузка
 * истории вверх при скролле). Источники и защита от спама те же:
 * - realtime через `pb.collection("comments").subscribe("*", ...)` для новых сообщений;
 * - отправка идёт через Rust-шлюз `/api/proxy/api/comments`, а не напрямую в PocketBase,
 *   т.к. там сообщения проходят модерацию (ИИ-фильтр на мат/спам/токсичность);
 * - 406 от прокси — отдельный кейс ("отклонено фильтром"), отличный от обычной
 *   сетевой ошибки ("сервер недоступен");
 * - клиентский кулдаун 60 секунд между сообщениями через localStorage, синхронизирован
 *   с сервером тем же ключом last_comment_time, что и в TerminalGuestbook.
 */
export function TerminalClient({
  dict,
  pbUrl,
}: {
  dict: Dictionary["terminal"];
  /**
   * Адрес PocketBase — приходит пропсом из серверного page.tsx, а не читается
   * напрямую из process.env.NEXT_PUBLIC_* здесь (см. комментарий в
   * app/[lang]/auth/auth-client.tsx для полного объяснения).
   */
  pbUrl: string;
}) {
  const [messages, setMessages] = useState<any[]>([]);
  const [nickname, setNickname] = useState("");
  const [inputMsg, setInputMsg] = useState("");
  const [errorText, setErrorText] = useState<string | null>(null);

  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);
  const [isLoading, setIsLoading] = useState(true);
  const [isFetchingMore, setIsFetchingMore] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [cooldown, setCooldown] = useState(0);

  const scrollRef = useRef<HTMLDivElement>(null);
  const prevScrollHeight = useRef<number>(0);

  useEffect(() => {
    pb.baseURL = pbUrl;
    fetchHistory(1, true);

    pb.collection("comments").subscribe("*", (e) => {
      if (e.action === "create") {
        setMessages((prev) => [...prev, e.record]);
        setTimeout(scrollToBottom, 50);
      }
    });

    const lastPost = localStorage.getItem("last_comment_time");
    if (lastPost) {
      const timePassed = Math.floor((Date.now() - parseInt(lastPost)) / 1000);
      if (timePassed < 60) setCooldown(60 - timePassed);
    }

    return () => {
      pb.collection("comments").unsubscribe("*");
    };
  }, [pbUrl]);

  useEffect(() => {
    if (cooldown > 0) {
      const timer = setTimeout(() => setCooldown((c) => c - 1), 1000);
      return () => clearTimeout(timer);
    }
  }, [cooldown]);

  useEffect(() => {
    if (prevScrollHeight.current > 0 && scrollRef.current) {
      const newHeight = scrollRef.current.scrollHeight;
      scrollRef.current.scrollTop += newHeight - prevScrollHeight.current;
      prevScrollHeight.current = 0;
    }
  }, [messages]);

  // Подгрузка истории постранично (30 сообщений за раз). При скролле наверх (см.
  // handleScroll) запрашивается следующая страница, и новые сообщения добавляются
  // в начало массива с сохранением позиции скролла (см. эффект с prevScrollHeight).
  const fetchHistory = async (pageToLoad: number, isInitial = false) => {
    try {
      if (isInitial) setIsLoading(true);
      else setIsFetchingMore(true);

      const res = await pb
        .collection("comments")
        .getList(pageToLoad, 30, { sort: "-created", requestKey: null });

      const fetchedItems = res.items.reverse();

      if (isInitial) {
        setMessages(fetchedItems);
        setTimeout(scrollToBottom, 100);
      } else {
        if (scrollRef.current) {
          prevScrollHeight.current = scrollRef.current.scrollHeight;
        }
        setMessages((prev) => [...fetchedItems, ...prev]);
      }

      setHasMore(res.page < res.totalPages);
      setPage(pageToLoad);
    } catch (e) {
      console.error(e);
    } finally {
      setIsLoading(false);
      setIsFetchingMore(false);
    }
  };

  const handleScroll = () => {
    if (!scrollRef.current || isFetchingMore || !hasMore) return;
    if (scrollRef.current.scrollTop === 0) {
      fetchHistory(page + 1);
    }
  };

  const scrollToBottom = () => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  };

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

    if (!nickname.trim() || !inputMsg.trim() || cooldown > 0 || isSubmitting)
      return;

    try {
      setIsSubmitting(true);
      const proxyUrl = "/api/proxy";

      const res = await fetch(`${proxyUrl}/api/comments`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          nickname: nickname.trim(),
          message: inputMsg.trim(),
        }),
      });

      if (!res.ok) {
        if (res.status === 406) {
          throw new Error("FILTER_VIOLATION");
        }
        throw new Error("SERVER_ERROR");
      }

      // Успешная отправка
      setInputMsg("");
      setCooldown(60);
      localStorage.setItem("last_comment_time", Date.now().toString());
      setTimeout(scrollToBottom, 50);
    } catch (err: any) {
      console.error(err);

      // Выдаем разные ошибки в зависимости от ответа сервера
      if (err.message === "FILTER_VIOLATION") {
        setErrorText(
          (dict as any).statusErrorFilter ||
            "⛔ Сообщение отклонено ИИ-фильтром (нарушение политики: мат, спам или токсичность).",
        );
      } else {
        setErrorText(
          (dict as any).statusErrorOffline ||
            "⚠️ Ошибка связи с сервером. Попробуйте повторить запрос позже.",
        );
      }

      // Убираем ошибку через 8 секунд
      setTimeout(() => setErrorText(null), 8000);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <div className="fixed inset-0 pt-20 pb-4 md:pt-24 z-30 bg-background flex justify-center px-2 sm:px-4">
      <div className="w-full max-w-5xl flex flex-col bg-card/10 backdrop-blur-3xl border border-border/50 rounded-2xl md:rounded-[2rem] overflow-hidden shadow-2xl relative">
        {/* Header */}
        <div className="h-12 bg-muted/50 border-b border-border/50 flex items-center px-4 justify-between select-none">
          <div className="flex items-center gap-3">
            <Terminal className="size-4 text-primary" />
            <span className="font-mono text-xs font-bold text-foreground/80 tracking-widest">
              {dict.title}
            </span>
          </div>
          <div className="flex items-center gap-2">
            <div className="size-2 rounded-full bg-primary/50 animate-pulse" />
            <span className="font-mono text-[10px] text-muted-foreground uppercase hidden sm:block">
              {dict.systemReady}
            </span>
          </div>
        </div>

        {/* Message Area */}
        <div
          ref={scrollRef}
          onScroll={handleScroll}
          className="flex-1 overflow-y-auto p-4 md:p-8 font-mono text-sm space-y-4 custom-scrollbar-cyber"
        >
          {isFetchingMore && (
            <div className="text-center text-primary/50 text-xs uppercase animate-pulse my-4">
              <Loader2 className="size-4 animate-spin inline mr-2" />{" "}
              {dict.loadingHistory}
            </div>
          )}

          {!hasMore && !isLoading && (
            <div className="text-center text-muted-foreground/30 text-[10px] uppercase my-8">
              --- {dict.noMoreLogs} ---
            </div>
          )}

          {/* MANIFESTO */}
          {!isFetchingMore && !hasMore && !isLoading && (
            <div className="mb-12 p-6 border border-primary/20 bg-primary/5 rounded-2xl font-mono text-sm relative overflow-hidden group">
              <div className="absolute inset-0 bg-gradient-to-b from-transparent via-primary/5 to-transparent -translate-y-full group-hover:animate-scan pointer-events-none" />
              <div className="flex items-center gap-3 text-primary mb-4">
                <ShieldCheck className="size-5" />
                <span className="font-black uppercase tracking-widest">
                  {dict.manifestoTitle}
                </span>
              </div>
              <p className="text-foreground/80 mb-6 leading-relaxed">
                {dict.manifestoText}
              </p>
              <div className="space-y-2 border-t border-primary/10 pt-4">
                <div className="text-[10px] text-primary/50 uppercase tracking-widest mb-2">
                  {dict.rulesTitle}
                </div>
                <p className="text-xs text-muted-foreground">{dict.rule1}</p>
                <p className="text-xs text-muted-foreground">{dict.rule2}</p>
                <p className="text-xs text-secondary/80 font-bold">
                  {dict.rule3}
                </p>
              </div>
              <div className="mt-6 flex items-center gap-2 text-[10px] text-green-500/60">
                <div className="size-1.5 rounded-full bg-green-500 animate-pulse" />
                {dict.statusReady}
              </div>
            </div>
          )}

          {messages.map((msg, idx) => (
            <motion.div
              key={msg.id || idx}
              initial={{ opacity: 0, x: -10 }}
              animate={{ opacity: 1, x: 0 }}
              className="flex flex-col mb-4"
            >
              <div className="text-xs text-muted-foreground/50 mb-1 flex justify-between">
                <span>
                  <span className="text-primary/70">guest@{msg.nickname}</span>
                  :~#
                </span>
                <span>{new Date(msg.created).toLocaleTimeString()}</span>
              </div>
              <div className="text-foreground/90 pl-4 border-l-2 border-primary/30 break-words whitespace-pre-wrap font-medium">
                {msg.message}
              </div>
            </motion.div>
          ))}

          {isLoading && (
            <div className="h-full flex items-center justify-center text-primary py-20">
              <Loader2 className="size-8 animate-spin" />
            </div>
          )}
        </div>

        {/* Input Panel */}
        <div className="p-4 bg-muted/20 border-t border-border/50 relative">
          {/* Блок вывода ошибок */}
          <AnimatePresence>
            {errorText && (
              <motion.div
                initial={{ opacity: 0, y: 10, scale: 0.95 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                exit={{ opacity: 0, y: 10, scale: 0.95 }}
                className="absolute bottom-full left-4 right-4 mb-4 p-3 rounded-xl border bg-destructive/10 border-destructive/20 text-destructive text-xs font-mono flex items-start gap-3 backdrop-blur-md shadow-lg"
              >
                <ShieldAlert className="size-4 shrink-0 mt-0.5" />
                <span className="leading-relaxed">{errorText}</span>
              </motion.div>
            )}
          </AnimatePresence>

          <form
            onSubmit={handleSubmit}
            className="flex flex-col sm:flex-row gap-3"
          >
            <input
              type="text"
              maxLength={20}
              placeholder={dict.alias}
              value={nickname}
              onChange={(e) => setNickname(e.target.value)}
              className="w-full sm:w-40 bg-background/50 border border-border rounded-xl px-4 py-3 font-mono text-sm focus:border-primary outline-none transition-colors"
              disabled={isSubmitting || cooldown > 0}
            />
            <div className="flex-1 relative flex items-center">
              <input
                type="text"
                maxLength={150}
                placeholder={
                  cooldown > 0
                    ? dict.cooldown.replace("{{time}}", cooldown.toString())
                    : dict.message
                }
                value={inputMsg}
                onChange={(e) => setInputMsg(e.target.value)}
                className="w-full bg-background/50 border border-border rounded-xl pl-4 pr-12 py-3 font-mono text-sm focus:border-primary outline-none transition-colors"
                disabled={isSubmitting || cooldown > 0}
              />
              <button
                type="submit"
                disabled={
                  isSubmitting ||
                  cooldown > 0 ||
                  !nickname.trim() ||
                  !inputMsg.trim()
                }
                className="absolute right-2 p-2 bg-primary/20 text-primary hover:bg-primary hover:text-white rounded-lg transition-colors disabled:opacity-30"
              >
                {isSubmitting ? (
                  <Loader2 className="size-4 animate-spin" />
                ) : (
                  <Send className="size-4" />
                )}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
}
