import { useState, useMemo, useEffect, useRef } from "react"
import { Link } from "react-router-dom"
import {
  Plus,
  Trash2,
  MessageSquare,
  Loader2,
  Search,
  Edit2,
  X,
  Sparkles,
} from "lucide-react"
import {
  useConversationsQuery,
  useCreateConversationMutation,
  useDeleteConversationMutation,
} from "@/hooks/useAiChatQuery"
import { useChatPage } from "./ChatPageContext"
import type { ConversationResponse } from "@/client/model"
import { t } from "@/i18n/T"
import { Badge } from "@/components/ui/badge"
import {
  Empty,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty"

interface ChatConversationListProps {
  selectedId: string | null
  onSelect: (id: string) => void
  onNew: () => void
}

export function ChatConversationList({
  selectedId,
  onSelect,
  onNew,
}: ChatConversationListProps) {
  const { scope, projectId, projectName, selectedModel } = useChatPage()
  const { data, isLoading } = useConversationsQuery(
    scope === "project" ? projectId : null
  )
  const createMutation = useCreateConversationMutation()
  const deleteMutation = useDeleteConversationMutation()
  const [deletingId, setDeletingId] = useState<string | null>(null)
  const [searchQuery, setSearchQuery] = useState("")
  const [isSearchOpen, setIsSearchOpen] = useState(false)
  const searchInputRef = useRef<HTMLInputElement>(null)

  const getConversationLink = (id: string) => {
    if (scope === "project" && projectName) return `/${projectName}/chat/${id}`
    return `/me/chat/${id}`
  }

  const conversations = useMemo(
    () => data?.conversations || [],
    [data?.conversations]
  )

  // Filter conversations by search query
  const filteredConversations = useMemo(() => {
    if (!searchQuery.trim()) return conversations
    const q = searchQuery.toLowerCase()
    return conversations.filter((c) =>
      (c.title || "Untitled Chat").toLowerCase().includes(q)
    )
  }, [conversations, searchQuery])

  // Group conversations by date
  const groupedConversations = useMemo(() => {
    const now = new Date()
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
    const yesterday = new Date(today)
    yesterday.setDate(yesterday.getDate() - 1)
    const weekAgo = new Date(today)
    weekAgo.setDate(weekAgo.getDate() - 7)
    const monthAgo = new Date(today)
    monthAgo.setMonth(monthAgo.getMonth() - 1)

    const groups: { label: string; items: ConversationResponse[] }[] = []

    const todayItems: ConversationResponse[] = []
    const yesterdayItems: ConversationResponse[] = []
    const thisWeekItems: ConversationResponse[] = []
    const thisMonthItems: ConversationResponse[] = []
    const earlierItems: ConversationResponse[] = []

    for (const c of filteredConversations) {
      const date = new Date(c.created_at)
      if (date >= today) {
        todayItems.push(c)
      } else if (date >= yesterday) {
        yesterdayItems.push(c)
      } else if (date >= weekAgo) {
        thisWeekItems.push(c)
      } else if (date >= monthAgo) {
        thisMonthItems.push(c)
      } else {
        earlierItems.push(c)
      }
    }

    if (todayItems.length > 0)
      groups.push({ label: "Today", items: todayItems })
    if (yesterdayItems.length > 0)
      groups.push({ label: "Yesterday", items: yesterdayItems })
    if (thisWeekItems.length > 0)
      groups.push({ label: "This Week", items: thisWeekItems })
    if (thisMonthItems.length > 0)
      groups.push({ label: "This Month", items: thisMonthItems })
    if (earlierItems.length > 0)
      groups.push({ label: "Earlier", items: earlierItems })

    return groups
  }, [filteredConversations])

  const handleNew = async () => {
    onNew()
    try {
      const conversation = await createMutation.mutateAsync({
        project_id: scope === "project" ? projectId : null,
        title: "New Chat",
        model: selectedModel?.model_name ?? null,
        model_config: null,
      })
      if (conversation?.id) {
        onSelect(conversation.id)
      }
    } catch (err) {
      console.error("Failed to create conversation:", err)
    }
  }

  const handleDelete = async (e: React.MouseEvent, id: string) => {
    e.stopPropagation()
    e.preventDefault()
    setDeletingId(id)
    try {
      await deleteMutation.mutateAsync(id)
      if (selectedId === id) {
        onNew()
      }
    } catch (err) {
      console.error("Failed to delete conversation:", err)
    } finally {
      setDeletingId(null)
    }
  }

  // Cmd/Ctrl+K to focus search
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key === "k") {
        e.preventDefault()
        setIsSearchOpen(true)
        setTimeout(() => searchInputRef.current?.focus(), 0)
      }
      if (e.key === "Escape" && isSearchOpen) {
        setIsSearchOpen(false)
        setSearchQuery("")
      }
    }
    window.addEventListener("keydown", handleKeyDown)
    return () => window.removeEventListener("keydown", handleKeyDown)
  }, [isSearchOpen])

  return (
    <div
      className="flex h-full shrink-0 flex-col border-r border-[var(--border-subtle)] bg-[var(--surface-sidebar)]/95 backdrop-blur-xl"
      style={{ width: 260 }}
    >
      {/* Header */}
      <div className="flex shrink-0 items-center justify-between border-b border-[var(--border-subtle)] px-4 py-4">
        <div>
          <span
            className="text-sm font-semibold"
            style={{ color: "var(--text-primary)" }}
          >
            {t("chat.conversations.chat_history")}
          </span>
          <p className="text-[11px]" style={{ color: "var(--text-muted)" }}>
            {conversations.length} conversations
          </p>
        </div>
        <div className="flex items-center gap-0.5">
          <button
            onClick={() => setIsSearchOpen(!isSearchOpen)}
            className="flex size-8 items-center justify-center rounded-full transition-colors hover:bg-[var(--hover-bg)]"
            style={{ color: "var(--text-muted)" }}
            title={t("navigation.search_shortcut")}
          >
            <Search className="size-3.5" />
          </button>
          <button
            onClick={handleNew}
            disabled={createMutation.isPending}
            className="flex size-8 items-center justify-center rounded-full transition-colors hover:bg-[var(--hover-bg)]"
            style={{ color: "var(--text-secondary)" }}
            title={t("chat.header.new_chat")}
          >
            {createMutation.isPending ? (
              <Loader2 className="size-3.5 animate-spin" />
            ) : (
              <Edit2 className="size-3.5" />
            )}
          </button>
        </div>
      </div>

      {/* Search Input */}
      {isSearchOpen && (
        <div className="shrink-0 px-3 py-2">
          <div
            className="flex items-center gap-2 rounded-xl border px-3 py-2"
            style={{
              backgroundColor: "var(--surface-ground)",
              borderColor: "var(--border-default)",
            }}
          >
            <Search
              className="size-3.5 shrink-0"
              style={{ color: "var(--text-muted)" }}
            />
            <input
              ref={searchInputRef}
              type="text"
              placeholder={t("chat.conversations.search_placeholder")}
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className="min-w-0 flex-1 bg-transparent text-sm outline-none"
              style={{ color: "var(--text-primary)" }}
            />
            {searchQuery && (
              <button
                onClick={() => setSearchQuery("")}
                className="shrink-0"
                style={{ color: "var(--text-muted)" }}
              >
                <X className="size-3.5" />
              </button>
            )}
          </div>
        </div>
      )}

      {/* New Chat Button */}
      <div className="px-3 py-2">
        <button
          onClick={handleNew}
          disabled={createMutation.isPending}
          className="flex w-full items-center justify-center gap-2 rounded-xl border px-3 py-2 text-sm font-medium transition-all duration-200"
          style={{
            borderColor: "var(--border-subtle)",
            color: "var(--text-primary)",
            backgroundColor: "var(--surface-ground)",
          }}
        >
          <Plus className="size-4" />
          {t("chat.conversations.new_chat")}
        </button>
      </div>

      {/* List */}
      <div className="flex-1 overflow-y-auto px-2 pb-2">
        {isLoading ? (
          <div className="flex items-center justify-center py-8">
            <Loader2
              className="size-5 animate-spin"
              style={{ color: "var(--text-muted)" }}
            />
          </div>
        ) : filteredConversations.length === 0 ? (
          <Empty className="mt-6 border-[var(--border-subtle)] bg-[var(--surface-secondary)]/60 py-10">
            <EmptyHeader>
              <EmptyMedia variant="icon">
                <MessageSquare />
              </EmptyMedia>
              <EmptyTitle>
                {searchQuery
                  ? t("chat.conversations.no_matching")
                  : t("chat.conversations.no_conversations")}
              </EmptyTitle>
              <EmptyDescription>
                {searchQuery
                  ? t("chat.conversations.try_different_search")
                  : t("chat.conversations.start_new_chat")}
              </EmptyDescription>
            </EmptyHeader>
          </Empty>
        ) : (
          <div className="space-y-3">
            {groupedConversations.map((group) => (
              <div key={group.label}>
                <div
                  className="px-3 py-1 text-[11px] font-semibold tracking-[0.2em] uppercase"
                  style={{ color: "var(--text-tertiary)" }}
                >
                  {group.label}
                </div>
                <div className="space-y-0.5">
                  {group.items.map((conversation) => (
                    <ConversationItem
                      key={conversation.id}
                      conversation={conversation}
                      isSelected={selectedId === conversation.id}
                      isDeleting={deletingId === conversation.id}
                      linkTo={getConversationLink(conversation.id)}
                      onDelete={(e) => handleDelete(e, conversation.id)}
                    />
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  )
}

function ConversationItem({
  conversation,
  isSelected,
  isDeleting,
  linkTo,
  onDelete,
}: {
  conversation: ConversationResponse
  isSelected: boolean
  isDeleting: boolean
  linkTo: string
  onDelete: (e: React.MouseEvent) => void
}) {
  const date = new Date(conversation.created_at)
  const now = new Date()
  const isToday =
    date.getDate() === now.getDate() &&
    date.getMonth() === now.getMonth() &&
    date.getFullYear() === now.getFullYear()

  const timeLabel = isToday
    ? date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
    : date.toLocaleDateString([], { month: "short", day: "numeric" })

  return (
    <Link
      to={linkTo}
      className="group relative flex cursor-pointer items-center gap-2.5 rounded-xl px-3 py-2 no-underline transition-all duration-150"
      style={{
        backgroundColor: isSelected ? "var(--hover-bg-strong)" : "transparent",
        color: isSelected ? "var(--text-primary)" : "var(--text-secondary)",
        border: isSelected
          ? "1px solid var(--border-default)"
          : "1px solid transparent",
      }}
    >
      <MessageSquare
        className="size-[15px] shrink-0"
        style={{ color: isSelected ? "var(--accent)" : "var(--text-muted)" }}
      />
      <div className="min-w-0 flex-1">
        <p className="truncate text-[13px] leading-snug">
          {conversation.title || t("chat.conversations.untitled_chat")}
        </p>
      </div>
      <div className="flex items-center gap-1">
        <span
          className="shrink-0 text-[11px]"
          style={{ color: "var(--text-muted)" }}
        >
          {timeLabel}
        </span>
        <button
          onClick={onDelete}
          disabled={isDeleting}
          className="shrink-0 rounded p-1 opacity-0 transition-opacity group-hover:opacity-100"
          style={{ color: "var(--text-muted)" }}
        >
          {isDeleting ? (
            <Loader2 className="size-3.5 animate-spin" />
          ) : (
            <Trash2 className="size-3.5" />
          )}
        </button>
      </div>
    </Link>
  )
}
