"use client"

import {
  useCallback,
  useImperativeHandle,
  useMemo,
  useRef,
  useState,
  type Ref,
} from "react"
import { useTranslations } from "next-intl"
import { toast } from "sonner"
import { CheckCheck, ChevronRight, Download, Loader2, Plus } from "lucide-react"
import { useFolderContext } from "@/contexts/folder-context"
import { useTabContext } from "@/contexts/tab-context"
import { useTaskContext } from "@/contexts/task-context"
import {
  importLocalConversations,
  updateConversationTitle,
  updateConversationStatus,
  deleteConversation,
} from "@/lib/tauri"
import type { ConversationStatus, DbConversationSummary } from "@/lib/types"
import { STATUS_ORDER, STATUS_COLORS } from "@/lib/types"
import { SidebarConversationCard } from "./sidebar-conversation-card"
import { Button } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import {
  Collapsible,
  CollapsibleTrigger,
  CollapsibleContent,
} from "@/components/ui/collapsible"
import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
} from "@/components/ui/context-menu"
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog"
import { cn } from "@/lib/utils"

function parseTimestamp(value: string): number {
  const timestamp = Date.parse(value)
  return Number.isNaN(timestamp) ? 0 : timestamp
}

function compareByUpdatedAtDesc(
  left: DbConversationSummary,
  right: DbConversationSummary
): number {
  const updatedDiff =
    parseTimestamp(right.updated_at) - parseTimestamp(left.updated_at)
  if (updatedDiff !== 0) return updatedDiff

  const createdDiff =
    parseTimestamp(right.created_at) - parseTimestamp(left.created_at)
  if (createdDiff !== 0) return createdDiff

  return right.id - left.id
}

export interface SidebarConversationListHandle {
  scrollToActive: () => void
  expandAll: () => void
  collapseAll: () => void
}

export function SidebarConversationList({
  ref,
}: {
  ref?: Ref<SidebarConversationListHandle>
}) {
  const t = useTranslations("Folder.sidebar")
  const tStatus = useTranslations("Folder.statusLabels")
  const tCommon = useTranslations("Folder.common")
  const {
    folder,
    conversations,
    loading,
    refreshing,
    error,
    selectedConversation,
    folderId,
    refreshConversations,
  } = useFolderContext()

  const { openTab, closeConversationTab, openNewConversationTab } =
    useTabContext()
  const { addTask, updateTask } = useTaskContext()

  const [importing, setImporting] = useState(false)
  const [completeReviewOpen, setCompleteReviewOpen] = useState(false)
  const [completingReview, setCompletingReview] = useState(false)
  const [groupExpanded, setGroupExpanded] = useState<
    Record<ConversationStatus, boolean>
  >({
    in_progress: true,
    pending_review: true,
    completed: false,
    cancelled: false,
  })

  const scrollContainerRef = useRef<HTMLDivElement>(null)

  useImperativeHandle(ref, () => ({
    scrollToActive() {
      if (!selectedConversation) return
      const conv = conversations.find(
        (c) =>
          c.id === selectedConversation.id &&
          c.agent_type === selectedConversation.agentType
      )
      if (!conv) return
      const status = conv.status as ConversationStatus
      if (!groupExpanded[status]) {
        setGroupExpanded((prev) => ({ ...prev, [status]: true }))
        requestAnimationFrame(() => {
          const el = scrollContainerRef.current?.querySelector(
            `[data-conversation-id="${selectedConversation.id}"]`
          )
          el?.scrollIntoView({ block: "center", behavior: "smooth" })
        })
      } else {
        const el = scrollContainerRef.current?.querySelector(
          `[data-conversation-id="${selectedConversation.id}"]`
        )
        el?.scrollIntoView({ block: "center", behavior: "smooth" })
      }
    },
    expandAll() {
      setGroupExpanded({
        in_progress: true,
        pending_review: true,
        completed: true,
        cancelled: true,
      })
    },
    collapseAll() {
      setGroupExpanded({
        in_progress: false,
        pending_review: false,
        completed: false,
        cancelled: false,
      })
    },
  }))

  const grouped = useMemo(() => {
    const map = new Map<ConversationStatus, DbConversationSummary[]>()
    for (const conv of conversations) {
      const status = conv.status as ConversationStatus
      const list = map.get(status)
      if (list) {
        list.push(conv)
      } else {
        map.set(status, [conv])
      }
    }
    for (const list of map.values()) {
      list.sort(compareByUpdatedAtDesc)
    }
    return map
  }, [conversations])

  const reviewConversations = useMemo(
    () => grouped.get("pending_review") ?? [],
    [grouped]
  )
  const reviewConversationCount = reviewConversations.length

  const toggleGroup = useCallback((status: ConversationStatus) => {
    setGroupExpanded((prev) => ({ ...prev, [status]: !prev[status] }))
  }, [])

  const handleSelect = useCallback(
    (id: number, agentType: string) => {
      openTab(id, agentType as Parameters<typeof openTab>[1], false)
    },
    [openTab]
  )

  const handleDoubleClick = useCallback(
    (id: number, agentType: string) => {
      openTab(id, agentType as Parameters<typeof openTab>[1], true)
    },
    [openTab]
  )

  const handleRename = useCallback(
    async (id: number, newTitle: string) => {
      await updateConversationTitle(id, newTitle)
      refreshConversations()
    },
    [refreshConversations]
  )

  const handleDelete = useCallback(
    async (id: number, agentType: string) => {
      await deleteConversation(id)
      closeConversationTab(id, agentType as Parameters<typeof openTab>[1])
      refreshConversations()
    },
    [closeConversationTab, refreshConversations]
  )

  const handleStatusChange = useCallback(
    async (id: number, status: ConversationStatus) => {
      await updateConversationStatus(id, status)
      refreshConversations()
    },
    [refreshConversations]
  )

  const handleNewConversation = useCallback(() => {
    if (!folder) return
    openNewConversationTab("codex", folder.path)
  }, [folder, openNewConversationTab])

  const handleImport = useCallback(async () => {
    if (importing) return
    setImporting(true)
    const taskId = `import-${folderId}-${Date.now()}`
    addTask(taskId, t("importLocalSessions"))
    updateTask(taskId, { status: "running" })
    try {
      const result = await importLocalConversations(folderId)
      updateTask(taskId, { status: "completed" })
      refreshConversations()
      if (result.imported > 0) {
        toast.success(
          t("toasts.importedSessions", {
            imported: result.imported,
            skipped: result.skipped,
          })
        )
      } else {
        toast.info(t("toasts.noNewSessionsFound", { skipped: result.skipped }))
      }
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e)
      updateTask(taskId, { status: "failed", error: msg })
      toast.error(t("toasts.importFailed", { message: msg }))
    } finally {
      setImporting(false)
    }
  }, [importing, folderId, addTask, updateTask, refreshConversations, t])

  const handleCompleteAllReview = useCallback(async () => {
    if (completingReview || reviewConversationCount === 0) return
    setCompletingReview(true)
    try {
      await Promise.all(
        reviewConversations.map((conversation) =>
          updateConversationStatus(conversation.id, "completed")
        )
      )
      refreshConversations()
      toast.success(
        t("toasts.reviewCompleted", { count: reviewConversationCount })
      )
      setCompleteReviewOpen(false)
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e)
      toast.error(t("toasts.completeReviewFailed", { message: msg }))
    } finally {
      setCompletingReview(false)
    }
  }, [
    completingReview,
    reviewConversationCount,
    reviewConversations,
    refreshConversations,
    t,
  ])

  return (
    <div className="flex flex-col flex-1 min-h-0">
      {(loading || refreshing) && (
        <div className="flex items-center justify-center py-1">
          <Loader2 className="h-3.5 w-3.5 animate-spin text-muted-foreground" />
        </div>
      )}

      {loading && !refreshing ? (
        <div className="px-3 space-y-1.5 overflow-hidden">
          {Array.from({ length: 6 }).map((_, i) => (
            <Skeleton key={i} className="h-14 w-full rounded-md" />
          ))}
        </div>
      ) : error ? (
        <div className="flex-1 flex items-center justify-center px-3">
          <p className="text-destructive text-xs">
            {t("error", { message: error })}
          </p>
        </div>
      ) : conversations.length === 0 ? (
        <ContextMenu>
          <ContextMenuTrigger asChild>
            <div className="flex-1 flex flex-col items-center justify-center px-3 gap-3">
              <p className="text-muted-foreground text-xs text-center">
                {t("noConversationsFound")}
              </p>
              <Button
                variant="outline"
                size="sm"
                disabled={importing}
                onClick={handleImport}
              >
                {importing ? (
                  <Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" />
                ) : (
                  <Download className="h-3.5 w-3.5 mr-1.5" />
                )}
                {importing ? t("importing") : t("importLocalSessions")}
              </Button>
            </div>
          </ContextMenuTrigger>
          <ContextMenuContent>
            <ContextMenuItem onSelect={handleNewConversation}>
              <Plus className="h-4 w-4" />
              {t("newConversation")}
            </ContextMenuItem>
            <ContextMenuSeparator />
            <ContextMenuItem disabled={importing} onSelect={handleImport}>
              <Download className="h-4 w-4" />
              {importing ? t("importing") : t("importLocalSessions")}
            </ContextMenuItem>
          </ContextMenuContent>
        </ContextMenu>
      ) : (
        <ContextMenu>
          <ContextMenuTrigger asChild>
            <div
              ref={scrollContainerRef}
              className={cn(
                "flex-1 min-h-0 overflow-y-auto px-1.5",
                "[&::-webkit-scrollbar]:w-1.5",
                "[&::-webkit-scrollbar-thumb]:rounded-full",
                "[&::-webkit-scrollbar-thumb]:bg-border"
              )}
            >
              {STATUS_ORDER.map((status) => {
                const items = grouped.get(status)
                if (!items || items.length === 0) return null
                const isOpen = groupExpanded[status]
                const groupHeader = (
                  <CollapsibleTrigger className="sticky top-0 z-10 bg-sidebar flex items-center gap-1.5 w-full px-1.5 py-1.5 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors cursor-pointer">
                    <ChevronRight
                      className={cn(
                        "h-3.5 w-3.5 shrink-0 transition-transform",
                        isOpen && "rotate-90"
                      )}
                    />
                    <span
                      className={cn(
                        "w-2 h-2 rounded-full shrink-0",
                        STATUS_COLORS[status]
                      )}
                    />
                    <span>{tStatus(status)}</span>
                    <span className="ml-auto text-muted-foreground/60 tabular-nums">
                      {items.length}
                    </span>
                  </CollapsibleTrigger>
                )
                return (
                  <Collapsible
                    key={status}
                    open={isOpen}
                    onOpenChange={() => toggleGroup(status)}
                  >
                    {status === "pending_review" ? (
                      <ContextMenu>
                        <ContextMenuTrigger asChild>
                          {groupHeader}
                        </ContextMenuTrigger>
                        <ContextMenuContent>
                          <ContextMenuItem
                            disabled={
                              reviewConversationCount === 0 || completingReview
                            }
                            onSelect={() => setCompleteReviewOpen(true)}
                          >
                            <CheckCheck className="h-4 w-4" />
                            {t("completeAllSessions")}
                          </ContextMenuItem>
                        </ContextMenuContent>
                      </ContextMenu>
                    ) : (
                      groupHeader
                    )}
                    <CollapsibleContent>
                      <div className="space-y-0.5 pb-1">
                        {items.map((conversation) => {
                          const isSelected =
                            selectedConversation?.agentType ===
                              conversation.agent_type &&
                            selectedConversation?.id === conversation.id
                          return (
                            <SidebarConversationCard
                              key={conversation.id}
                              conversation={conversation}
                              isSelected={isSelected}
                              onSelect={handleSelect}
                              onDoubleClick={handleDoubleClick}
                              onRename={handleRename}
                              onDelete={handleDelete}
                              onStatusChange={handleStatusChange}
                              onNewConversation={handleNewConversation}
                              onImport={handleImport}
                              importing={importing}
                            />
                          )
                        })}
                      </div>
                    </CollapsibleContent>
                  </Collapsible>
                )
              })}
            </div>
          </ContextMenuTrigger>
          <ContextMenuContent>
            <ContextMenuItem onSelect={handleNewConversation}>
              <Plus className="h-4 w-4" />
              {t("newConversation")}
            </ContextMenuItem>
            <ContextMenuSeparator />
            <ContextMenuItem disabled={importing} onSelect={handleImport}>
              <Download className="h-4 w-4" />
              {importing ? t("importing") : t("importLocalSessions")}
            </ContextMenuItem>
          </ContextMenuContent>
        </ContextMenu>
      )}
      <AlertDialog
        open={completeReviewOpen}
        onOpenChange={(open) =>
          !completingReview && setCompleteReviewOpen(open)
        }
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>{t("completeAllReviewTitle")}</AlertDialogTitle>
            <AlertDialogDescription>
              {t("completeAllReviewDescription", {
                count: reviewConversationCount,
              })}
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={completingReview}>
              {tCommon("cancel")}
            </AlertDialogCancel>
            <AlertDialogAction
              disabled={completingReview || reviewConversationCount === 0}
              onClick={handleCompleteAllReview}
            >
              {completingReview ? t("completing") : tCommon("confirm")}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  )
}
