<!-- #region AgentChat.ConversationList [C:3] [TYPE Component] [SEMANTICS agent,conversations,list,sidebar,ui] -->
<!-- @ingroup AgentChat -->
<!-- @BRIEF Sidebar conversation list — search, infinite scroll, date grouping, archive action. -->
<!-- @UX_STATE loading — skeleton cards (3-5, animate-pulse bg-surface-muted). -->
<!-- @UX_STATE loaded — grouped list with conversation titles and dates. -->
<!-- @UX_STATE empty — "Нет диалогов" placeholder. -->
<!-- @UX_STATE error — retry button. -->
<!-- @RELATION DEPENDS_ON -> $lib/ui/Input (existing) -->
<!-- @RELATION DEPENDS_ON -> $lib/ui/Button variant="ghost" (existing) -->
<!-- @RELATION BINDS_TO -> AgentChat.Model -->
<!-- Design tokens: sidebar=bg-surface-card border-r border-border, skeleton=animate-pulse bg-surface-muted -->
<script lang="ts">
  import { t } from "$lib/i18n/index.svelte.js";
  import Input from "$lib/ui/Input.svelte";
  import Button from "$lib/ui/Button.svelte";
  import Icon from "$lib/ui/Icon.svelte";
  import { ConfirmDialog } from "$lib/ui";

  let {
    conversations = [],
    currentConversationId = null,
    isLoading = false,
    hasNext = false,
    onselect = undefined,
    ondelete = undefined,
    onloadmore = undefined,
    onsearch = undefined,
  }: {
    conversations: Array<{ id: string; title: string; updated_at: string; message_count?: number }>;
    currentConversationId: string | null;
    isLoading: boolean;
    hasNext: boolean;
    onselect?: (id: string) => void;
    ondelete?: (id: string) => void;
    onloadmore?: () => void;
    onsearch?: (query: string) => void;
  } = $props();

  let searchQuery = $state("");
  let searchTimer: ReturnType<typeof setTimeout> | null = null;
  let showDeleteConfirm = $state(false);
  let pendingDeleteId: string | null = $state(null);

  // Group conversations by date on client
  let groupedConversations = $derived.by(() => {
    const groups: Map<string, typeof conversations> = new Map();
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    const thisWeek = new Date(today);
    thisWeek.setDate(thisWeek.getDate() - 7);

    for (const convo of conversations) {
      const d = new Date(convo.updated_at || convo.created_at || Date.now());
      let label: string;
      if (d >= today) {
        label = $t.assistant?.today || "Today";
      } else if (d >= yesterday) {
        label = $t.assistant?.yesterday || "Yesterday";
      } else if (d >= thisWeek) {
        label = $t.assistant?.this_week || "This week";
      } else {
        label = d.toLocaleDateString();
      }
      if (!groups.has(label)) groups.set(label, []);
      groups.get(label)!.push(convo);
    }
    return Array.from(groups.entries());
  });

  function handleSearch(value: string) {
    searchQuery = value;
    if (searchTimer) clearTimeout(searchTimer);
    searchTimer = setTimeout(() => {
      onsearch?.(value);
    }, 300);
  }

  function handleDelete(e: Event, id: string) {
    e.stopPropagation();
    pendingDeleteId = id;
    showDeleteConfirm = true;
  }
</script>

<div class="flex flex-col h-full bg-surface-card border-r border-border w-60 shrink-0">
  <!-- Search -->
  <div class="p-2 border-b border-border">
    <Input
      placeholder={$t.assistant?.search_placeholder || "Search conversations..."}
      value={searchQuery}
      oninput={(e) => handleSearch((e.target as HTMLInputElement).value)}
    />
  </div>

  <!-- List -->
  <div class="flex-1 overflow-y-auto">
    {#if isLoading && conversations.length === 0}
      <!-- Skeleton -->
      <div class="space-y-2 p-3">
        {#each Array(5) as _, i}
          <div key={i} class="animate-pulse bg-surface-muted rounded-lg h-12"></div>
        {/each}
      </div>
    {:else if conversations.length === 0}
      <!-- Empty -->
      <div class="p-4 text-sm text-text-muted text-center">
        {$t.assistant?.no_conversations || "No conversations"}
      </div>
    {:else}
      <!-- Grouped list -->
      {#each groupedConversations as [label, items]}
        <div class="px-3 pt-3 pb-1">
          <span class="text-text-muted text-xs font-semibold uppercase">{label}</span>
        </div>
        {#each items as convo (convo.id)}
          <div
            class={`w-full flex items-center justify-between gap-1 px-3 py-2 text-sm cursor-pointer transition hover:bg-surface-muted ${convo.id === currentConversationId ? "bg-surface-muted" : ""}`}
            onclick={() => onselect?.(convo.id)}
            role="button"
            tabindex="0"
            onkeydown={(e) => e.key === "Enter" && onselect?.(convo.id)}
          >
            <div class="min-w-0 flex-1">
              <div class="truncate font-medium text-text">{convo.title || "New Conversation"}</div>
              <div class="text-xs text-text-muted mt-0.5">
                {convo.message_count ? `${convo.message_count} msgs` : ""}
              </div>
            </div>
            <button
              class="shrink-0 rounded p-1 text-text-subtle hover:text-destructive hover:bg-destructive-light"
              onclick={(e) => handleDelete(e, convo.id)}
              title={$t.assistant?.delete || "Delete"}
            >
              <Icon name="trash" size={12} />
            </button>
          </div>
        {/each}
      {/each}

      <!-- Load more -->
      {#if hasNext}
        <div class="p-3">
          <Button variant="ghost" size="sm" onclick={() => onloadmore?.()}>
            {$t.assistant?.load_more || "Load more"}
          </Button>
        </div>
      {/if}
    {/if}
  </div>
</div>

<ConfirmDialog
  bind:show={showDeleteConfirm}
  title={$t.assistant?.delete_title || "Delete conversation?"}
  message={$t.assistant?.delete_confirm || "This conversation will be permanently deleted."}
  variant="destructive"
  confirmLabel={$t.assistant?.delete || "Delete"}
  cancelLabel={$t.common?.cancel || "Cancel"}
  onConfirm={() => { if (pendingDeleteId) ondelete?.(pendingDeleteId); }}
  onCancel={() => { pendingDeleteId = null; }}
/>

<!-- #endregion AgentChat.ConversationList -->
