import { useServerFn } from "@tanstack/react-start";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useRef, useState } from "react";

import {
  getVisitorMessages,
  sendVisitorMessage,
  startChat,
} from "@/lib/chat.functions";

type StoredSession = { sessionId: string; secret: string; name: string };

type ChatMessage = {
  id: string;
  sender: "visitor" | "owner";
  body: string;
  created_at: string;
};

const STORAGE_KEY = "shahnoor-chat-session";

function loadStoredSession(): StoredSession | null {
  if (typeof window === "undefined") return null;
  try {
    const raw = window.localStorage.getItem(STORAGE_KEY);
    return raw ? (JSON.parse(raw) as StoredSession) : null;
  } catch {
    return null;
  }
}

export function ChatWidget() {
  const [open, setOpen] = useState(false);
  const [session, setSession] = useState<StoredSession | null>(null);
  const [name, setName] = useState("");
  const [phone, setPhone] = useState("");
  const [draft, setDraft] = useState("");
  const [starting, setStarting] = useState(false);
  const [error, setError] = useState("");
  const scrollRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const queryClient = useQueryClient();

  const startChatFn = useServerFn(startChat);
  const sendMessageFn = useServerFn(sendVisitorMessage);
  const getMessagesFn = useServerFn(getVisitorMessages);

  useEffect(() => {
    setSession(loadStoredSession());
  }, []);

  const { data } = useQuery({
    queryKey: ["visitor-chat", session?.sessionId],
    enabled: open && !!session,
    refetchInterval: 4000,
    queryFn: () =>
      getMessagesFn({
        data: { sessionId: session!.sessionId, secret: session!.secret },
      }),
  });

  const messages: ChatMessage[] = (data?.messages ?? []) as ChatMessage[];

  useEffect(() => {
    scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });
  }, [messages.length, open]);

  useEffect(() => {
    if (open && session) inputRef.current?.focus();
  }, [open, session]);

  async function handleStart(e: React.FormEvent) {
    e.preventDefault();
    if (!name.trim() || starting) return;
    setStarting(true);
    setError("");
    try {
      const result = await startChatFn({
        data: { name: name.trim(), phone: phone.trim() || undefined },
      });
      const next: StoredSession = {
        sessionId: result.sessionId,
        secret: result.secret,
        name: name.trim(),
      };
      window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
      setSession(next);
    } catch {
      setError("Could not start the chat. Please try again or call us.");
    } finally {
      setStarting(false);
    }
  }

  async function handleSend(e: React.FormEvent) {
    e.preventDefault();
    const body = draft.trim();
    if (!body || !session) return;
    setDraft("");
    try {
      await sendMessageFn({
        data: { sessionId: session.sessionId, secret: session.secret, body },
      });
      await queryClient.invalidateQueries({
        queryKey: ["visitor-chat", session.sessionId],
      });
    } catch {
      setDraft(body);
      setError("Message failed to send. Please try again.");
    }
    inputRef.current?.focus();
  }

  function handleNewChat() {
    window.localStorage.removeItem(STORAGE_KEY);
    setSession(null);
    setName("");
    setPhone("");
    setDraft("");
  }

  return (
    <>
      {open && (
        <div className="lc-panel" role="dialog" aria-label="Live chat">
          <div className="lc-header">
            <div>
              <p className="lc-title">Shahnoor Taxi Service</p>
              <p className="lc-subtitle">We usually reply within minutes</p>
            </div>
            <div className="lc-header-actions">
              {session && (
                <button
                  type="button"
                  className="lc-icon-btn"
                  onClick={handleNewChat}
                  title="Start a new chat"
                  aria-label="Start a new chat"
                >
                  ⟳
                </button>
              )}
              <button
                type="button"
                className="lc-icon-btn"
                onClick={() => setOpen(false)}
                aria-label="Close chat"
              >
                ✕
              </button>
            </div>
          </div>

          {!session ? (
            <form className="lc-start" onSubmit={handleStart}>
              <p className="lc-start-text">
                Chat with us directly — ask about fares, availability, or book a
                ride across Goa.
              </p>
              <input
                className="input"
                placeholder="Your name"
                value={name}
                onChange={(e) => setName(e.target.value)}
                required
                maxLength={80}
              />
              <input
                className="input"
                placeholder="Phone number (optional)"
                value={phone}
                onChange={(e) => setPhone(e.target.value)}
                maxLength={20}
                inputMode="tel"
              />
              {error && <p className="lc-error">{error}</p>}
              <button className="btn btn-primary lc-full" disabled={starting}>
                {starting ? "Starting…" : "Start chat"}
              </button>
            </form>
          ) : (
            <>
              <div className="lc-messages" ref={scrollRef}>
                {messages.length === 0 && (
                  <p className="lc-empty">
                    Hi {session.name}! Send us a message and we'll reply here.
                  </p>
                )}
                {messages.map((m) => (
                  <div
                    key={m.id}
                    className={`lc-bubble ${m.sender === "visitor" ? "lc-mine" : "lc-theirs"}`}
                  >
                    {m.body}
                  </div>
                ))}
                {data?.status === "closed" && (
                  <p className="lc-empty">
                    This chat was closed. Start a new chat anytime.
                  </p>
                )}
              </div>
              {error && <p className="lc-error lc-error-pad">{error}</p>}
              <form className="lc-composer" onSubmit={handleSend}>
                <input
                  ref={inputRef}
                  className="input"
                  placeholder="Type a message…"
                  value={draft}
                  onChange={(e) => setDraft(e.target.value)}
                  maxLength={1000}
                />
                <button
                  className="btn btn-primary lc-send"
                  disabled={!draft.trim()}
                  aria-label="Send message"
                >
                  ➤
                </button>
              </form>
            </>
          )}
        </div>
      )}

      <button
        type="button"
        className="lc-fab"
        onClick={() => setOpen((v) => !v)}
        aria-label={open ? "Close live chat" : "Open live chat"}
      >
        {open ? (
          "✕"
        ) : (
          <svg viewBox="0 0 24 24" fill="currentColor" className="lc-fab-icon" aria-hidden="true">
            <path d="M12 3C6.48 3 2 6.94 2 11.75c0 2.66 1.35 5.03 3.47 6.6-.11.9-.62 2.4-1.47 3.65 1.9-.1 3.66-.96 4.83-1.96.99.22 2.04.34 3.17.34 5.52 0 10-3.94 10-8.63S17.52 3 12 3z" />
          </svg>
        )}
      </button>
    </>
  );
}
