"use client";

import { useState, useEffect, forwardRef, useImperativeHandle, useCallback } from "react";
import { getConversations, type Idea } from "@/lib/api/ideas";
import { useAuth } from "@/lib/auth/auth-context";
import { safeJsonParse, isMessageArray } from "@/lib/utils/safe-json";

interface ConversationSummary {
  id: string;
  title: string | null;
  projectId: string | null;
  updatedAt: string;
  messageCount: number;
}

export interface ConversationSidebarRef {
  refresh: () => Promise<void>;
  addConversation: (conversation: ConversationSummary) => void;
}

interface ConversationSidebarProps {
  isOpen: boolean;
  onClose: () => void;
  currentConversationId: string | null;
  onSelectConversation: (conversationId: string | null) => Promise<void>;
  onNewConversation: (projectId?: string | null) => void;
}

export const ConversationSidebar = forwardRef<ConversationSidebarRef, ConversationSidebarProps>(
  function ConversationSidebar(
    { isOpen, onClose, currentConversationId, onSelectConversation, onNewConversation },
    ref
  ) {
    const [searchQuery, setSearchQuery] = useState("");
    const [conversations, setConversations] = useState<ConversationSummary[]>([]);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const { user } = useAuth();

    /**
     * Convert Idea to ConversationSummary
     */
    const ideaToConversation = useCallback((idea: Idea): ConversationSummary => {
      // Count messages from the stored JSON content with runtime validation
      const messages = safeJsonParse(idea.content, isMessageArray, []);
      const messageCount = messages.length;

      return {
        id: idea.id,
        title: idea.title ?? null,
        projectId: idea.projectId ?? null,
        updatedAt: idea.updatedAt,
        messageCount,
      };
    }, []);

    /**
     * Fetch conversations from backend
     */
    const fetchConversations = useCallback(async (): Promise<void> => {
      if (!user) {
        setConversations([]);
        return;
      }

      try {
        setIsLoading(true);
        setError(null);

        const response = await getConversations({
          limit: 50,
          page: 1,
        });

        const summaries = response.data.map(ideaToConversation);
        setConversations(summaries);
      } catch (err) {
        const errorMsg = err instanceof Error ? err.message : "Failed to load conversations";
        setError(errorMsg);
        // Error is set to state and will be displayed to the user
      } finally {
        setIsLoading(false);
      }
    }, [user, ideaToConversation]);

    // Load conversations on mount and when user changes
    useEffect(() => {
      void fetchConversations();
    }, [fetchConversations]);

    // Expose methods to parent via ref
    useImperativeHandle(
      ref,
      (): ConversationSidebarRef => ({
        refresh: async (): Promise<void> => {
          await fetchConversations();
        },
        addConversation: (conversation: ConversationSummary): void => {
          setConversations((prev) => [conversation, ...prev]);
        },
      })
    );

    const filteredConversations = conversations.filter((conv): boolean => {
      if (!searchQuery.trim()) return true;
      const title = conv.title ?? "Untitled conversation";
      return title.toLowerCase().includes(searchQuery.toLowerCase());
    });

    const formatRelativeTime = (dateString: string): string => {
      const date = new Date(dateString);
      const now = new Date();
      const diffMs = now.getTime() - date.getTime();
      const diffMins = Math.floor(diffMs / 60000);
      const diffHours = Math.floor(diffMs / 3600000);
      const diffDays = Math.floor(diffMs / 86400000);

      if (diffMins < 1) return "Just now";
      if (diffMins < 60) return `${String(diffMins)}m ago`;
      if (diffHours < 24) return `${String(diffHours)}h ago`;
      if (diffDays < 7) return `${String(diffDays)}d ago`;
      return date.toLocaleDateString(undefined, { month: "short", day: "numeric" });
    };

    const truncateTitle = (title: string | null, maxLength = 32): string => {
      const displayTitle = title ?? "Untitled conversation";
      if (displayTitle.length <= maxLength) return displayTitle;
      return displayTitle.substring(0, maxLength - 1) + "…";
    };

    return (
      <>
        {/* Mobile overlay */}
        {isOpen && (
          <div
            className="fixed inset-0 z-40 md:hidden animate-fade-in"
            style={{ backgroundColor: "rgb(0 0 0 / 0.6)" }}
            onClick={onClose}
            aria-hidden="true"
          />
        )}

        {/* Sidebar */}
        <aside
          className={`
          fixed left-0 top-0 z-50 h-screen transform border-r transition-all duration-200 ease-out flex flex-col
          md:sticky md:top-0 md:z-auto md:h-screen md:transform-none md:transition-[width]
          ${isOpen ? "translate-x-0 w-72" : "-translate-x-full md:translate-x-0 md:w-16"}
        `}
          style={{
            backgroundColor: "rgb(var(--surface-0))",
            borderColor: "rgb(var(--border-default))",
          }}
          aria-label="Conversation history"
        >
          {/* Collapsed view */}
          {!isOpen && (
            <div className="hidden md:flex flex-col items-center py-3 h-full">
              <button
                onClick={() => {
                  onNewConversation();
                }}
                className="p-3 rounded-lg transition-colors hover:bg-[rgb(var(--surface-1))]"
                title="New Conversation"
              >
                <svg
                  className="h-5 w-5"
                  style={{ color: "rgb(var(--text-muted))" }}
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  strokeWidth={2}
                >
                  <path d="M12 4v16m8-8H4" />
                </svg>
              </button>
            </div>
          )}

          {/* Full sidebar content */}
          {isOpen && (
            <>
              {/* Header */}
              <div
                className="flex items-center justify-between border-b px-4 py-3"
                style={{ borderColor: "rgb(var(--border-default))" }}
              >
                <div className="flex items-center gap-2">
                  <svg
                    className="h-5 w-5"
                    style={{ color: "rgb(var(--text-muted))" }}
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    strokeWidth={1.5}
                  >
                    <path d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
                  </svg>
                  <span
                    className="text-sm font-semibold"
                    style={{ color: "rgb(var(--text-primary))" }}
                  >
                    Conversations
                  </span>
                </div>

                <button
                  onClick={onClose}
                  className="btn-ghost rounded-md p-1.5"
                  aria-label="Close sidebar"
                >
                  <svg
                    className="h-5 w-5"
                    style={{ color: "rgb(var(--text-muted))" }}
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    strokeWidth={1.5}
                  >
                    <path d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
              </div>

              {/* New Chat Button */}
              <div className="px-3 pt-3">
                <button
                  onClick={() => {
                    onNewConversation();
                  }}
                  className="w-full flex items-center justify-center gap-2 rounded-lg border border-dashed py-2.5 text-sm font-medium transition-all duration-150 hover:border-solid"
                  style={{
                    borderColor: "rgb(var(--border-strong))",
                    color: "rgb(var(--text-secondary))",
                  }}
                >
                  <svg
                    className="h-4 w-4"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    strokeWidth={2}
                  >
                    <path d="M12 4v16m8-8H4" />
                  </svg>
                  <span>New Conversation</span>
                </button>
              </div>

              {/* Search */}
              <div className="px-3 pt-3">
                <div className="relative">
                  <svg
                    className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2"
                    style={{ color: "rgb(var(--text-muted))" }}
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    strokeWidth={2}
                  >
                    <circle cx="11" cy="11" r="8" />
                    <path d="M21 21l-4.35-4.35" />
                  </svg>
                  <input
                    type="text"
                    placeholder="Search conversations..."
                    value={searchQuery}
                    onChange={(e) => {
                      setSearchQuery(e.target.value);
                    }}
                    className="input pl-9 pr-10 py-2 text-sm"
                    style={{ backgroundColor: "rgb(var(--surface-1))" }}
                  />
                </div>
              </div>

              {/* Conversations List */}
              <div className="flex-1 overflow-y-auto px-3 pt-3 pb-3 space-y-1">
                {isLoading ? (
                  <div className="text-center py-8" style={{ color: "rgb(var(--text-muted))" }}>
                    <div
                      className="h-5 w-5 mx-auto animate-spin rounded-full border-2 border-t-transparent"
                      style={{
                        borderColor: "rgb(var(--accent-primary))",
                        borderTopColor: "transparent",
                      }}
                    />
                    <p className="text-xs mt-2">Loading conversations...</p>
                  </div>
                ) : error ? (
                  <div className="text-center py-8" style={{ color: "rgb(var(--semantic-error))" }}>
                    <svg
                      className="h-8 w-8 mx-auto mb-2"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                      strokeWidth={2}
                    >
                      <circle cx="12" cy="12" r="10" />
                      <line x1="12" y1="8" x2="12" y2="12" />
                      <line x1="12" y1="16" x2="12.01" y2="16" />
                    </svg>
                    <p className="text-xs">{error}</p>
                    <button
                      onClick={() => void fetchConversations()}
                      className="text-xs mt-2 underline"
                      style={{ color: "rgb(var(--accent-primary))" }}
                    >
                      Retry
                    </button>
                  </div>
                ) : filteredConversations.length === 0 ? (
                  <div className="text-center py-8" style={{ color: "rgb(var(--text-muted))" }}>
                    <p className="text-sm">
                      {searchQuery ? "No matching conversations" : "No conversations yet"}
                    </p>
                    <p className="text-xs mt-1">
                      {searchQuery ? "Try a different search" : "Start a new chat to begin"}
                    </p>
                  </div>
                ) : (
                  filteredConversations.map((conv) => (
                    <button
                      key={conv.id}
                      onClick={() => void onSelectConversation(conv.id)}
                      className={`w-full text-left px-3 py-2 rounded-lg transition-colors ${
                        conv.id === currentConversationId
                          ? "bg-[rgb(var(--accent-primary-light))]"
                          : "hover:bg-[rgb(var(--surface-2))]"
                      }`}
                    >
                      <p
                        className="text-sm font-medium truncate"
                        style={{
                          color:
                            conv.id === currentConversationId
                              ? "rgb(var(--accent-primary))"
                              : "rgb(var(--text-primary))",
                        }}
                      >
                        {truncateTitle(conv.title)}
                      </p>
                      <div
                        className="flex items-center gap-2 mt-0.5"
                        style={{ color: "rgb(var(--text-muted))" }}
                      >
                        <span className="text-xs">{formatRelativeTime(conv.updatedAt)}</span>
                        {conv.messageCount > 0 && (
                          <>
                            <span className="text-xs">·</span>
                            <span className="text-xs">
                              {conv.messageCount} msg{conv.messageCount !== 1 ? "s" : ""}
                            </span>
                          </>
                        )}
                      </div>
                    </button>
                  ))
                )}
              </div>
            </>
          )}
        </aside>
      </>
    );
  }
);
