<script lang="ts">
  import type { HistoryEntry } from "../state/history.svelte.ts";

  type Props = {
    entries: HistoryEntry[];
    notice?: string | null;
    onClear: () => void;
    onDismissNotice?: () => void;
    onExport?: () => void;
    onFavorite: (id: string) => void;
    onImport?: (file: File) => void;
    onLoad: (id: string, inNewTab: boolean) => void;
    onRemove: (id: string) => void;
  };

  let {
    entries,
    notice = null,
    onClear,
    onDismissNotice,
    onExport,
    onFavorite,
    onImport,
    onLoad,
    onRemove
  }: Props = $props();

  let fileInput = $state<HTMLInputElement | null>(null);

  const sorted = $derived([...entries].sort((a, b) => {
    if (a.favorite !== b.favorite)
      return a.favorite ? -1 : 1;

    return b.timestamp - a.timestamp;
  }));

  function formatTimestamp(ms: number): string {
    const d = new Date(ms);
    return d.toLocaleString();
  }

  function onEntryClick(event: MouseEvent, id: string) {
    onLoad(id, event.shiftKey);
  }

  function onEntryKey(event: KeyboardEvent, id: string) {
    if (event.key === "Enter" || event.key === " ") {
      event.preventDefault();
      onLoad(id, event.shiftKey);
    }
  }

  function onImportClick() {
    fileInput?.click();
  }

  function onFileChange(event: Event) {
    const input = event.currentTarget as HTMLInputElement;
    const file = input.files?.[0];

    if (file)
      onImport?.(file);

    input.value = "";
  }
</script>

<style lang="scss">
  .panel {
    background: var(--graphiql-panel, #252526);
    border-right: 1px solid var(--graphiql-border, #333);
    display: grid;
    grid-template-rows: auto 1fr;
    height: 100%;
    min-height: 0;
    overflow: hidden;
  }

  .header {
    align-items: center;
    border-bottom: 1px solid var(--graphiql-border, #333);
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    padding: 0.5rem 0.75rem;
  }

  .title {
    font-size: 0.8125rem;
    font-weight: 600;
  }

  .actions {
    display: flex;
    gap: 0.5rem;
  }

  .action {
    background: none;
    border: none;
    color: var(--graphiql-muted, #858585);
    cursor: pointer;
    font-family: inherit;
    font-size: 0.75rem;
    padding: 0;

    &:hover {
      color: var(--graphiql-fg, #d4d4d4);
    }
  }

  .hidden-input {
    display: none;
  }

  .notice {
    align-items: center;
    background: var(--graphiql-bg, #1e1e1e);
    border-bottom: 1px solid var(--graphiql-border, #333);
    color: var(--graphiql-fg, #d4d4d4);
    display: flex;
    font-size: 0.75rem;
    gap: 0.5rem;
    justify-content: space-between;
    padding: 0.375rem 0.75rem;
  }

  .notice-dismiss {
    background: none;
    border: none;
    color: var(--graphiql-muted, #858585);
    cursor: pointer;
    font-size: 0.875rem;
    line-height: 1;
    padding: 0 0.25rem;

    &:hover {
      color: var(--graphiql-fg, #d4d4d4);
    }
  }

  .list {
    display: grid;
    gap: 0.125rem;
    min-height: 0;
    overflow-y: auto;
    padding: 0.375rem 0;
  }

  .entry {
    align-items: flex-start;
    cursor: pointer;
    display: grid;
    gap: 0.125rem;
    grid-template-columns: auto 1fr auto;
    padding: 0.375rem 0.75rem;

    &:hover {
      background: var(--graphiql-bg, #1e1e1e);
    }
  }

  .star {
    background: none;
    border: none;
    color: var(--graphiql-muted, #858585);
    cursor: pointer;
    font-size: 0.875rem;
    padding: 0 0.375rem 0 0;

    &.active {
      color: var(--graphiql-accent, #e3b341);
    }
  }

  .meta {
    align-self: center;
    min-width: 0;
  }

  .entry-title {
    font-size: 0.8125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .entry-time {
    color: var(--graphiql-muted, #858585);
    font-size: 0.7rem;
  }

  .remove {
    align-self: center;
    background: none;
    border: none;
    color: var(--graphiql-muted, #858585);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 0 0.25rem;

    &:hover {
      color: var(--graphiql-fg, #d4d4d4);
    }
  }

  .empty {
    color: var(--graphiql-muted, #858585);
    font-size: 0.8125rem;
    padding: 0.75rem;
  }
</style>

<div class="panel">
  <div>
    <div class="header">
      <span class="title">History</span>
      <div class="actions">
        {#if onExport}
          <button class="action" onclick={onExport} type="button">Export</button>
        {/if}
        {#if onImport}
          <button class="action" onclick={onImportClick} type="button">Import</button>
          <input
            accept="application/json"
            bind:this={fileInput}
            class="hidden-input"
            onchange={onFileChange}
            type="file"/>
        {/if}
        {#if entries.length > 0}
          <button class="action" onclick={onClear} type="button">Clear</button>
        {/if}
      </div>
    </div>
    {#if notice}
      <div class="notice">
        <span>{notice}</span>
        {#if onDismissNotice}
          <button
            aria-label="Dismiss notice"
            class="notice-dismiss"
            onclick={onDismissNotice}
            type="button">×</button>
        {/if}
      </div>
    {/if}
  </div>
  <div class="list">
    {#if sorted.length === 0}
      <div class="empty">No history yet.</div>
    {:else}
      {#each sorted as entry (entry.id)}
        <div
          aria-label="Load history entry"
          class="entry"
          onclick={(e) => onEntryClick(e, entry.id)}
          onkeydown={(e) => onEntryKey(e, entry.id)}
          role="button"
          tabindex="0">
          <button
            aria-label={entry.favorite ? "Unfavorite" : "Favorite"}
            class="star"
            class:active={entry.favorite}
            onclick={(e) => { e.stopPropagation(); onFavorite(entry.id); }}
            type="button">{entry.favorite ? "★" : "☆"}</button>
          <div class="meta">
            <div class="entry-title">{entry.title}</div>
            <div class="entry-time">{formatTimestamp(entry.timestamp)}</div>
          </div>
          <button
            aria-label="Remove entry"
            class="remove"
            onclick={(e) => { e.stopPropagation(); onRemove(entry.id); }}
            type="button">×</button>
        </div>
      {/each}
    {/if}
  </div>
</div>
