"use client";

import React, { useEffect, useMemo, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import type { ChatMessage, ChatSource } from "./ChatWidget";
import {
  AlertTriangle,
  Bot,
  Copy,
  ExternalLink,
  RefreshCw,
  ThumbsDown,
  ThumbsUp,
} from "lucide-react";

interface Props {
  messages: ChatMessage[];
  isStreaming: boolean;
  category: string | null;
  onRegenerate: (assistantId: string) => void;
  isLoadingHistory?: boolean;
  isLoadingThread?: boolean;
}

const CATEGORY_META: Record<string, { icon: string; text: string }> = {
  "operation manual": {
    icon: "📘",
    text: "I can help you with internal processes, SOPs, and daily operations.",
  },
  marketing: {
    icon: "📢",
    text: "I can help you with marketing strategies, promotions, and growth ideas.",
  },
};

const looksLikeErrorMessage = (text: string) => {
  const normalized = text.toLowerCase();

  return (
    normalized.includes("something went wrong") ||
    normalized.includes("unable to") ||
    normalized.includes("could not") ||
    normalized.includes("i couldn’t") ||
    normalized.includes("i'm unable to") ||
    normalized.includes("i’m unable to") ||
    normalized.includes("server") ||
    normalized.includes("try again") ||
    normalized.includes("conversation right now")
  );
};

const getPrimarySource = (sources?: ChatSource[]) => {
  if (!sources || !sources.length) return null;

  const sorted = [...sources].sort(
    (a, b) => (a?.relevance_rank ?? 999) - (b?.relevance_rank ?? 999),
  );

  return sorted[0] || null;
};

const decodeHtmlEntities = (value?: string) => {
  if (!value) return "";
  if (typeof window === "undefined") return value;

  const textarea = document.createElement("textarea");
  textarea.innerHTML = value;
  return textarea.value;
};

export default function ChatMessages({
  messages,
  isStreaming,
  category,
  onRegenerate,
  isLoadingHistory = false,
  isLoadingThread = false,
}: Props) {
  const [copiedId, setCopiedId] = useState<string | null>(null);
  const [typedText, setTypedText] = useState("");
  const bottomRef = useRef<HTMLDivElement | null>(null);

  const hasMessages = messages.length > 0;
  const categoryMeta = useMemo(
    () => (category ? CATEGORY_META[category] : null),
    [category],
  );

  useEffect(() => {
    if (!category || hasMessages) {
      setTypedText("");
      return;
    }

    const full = categoryMeta?.text || "";
    let i = 0;

    const interval = window.setInterval(() => {
      i++;
      setTypedText(full.slice(0, i));
      if (i >= full.length) {
        window.clearInterval(interval);
      }
    }, 18);

    return () => window.clearInterval(interval);
  }, [category, hasMessages, categoryMeta]);

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

  useEffect(() => {
    if (!copiedId) return;

    const timeout = window.setTimeout(() => {
      setCopiedId(null);
    }, 1600);

    return () => window.clearTimeout(timeout);
  }, [copiedId]);

  const handleCopy = async (id: string, text: string) => {
    try {
      await navigator.clipboard.writeText(text);
      setCopiedId(id);
    } catch (error) {
      console.error("Copy failed:", error);
    }
  };

  return (
    <div className="flex-1 overflow-y-auto px-4 py-4 sm:px-5 sm:py-5">
      <div className="mx-auto flex h-full w-full max-w-3xl flex-col">
        {isLoadingThread && (
          <div className="flex h-full min-h-[280px] flex-col items-center justify-center text-center animate-fade-in">
            <div className="mb-4 flex items-center gap-2 rounded-full border border-slate-200 bg-white px-4 py-2 shadow-sm">
              <div className="flex gap-1">
                <div className="h-2 w-2 rounded-full bg-blue-500 animate-bounce" />
                <div
                  className="h-2 w-2 rounded-full bg-blue-500 animate-bounce"
                  style={{ animationDelay: "0.1s" }}
                />
                <div
                  className="h-2 w-2 rounded-full bg-blue-500 animate-bounce"
                  style={{ animationDelay: "0.2s" }}
                />
              </div>
              <span className="text-sm font-medium text-slate-600">
                Loading conversation...
              </span>
            </div>
            <p className="max-w-sm text-sm text-slate-500">
              Please wait while we bring back your recent messages.
            </p>
          </div>
        )}

        {!isLoadingHistory && !isLoadingThread && !hasMessages && (
          <div className="flex h-full min-h-[280px] flex-col items-center justify-center px-4 text-center animate-fade-in">
            <div className="mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-white shadow-sm ring-1 ring-slate-200">
              <Bot className="h-6 w-6 text-slate-700" />
            </div>
            <h3 className="text-sm font-semibold text-slate-800">
              How can I help you?
            </h3>
            <p className="mt-2 max-w-md text-sm leading-6 text-slate-500">
              For example, you can ask:&nbsp;
              <span className="ml-1 font-medium text-amber-600">
                &quot;Where are the social media posts?&quot;
              </span>
            </p>
          </div>
        )}

        {!isLoadingThread && hasMessages && (
          <div className="space-y-3">
            {messages.map((msg) => {
              const isAssistant = msg.role === "assistant";
              const isUser = msg.role === "user";
              const isErrorAssistant =
                isAssistant &&
                msg.content &&
                looksLikeErrorMessage(msg.content);
              const primarySource = getPrimarySource(msg.sources);
              const decodedSourceTitle = decodeHtmlEntities(
                primarySource?.title,
              );

              return (
                <div key={msg.id}>
                  {isAssistant && !msg.content ? (
                    <div className="flex w-full justify-start">
                      <div className="w-full rounded-xl border border-slate-200 bg-white px-4 py-4 shadow-sm">
                        <Skeleton />
                      </div>
                    </div>
                  ) : (
                    <>
                      <div
                        className={`flex ${
                          isUser ? "justify-end" : "justify-start"
                        }`}
                      >
                        <div
                          className={`min-w-0 max-w-[88%] sm:max-w-[75%] rounded-2xl px-4 py-2 text-sm shadow-sm transition-all duration-200 ${
                            isUser
                              ? "bg-[var(--ye-primary)] text-white rounded-br-md"
                              : isErrorAssistant
                                ? "border border-red-200 bg-red-50 text-red-900 rounded-bl-md"
                                : "border border-slate-200 bg-white text-slate-900 rounded-bl-md"
                          }`}
                        >
                          {isAssistant ? (
                            isErrorAssistant ? (
                              <div className="flex min-w-0 items-start gap-3">
                                <div className="mt-0.5 shrink-0 rounded-full bg-red-100 p-1.5">
                                  <AlertTriangle className="h-4 w-4 text-red-600" />
                                </div>
                                <div className="min-w-0">
                                  <div className="mb-1 text-sm font-semibold text-red-800">
                                    Response issue
                                  </div>
                                  <div className="whitespace-pre-wrap break-words text-sm leading-6 text-red-900">
                                    {msg.content}
                                  </div>
                                </div>
                              </div>
                            ) : (
                              <div className="min-w-0 max-w-full prose prose-sm prose-p:my-1.5 prose-pre:my-2.5 prose-code:before:hidden prose-code:after:hidden">
                                <ReactMarkdown
                                  remarkPlugins={[remarkGfm]}
                                  components={{
                                    p({ children }) {
                                      return (
                                        <p className="break-words text-sm leading-6 text-slate-800">
                                          {children}
                                        </p>
                                      );
                                    },
                                    ul({ children }) {
                                      return (
                                        <ul className="my-1.5 list-disc space-y-1 pl-5 text-sm text-slate-800">
                                          {children}
                                        </ul>
                                      );
                                    },
                                    ol({ children }) {
                                      return (
                                        <ol className="my-1.5 list-decimal space-y-1 pl-5 text-sm text-slate-800">
                                          {children}
                                        </ol>
                                      );
                                    },
                                    li({ children }) {
                                      return (
                                        <li className="break-words leading-6">
                                          {children}
                                        </li>
                                      );
                                    },
                                    a({ href, children }) {
                                      return (
                                        <a
                                          href={href}
                                          target="_blank"
                                          rel="noreferrer"
                                          className="break-all text-blue-600 underline underline-offset-2 hover:text-blue-700"
                                          style={{
                                            overflowWrap: "anywhere",
                                            wordBreak: "break-word",
                                          }}
                                        >
                                          {children}
                                        </a>
                                      );
                                    },
                                    code(props) {
                                      const { inline, className, children } =
                                        props as {
                                          inline?: boolean;
                                          className?: string;
                                          children?: React.ReactNode;
                                        };

                                      const text = String(
                                        children || "",
                                      ).replace(/\n$/, "");

                                      if (inline) {
                                        return (
                                          <code className="rounded bg-slate-100 px-1.5 py-0.5 text-[13px] text-slate-800 break-words">
                                            {children}
                                          </code>
                                        );
                                      }

                                      return (
                                        <div className="relative my-2.5 max-w-full overflow-hidden rounded-xl border border-slate-200 bg-slate-950">
                                          <div className="flex items-center justify-between border-b border-slate-800 px-3 py-2">
                                            <span className="text-[11px] uppercase tracking-wide text-slate-400">
                                              Code
                                            </span>
                                            <button
                                              onClick={() =>
                                                handleCopy(
                                                  `code-${msg.id}`,
                                                  text,
                                                )
                                              }
                                              className="rounded-md px-2 py-1 text-xs text-slate-300 transition hover:bg-slate-800 hover:text-white"
                                            >
                                              {copiedId === `code-${msg.id}`
                                                ? "Copied"
                                                : "Copy"}
                                            </button>
                                          </div>
                                          <pre className="max-w-full overflow-x-auto p-4 text-xs text-slate-100">
                                            <code className={className}>
                                              {children}
                                            </code>
                                          </pre>
                                        </div>
                                      );
                                    },
                                  }}
                                >
                                  {msg.content}
                                </ReactMarkdown>
                              </div>
                            )
                          ) : (
                            <div className="whitespace-pre-wrap break-words text-sm leading-6">
                              {msg.content}
                            </div>
                          )}

                          {isAssistant && primarySource && (
                            <div className="mt-3 min-w-0">
                              <a
                                href={primarySource.link}
                                target="_blank"
                                rel="noreferrer"
                                className="inline-flex max-w-full items-center gap-2 rounded-lg border border-slate-200 bg-slate-50 px-3 py-1.5 text-xs font-medium text-slate-700 transition hover:bg-slate-100"
                                title={decodedSourceTitle}
                              >
                                <span className="shrink-0 rounded-md bg-white px-2 py-0.5 text-[11px] font-semibold text-slate-600 ring-1 ring-slate-200">
                                  Related article
                                </span>
                                <span className="truncate max-w-[180px]">
                                  {decodedSourceTitle}
                                </span>
                                <ExternalLink className="h-3.5 w-3.5 shrink-0" />
                              </a>
                            </div>
                          )}
                        </div>
                      </div>

                      {isAssistant && msg.content && (
                        <div className="mt-1.5 flex items-center gap-1.5 pl-1 text-xs text-slate-500">
                          <button
                            onClick={() => handleCopy(msg.id, msg.content)}
                            className="inline-flex items-center gap-1 rounded-full px-2 py-1 transition hover:bg-slate-200 hover:text-slate-900"
                          >
                            <Copy className="h-3.5 w-3.5" />
                            {copiedId === msg.id ? "Copied" : "Copy"}
                          </button>

                          <button
                            onClick={() => onRegenerate(msg.id)}
                            className="inline-flex items-center gap-1 rounded-full px-2 py-1 transition hover:bg-slate-200 hover:text-slate-900"
                          >
                            <RefreshCw className="h-3.5 w-3.5" />
                            Regenerate
                          </button>

                          <button className="inline-flex items-center gap-1 rounded-full px-2 py-1 transition hover:bg-green-50 hover:text-green-700">
                            <ThumbsUp className="h-3.5 w-3.5" />
                          </button>

                          <button className="inline-flex items-center gap-1 rounded-full px-2 py-1 transition hover:bg-red-50 hover:text-red-700">
                            <ThumbsDown className="h-3.5 w-3.5" />
                          </button>
                        </div>
                      )}
                    </>
                  )}
                </div>
              );
            })}
          </div>
        )}

        <div ref={bottomRef} />
      </div>
    </div>
  );
}

function Skeleton() {
  return (
    <div className="flex w-full items-start gap-3 animate-fade-in">
      <div className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-slate-100">
        <div className="flex gap-[3px]">
          <span className="typing-dot h-1.5 w-1.5 rounded-full bg-slate-400" />
          <span className="typing-dot h-1.5 w-1.5 rounded-full bg-slate-400" />
          <span className="typing-dot h-1.5 w-1.5 rounded-full bg-slate-400" />
        </div>
      </div>

      <div className="flex-1 space-y-3">
        <div className="mb-1 text-[11px] font-medium text-slate-400">
          Thinking…
        </div>
        <div className="skeleton-line h-3 w-full rounded-full" />
        <div className="skeleton-line h-3 w-[96%] rounded-full" />
        <div className="skeleton-line h-3 w-[82%] rounded-full" />
      </div>
    </div>
  );
}
