import { FormEvent, KeyboardEvent, useEffect, useRef, useState } from "react";

import { moduleCatalog } from "@platform-config";
import { isModuleEnabled } from "@platform-shared";

import { portalRuntimeConfig } from "../config/runtime";
import { usePortalSession } from "../context/PortalSessionContext";
import {
  clearStoredAssistantThread,
  loadStoredAssistantThread,
  storeAssistantThread
} from "../lib/assistantThread";
import {
  AssistantConversationMessage,
  clearAssistantThread,
  fetchAssistantThread,
  fetchAssistantProfile,
  sendAssistantMessage
} from "../lib/api";

export function LandingPage() {
  const { tenantContext, currentUser } = usePortalSession();
  const [assistantName, setAssistantName] = useState("Assistente Locale");
  const [draft, setDraft] = useState("");
  const [busy, setBusy] = useState(false);
  const [messages, setMessages] = useState<AssistantConversationMessage[]>([]);
  const [threadId, setThreadId] = useState<string | null>(null);
  const threadRef = useRef<HTMLDivElement | null>(null);
  const composerRef = useRef<HTMLTextAreaElement | null>(null);
  const assistantThreadReadyRef = useRef(false);
  const interactionVersionRef = useRef(0);
  const canUseAssistant =
    currentUser?.role === "owner" ||
    currentUser?.role === "super_admin" ||
    Boolean(currentUser?.permissions?.includes("assistant"));

  useEffect(() => {
    async function loadAssistantProfile() {
      try {
        const profile = await fetchAssistantProfile(portalRuntimeConfig.apiHubBaseUrl);
        setAssistantName(profile.assistant_name);
      } catch (error) {
        console.error(error);
      }
    }

    void loadAssistantProfile();
  }, []);

  useEffect(() => {
    if (!tenantContext || !currentUser) {
      assistantThreadReadyRef.current = false;
      setThreadId(null);
      return;
    }

    if (!canUseAssistant) {
      clearStoredAssistantThread(tenantContext.tenant.id, currentUser.id);
      setMessages([]);
      setThreadId(null);
      assistantThreadReadyRef.current = true;
      return;
    }

    const storedThread = loadStoredAssistantThread(tenantContext.tenant.id, currentUser.id);
    setMessages(storedThread?.messages ?? []);
    setThreadId(storedThread?.threadId ?? null);
    if (storedThread?.assistantName) {
      setAssistantName(storedThread.assistantName);
    }
    assistantThreadReadyRef.current = false;

    let cancelled = false;
    async function loadAssistantThread() {
      try {
        const serverThread = await fetchAssistantThread(portalRuntimeConfig.apiHubBaseUrl, storedThread?.threadId ?? null);
        if (cancelled) {
          return;
        }

        if (serverThread.thread_id || serverThread.messages.length > 0 || !storedThread) {
          setThreadId(serverThread.thread_id);
          setMessages(serverThread.messages);
          setAssistantName(serverThread.assistant_name);
        }
      } catch (error) {
        console.error(error);
      } finally {
        if (!cancelled) {
          assistantThreadReadyRef.current = true;
        }
      }
    }

    void loadAssistantThread();
    return () => {
      cancelled = true;
    };
  }, [tenantContext?.tenant.id, currentUser?.id, canUseAssistant]);

  useEffect(() => {
    if (!threadRef.current) {
      return;
    }

    threadRef.current.scrollTop = threadRef.current.scrollHeight;
  }, [busy, messages]);

  useEffect(() => {
    if (!composerRef.current) {
      return;
    }

    composerRef.current.style.height = "auto";
    composerRef.current.style.height = `${Math.min(composerRef.current.scrollHeight, 220)}px`;
    composerRef.current.style.overflowY = composerRef.current.scrollHeight > 220 ? "auto" : "hidden";
  }, [draft]);

  useEffect(() => {
    if (!tenantContext || !currentUser || !assistantThreadReadyRef.current) {
      return;
    }

    storeAssistantThread(tenantContext.tenant.id, currentUser.id, {
      threadId,
      assistantName,
      messages
    });
  }, [assistantName, currentUser, messages, tenantContext, threadId]);

  async function submitMessage(message: string) {
    const trimmedMessage = message.trim();
    if (!trimmedMessage || busy) {
      return;
    }

    interactionVersionRef.current += 1;
    const requestVersion = interactionVersionRef.current;
    const nextConversation = [...messages, { role: "user" as const, content: trimmedMessage }];
    setMessages(nextConversation);
    setDraft("");
    setBusy(true);

    try {
      const response = await sendAssistantMessage(portalRuntimeConfig.apiHubBaseUrl, {
        message: trimmedMessage,
        thread_id: threadId,
        conversation: messages
      });

      if (requestVersion !== interactionVersionRef.current) {
        return;
      }
      setAssistantName(response.assistant_name);
      setThreadId(response.thread_id);
      setMessages((current) => [...current, { role: "assistant", content: response.reply }]);
    } catch (error) {
      if (requestVersion !== interactionVersionRef.current) {
        return;
      }
      console.error(error);
      setMessages((current) => [
        ...current,
        {
          role: "assistant",
          content: "Non riesco a rispondere in questo momento. Riprova tra poco."
        }
      ]);
    } finally {
      if (requestVersion === interactionVersionRef.current) {
        setBusy(false);
      }
    }
  }

  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    void submitMessage(draft);
  }

  function handleComposerKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {
    if (event.key !== "Enter" || event.shiftKey || event.nativeEvent.isComposing) {
      return;
    }

    event.preventDefault();

    if (!busy && draft.trim()) {
      void submitMessage(draft);
    }
  }

  function handleClearConversation() {
    if (!tenantContext || !currentUser) {
      return;
    }

    const currentThreadId = threadId;
    interactionVersionRef.current += 1;
    clearStoredAssistantThread(tenantContext.tenant.id, currentUser.id);
    setThreadId(null);
    setMessages([]);
    setDraft("");
    setBusy(false);
    void clearAssistantThread(portalRuntimeConfig.apiHubBaseUrl, currentThreadId).catch((error) => {
      console.error(error);
    });
  }

  if (!tenantContext) {
    return null;
  }

  const showThread = messages.length > 0 || busy;

  return (
    <section className="assistant-page">
      {(messages.length > 0 || draft.trim() || busy) && (
        <div className="assistant-toolbar">
          <button
            type="button"
            className="btn-ghost"
            onClick={handleClearConversation}
            disabled={!messages.length && !draft.trim() && !busy}
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" width={16} height={16}>
              <path d="M12 4v16m8-8H4" />
            </svg>
            Nuova chat
          </button>
        </div>
      )}

      <div className={`chat-container${showThread ? " has-thread" : ""}`}>
        {!showThread ? (
          <div className="chat-empty">
            <strong>Come posso aiutarti?</strong>
          </div>
        ) : (
          <div ref={threadRef} className="chat-thread" aria-live="polite">
            {messages.map((message, index) => (
              <article
                key={`${message.role}-${index}`}
                className={`chat-msg chat-msg-${message.role}`}
              >
                {message.role === "assistant" && (
                  <div className="chat-msg-avatar">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
                      <path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
                    </svg>
                  </div>
                )}
                <p>{message.content}</p>
              </article>
            ))}
            {busy ? (
              <article className="chat-msg chat-msg-assistant chat-msg-pending">
                <div className="chat-msg-avatar">
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
                    <path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
                  </svg>
                </div>
                <p>Sto elaborando la richiesta.</p>
              </article>
            ) : null}
          </div>
        )}

        <form className={`chat-composer${showThread ? " is-sticky" : ""}`} onSubmit={handleSubmit}>
          <div className="chat-input-row">
            <textarea
              ref={composerRef}
              value={draft}
              onChange={(event) => setDraft(event.target.value)}
              onKeyDown={handleComposerKeyDown}
              aria-label="Scrivi la tua richiesta all'assistente"
              placeholder="Scrivi un messaggio..."
              disabled={busy}
              className="chat-input"
              rows={1}
            />
            <button
              type="submit"
              className="chat-send"
              aria-label="Invia messaggio"
              disabled={busy || !draft.trim()}
            >
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
                <path d="M5 12h14M12 5l7 7-7 7" />
              </svg>
            </button>
          </div>
          <p className="chat-status" role="status">
            {busy ? `${assistantName} sta elaborando...` : ""}
          </p>
        </form>
      </div>
    </section>
  );
}
