// SPDX-License-Identifier: LicenseRef-Commercial
<script lang="ts">
  import {
    proMemoryList,
    proMemorySearch,
    proMemoryAdd,
    proMemoryDelete,
    proMemoryInject,
    type MemoryFragment,
  } from './pro-bridge';

  interface Props {
    projectId: string;
  }

  let { projectId }: Props = $props();

  let loading = $state(true);
  let error = $state<string | null>(null);
  let memories = $state<MemoryFragment[]>([]);
  let searchQuery = $state('');
  let searching = $state(false);

  // Add form
  let showAddForm = $state(false);
  let addContent = $state('');
  let addTags = $state('');
  let addSource = $state<'human' | 'agent' | 'auto'>('human');
  let adding = $state(false);

  // Expand/collapse
  let expandedIds = $state<Set<number>>(new Set());
  function toggleExpand(id: number) {
    const next = new Set(expandedIds);
    next.has(id) ? next.delete(id) : next.add(id);
    expandedIds = next;
  }

  // Delete confirmation
  let confirmDeleteId = $state<number | null>(null);

  // Inject
  let injectedPreview = $state<string | null>(null);
  let injecting = $state(false);

  const TRUST_COLORS: Record<string, string> = {
    human: 'var(--ctp-green)',
    agent: 'var(--ctp-yellow)',
    auto: 'var(--ctp-blue)',
  };

  function errMsg(e: unknown): string { return e instanceof Error ? e.message : String(e); }

  async function loadMemories() {
    loading = true; error = null;
    try { memories = await proMemoryList(projectId, 50); }
    catch (e) { error = errMsg(e); }
    finally { loading = false; }
  }

  $effect(() => { void projectId; loadMemories(); });

  async function doSearch() {
    if (!searchQuery.trim()) { loadMemories(); return; }
    searching = true; error = null;
    try { memories = await proMemorySearch(projectId, searchQuery.trim()); }
    catch (e) { error = errMsg(e); }
    finally { searching = false; }
  }

  async function addMemory() {
    if (!addContent.trim()) return;
    adding = true;
    try {
      await proMemoryAdd(projectId, addContent.trim(), addSource, addTags.trim());
      addContent = ''; addTags = ''; showAddForm = false;
      await loadMemories();
    } catch (e) { error = errMsg(e); }
    finally { adding = false; }
  }

  async function removeMemory(id: number) {
    try { await proMemoryDelete(id); memories = memories.filter((m) => m.id !== id); }
    catch (e) { error = errMsg(e); }
  }

  async function injectContext() {
    injecting = true;
    try { injectedPreview = await proMemoryInject(projectId, 4000); }
    catch (e) { error = errMsg(e); }
    finally { injecting = false; }
  }

  function fmtDate(ts: number): string {
    return new Date(ts * 1000).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
  }
</script>

<div class="memory-root">
  <div class="toolbar">
    <div class="search-row">
      <input
        class="search-input"
        type="text"
        placeholder="Search memories..."
        bind:value={searchQuery}
        onkeydown={(e: KeyboardEvent) => e.key === 'Enter' && doSearch()}
      />
      <button class="btn" onclick={doSearch} disabled={searching}>
        {searching ? '...' : 'Search'}
      </button>
    </div>
    <div class="action-row">
      <button class="btn" onclick={() => (showAddForm = !showAddForm)}>
        {showAddForm ? 'Cancel' : '+ Add Memory'}
      </button>
      <button class="btn secondary" onclick={injectContext} disabled={injecting}>
        {injecting ? 'Injecting...' : 'Inject Context'}
      </button>
      <button class="btn secondary" disabled title="Coming soon">Extract from Session</button>
    </div>
  </div>

  {#if showAddForm}
    <div class="add-form">
      <textarea class="add-textarea" bind:value={addContent} placeholder="Memory content..." rows="3"></textarea>
      <div class="add-row">
        <input class="add-tags" type="text" bind:value={addTags} placeholder="Tags (comma-separated)" />
        <select class="add-select" bind:value={addSource}>
          <option value="human">Human</option>
          <option value="agent">Agent</option>
          <option value="auto">Auto</option>
        </select>
        <button class="btn" onclick={addMemory} disabled={adding || !addContent.trim()}>
          {adding ? 'Adding...' : 'Save'}
        </button>
      </div>
    </div>
  {/if}

  {#if injectedPreview}
    <div class="inject-preview">
      <div class="inject-header">
        <span class="section-title">Injected Context Preview</span>
        <button class="close-btn" onclick={() => (injectedPreview = null)}>x</button>
      </div>
      <pre class="inject-text">{injectedPreview}</pre>
    </div>
  {/if}

  {#if error}
    <div class="state-msg error">{error}</div>
  {/if}

  {#if loading}
    <div class="state-msg">Loading memories...</div>
  {:else if memories.length === 0}
    <div class="state-msg">No memories found.</div>
  {:else}
    <div class="memory-list">
      {#each memories as mem (mem.id)}
        <div class="memory-card">
          <div class="card-header">
            <span class="trust-badge" style:background={TRUST_COLORS[mem.trust] ?? 'var(--ctp-overlay0)'}>{mem.source}</span>
            <span class="card-date">{fmtDate(mem.createdAt)}</span>
            {#if confirmDeleteId === mem.id}
              <button class="del-btn confirm" onclick={() => { confirmDeleteId = null; removeMemory(mem.id); }}>Confirm?</button>
              <button class="del-btn" onclick={() => (confirmDeleteId = null)}>Cancel</button>
            {:else}
              <button class="del-btn" onclick={() => (confirmDeleteId = mem.id)}>x</button>
            {/if}
          </div>
          <div class="card-content">
            {#if expandedIds.has(mem.id)}
              {mem.content}
            {:else if mem.content.length > 200}
              {mem.content.slice(0, 200)}...
            {:else}
              {mem.content}
            {/if}
          </div>
          {#if mem.content.length > 200}
            <button class="expand-btn" onclick={() => toggleExpand(mem.id)}>
              {expandedIds.has(mem.id) ? 'Show less' : 'Show more'}
            </button>
          {/if}
          <div class="card-footer">
            <div class="confidence-bar-bg">
              <div class="confidence-bar-fill" style:width="{mem.confidence * 100}%"></div>
            </div>
            {#if mem.tags}
              <div class="card-tags">
                {#each mem.tags.split(',').filter(Boolean).map(t => t.trim()) as tag}
                  <span class="tag">{tag}</span>
                {/each}
              </div>
            {/if}
          </div>
        </div>
      {/each}
    </div>
  {/if}
</div>

<style>
  .memory-root {
    padding: 0.75rem; display: flex; flex-direction: column; gap: 0.5rem;
    color: var(--ctp-text); font-family: var(--ui-font-family, system-ui, sans-serif);
    font-size: var(--ui-font-size, 0.8125rem); overflow-y: auto; height: 100%;
  }
  .toolbar { display: flex; flex-direction: column; gap: 0.375rem; }
  .search-row { display: flex; gap: 0.375rem; }
  .search-input, .add-tags {
    flex: 1; padding: 0.3125rem 0.5rem; border-radius: 0.25rem;
    border: 1px solid var(--ctp-surface1); background: var(--ctp-surface0);
    color: var(--ctp-text); font-size: 0.75rem;
  }
  .search-input:focus, .add-tags:focus, .add-textarea:focus { outline: none; border-color: var(--ctp-blue); }
  .action-row { display: flex; gap: 0.375rem; flex-wrap: wrap; }
  .btn {
    padding: 0.3125rem 0.75rem; border-radius: 0.25rem; border: 1px solid var(--ctp-surface1);
    background: var(--ctp-blue); color: var(--ctp-base); cursor: pointer; font-size: 0.75rem; font-weight: 500;
  }
  .btn:hover { opacity: 0.9; }
  .btn:disabled { opacity: 0.5; cursor: not-allowed; }
  .btn.secondary { background: var(--ctp-surface0); color: var(--ctp-subtext0); }
  .btn.secondary:hover { background: var(--ctp-surface1); color: var(--ctp-text); }
  .add-form {
    display: flex; flex-direction: column; gap: 0.375rem; padding: 0.5rem;
    background: var(--ctp-surface0); border-radius: 0.375rem; border: 1px solid var(--ctp-surface1);
  }
  .add-textarea {
    padding: 0.375rem; border-radius: 0.25rem; border: 1px solid var(--ctp-surface1);
    background: var(--ctp-mantle); color: var(--ctp-text); font-size: 0.75rem; resize: vertical; font-family: inherit;
  }
  .add-row { display: flex; gap: 0.375rem; }
  .add-select {
    padding: 0.25rem 0.375rem; border-radius: 0.25rem;
    border: 1px solid var(--ctp-surface1); background: var(--ctp-mantle); color: var(--ctp-text); font-size: 0.75rem;
  }
  .inject-preview { padding: 0.5rem; background: var(--ctp-surface0); border-radius: 0.375rem; border: 1px solid var(--ctp-teal); }
  .inject-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.375rem; }
  .section-title { font-size: 0.75rem; color: var(--ctp-subtext1); text-transform: uppercase; letter-spacing: 0.04em; }
  .close-btn { background: none; border: none; color: var(--ctp-overlay0); cursor: pointer; font-size: 0.75rem; padding: 0.125rem 0.25rem; }
  .close-btn:hover { color: var(--ctp-text); }
  .inject-text {
    font-family: monospace; font-size: 0.6875rem; color: var(--ctp-subtext0);
    white-space: pre-wrap; word-break: break-word; max-height: 10rem; overflow-y: auto; margin: 0;
  }
  .state-msg { padding: 1.5rem; text-align: center; color: var(--ctp-subtext0); }
  .state-msg.error { color: var(--ctp-red); }
  .memory-list { display: flex; flex-direction: column; gap: 0.375rem; }
  .memory-card {
    padding: 0.5rem 0.625rem; background: var(--ctp-surface0); border-radius: 0.375rem;
    border: 1px solid var(--ctp-surface1); display: flex; flex-direction: column; gap: 0.375rem;
  }
  .memory-card:hover { border-color: var(--ctp-surface2); }
  .card-header { display: flex; align-items: center; gap: 0.375rem; }
  .trust-badge, .tag, .kind-badge {
    padding: 0.0625rem 0.375rem; border-radius: 0.1875rem; font-size: 0.625rem; font-weight: 600;
  }
  .trust-badge { color: var(--ctp-base); text-transform: uppercase; letter-spacing: 0.03em; }
  .card-date { font-size: 0.6875rem; color: var(--ctp-overlay0); margin-left: auto; }
  .del-btn { background: none; border: none; color: var(--ctp-overlay0); cursor: pointer; font-size: 0.75rem; padding: 0 0.25rem; }
  .del-btn:hover { color: var(--ctp-red); }
  .del-btn.confirm { color: var(--ctp-red); font-weight: 600; }
  .expand-btn { background: none; border: none; color: var(--ctp-blue); cursor: pointer; font-size: 0.6875rem; padding: 0; align-self: flex-start; }
  .expand-btn:hover { text-decoration: underline; }
  .card-content { font-size: 0.75rem; color: var(--ctp-subtext1); line-height: 1.4; }
  .card-footer { display: flex; flex-direction: column; gap: 0.25rem; }
  .confidence-bar-bg { height: 0.1875rem; background: var(--ctp-surface1); border-radius: 0.125rem; overflow: hidden; }
  .confidence-bar-fill { height: 100%; background: var(--ctp-teal); border-radius: 0.125rem; }
  .card-tags { display: flex; flex-wrap: wrap; gap: 0.25rem; }
  .tag { background: var(--ctp-surface1); color: var(--ctp-subtext0); font-weight: 400; }
</style>
