<script lang="ts">
    import { fileUrl } from '$lib/api/client';
    import { chapterLabel } from '$lib/api/chapters';
    import { overflowTooltip } from '$lib/actions/overflowTooltip';
    import type { ReadProgressSummary } from '$lib/api/read_progress';
    import IconButton from '$lib/components/IconButton.svelte';
    import BookImage from '@lucide/svelte/icons/book-image';
    import Trash2 from '@lucide/svelte/icons/trash-2';

    // Shared reading-history list, used by both the desktop /profile/history
    // page and the mobile Library "History" tab so the two can't drift in
    // layout, labels, or fallback handling (they previously did). The clear
    // affordance is opt-in: pass `onClear` to enable per-row removal — the
    // component owns the optimistic-removal UX (instant remove, rollback +
    // inline error on failure) so every caller gets identical behavior.
    let {
        entries,
        onClear,
        emptyText = 'Nothing here yet — open any manga and a row will land here once you turn a page.',
        testid = 'history'
    }: {
        entries: ReadProgressSummary[];
        onClear?: (p: ReadProgressSummary) => Promise<void>;
        emptyText?: string;
        testid?: string;
    } = $props();

    // Internal working copy so optimistic removal can mutate without
    // reaching back into the caller's loaded data. Seeded from `entries`;
    // the caller's list is the initial truth, this owns it from then on.
    // svelte-ignore state_referenced_locally
    let rows = $state<ReadProgressSummary[]>([...entries]);
    let clearError = $state<string | null>(null);

    async function clear(p: ReadProgressSummary) {
        if (!onClear) return;
        clearError = null;
        const snapshot = rows;
        rows = rows.filter((x) => x.manga_id !== p.manga_id);
        try {
            await onClear(p);
        } catch (e) {
            // Roll back the optimistic removal and surface inline rather than
            // via alert() — keeps the surface non-modal and unit-testable.
            rows = snapshot;
            clearError = `Couldn't clear "${p.manga_title}": ${(e as Error).message}`;
        }
    }

    function formatDate(iso: string): string {
        return new Date(iso).toLocaleDateString();
    }

    // Built in script rather than inline so the " — page N" suffix keeps its
    // surrounding spaces — Svelte trims whitespace at `{#if}` block edges,
    // which previously rendered "Chapter 3— page 7" with no space.
    function continueLabel(p: ReadProgressSummary): string {
        // Only rendered behind a `chapter_number != null` guard in the
        // template; narrow here so the helper doesn't depend on that.
        const label = p.chapter_number != null ? chapterLabel({ number: p.chapter_number, title: null }) : '';
        const base = `Continue ${label}`;
        return p.page > 1 ? `${base} — page ${p.page}` : base;
    }
</script>

{#if clearError}
    <p class="error" role="alert" data-testid="{testid}-error">
        {clearError}
    </p>
{/if}

{#if rows.length === 0}
    <p class="hint" data-testid="{testid}-empty">{emptyText}</p>
{:else}
    <ul class="entry-list" data-testid="{testid}-list">
        {#each rows as p (p.manga_id)}
            <li class="entry">
                <a
                    href={p.chapter_id != null
                        ? `/manga/${p.manga_id}/chapter/${p.chapter_id}`
                        : `/manga/${p.manga_id}`}
                    class="cover-link"
                    tabindex="-1"
                    aria-hidden="true"
                >
                    {#if p.manga_cover_image_path}
                        <img
                            src={fileUrl(p.manga_cover_image_path)}
                            alt=""
                            class="cover"
                            loading="lazy"
                            decoding="async"
                        />
                    {:else}
                        <div class="cover cover-placeholder">
                            <BookImage size={20} aria-hidden="true" />
                        </div>
                    {/if}
                </a>
                <div class="meta">
                    <a
                        href="/manga/{p.manga_id}"
                        class="title"
                        data-testid="{testid}-title"
                        use:overflowTooltip={p.manga_title}
                    >
                        {p.manga_title}
                    </a>
                    <span class="target">
                        {#if p.chapter_id != null && p.chapter_number != null}
                            <a href="/manga/{p.manga_id}/chapter/{p.chapter_id}">
                                {continueLabel(p)}
                            </a>
                        {:else if p.chapter_id}
                            <span class="muted">(chapter removed)</span>
                        {:else}
                            <span class="muted">Whole manga, page {p.page}</span>
                        {/if}
                    </span>
                    <span class="when">Read {formatDate(p.updated_at)}</span>
                </div>
                {#if onClear}
                    <IconButton
                        variant="danger"
                        onclick={() => clear(p)}
                        aria-label={`Clear ${p.manga_title} from history`}
                        title="Clear from history"
                        data-testid="{testid}-clear-{p.manga_id}"
                    >
                        <Trash2 size={16} aria-hidden="true" />
                    </IconButton>
                {/if}
            </li>
        {/each}
    </ul>
{/if}

<style>
    .entry-list {
        list-style: none;
        padding: 0;
        margin: 0;
    }

    .entry {
        display: grid;
        grid-template-columns: 56px 1fr auto;
        gap: var(--space-3);
        align-items: center;
        padding: var(--space-2) 0;
        border-bottom: 1px solid var(--border);
    }

    .cover-link {
        display: block;
        line-height: 0;
    }

    .cover {
        width: 56px;
        height: 84px;
        object-fit: cover;
        border-radius: var(--radius-sm);
        background: var(--surface);
    }

    .cover-placeholder {
        display: flex;
        align-items: center;
        justify-content: center;
        color: var(--text-muted);
    }

    .meta {
        display: flex;
        flex-direction: column;
        gap: var(--space-1);
        min-width: 0;
    }

    .title {
        font-weight: var(--weight-semibold);
        color: var(--text);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .title:hover {
        color: var(--primary);
    }

    .target {
        font-size: var(--font-sm);
    }

    .muted {
        color: var(--text-muted);
    }

    .when {
        color: var(--text-muted);
        font-size: var(--font-xs);
    }

    .hint {
        color: var(--text-muted);
    }

    .error {
        color: var(--danger);
        background: var(--danger-soft-bg);
        border: 1px solid var(--danger);
        border-radius: var(--radius-md);
        padding: var(--space-2) var(--space-3);
        margin: 0 0 var(--space-2);
    }
</style>
