<script lang="ts">
    import { fileUrl } from '$lib/api/client';
    import type { TaggedMangaAggregate } from '$lib/api/page_tags';

    /**
     * Single row in the /search Mangas tab. Renders the manga cover,
     * title, the cross-chapter match-count pill, and a thumbnail
     * strip of matching pages. Clicking the row lands on the manga
     * detail page.
     *
     * Cover precedence: `manga_cover_image_path` if the manga has
     * one, else the first sample page. Mangas without uploaded
     * covers (rare during dev / bots) still get a recognisable thumb.
     */
    let {
        item,
        testid
    }: {
        item: TaggedMangaAggregate;
        testid?: string;
    } = $props();

    const href = $derived(`/manga/${item.manga_id}`);
    const primaryCover = $derived(
        item.manga_cover_image_path ?? item.sample_storage_keys[0] ?? null
    );
    /** Sample strip skips the slot already used as the primary cover
     *  to avoid showing the same thumbnail twice. */
    const sampleStrip = $derived(
        item.manga_cover_image_path != null
            ? item.sample_storage_keys
            : item.sample_storage_keys.slice(1)
    );
</script>

<li class="row" data-testid={testid}>
    <a {href} class="cover-link" aria-hidden="true" tabindex="-1">
        {#if primaryCover}
            <img src={fileUrl(primaryCover)} alt="" class="cover" loading="lazy" decoding="async" />
        {:else}
            <div class="cover cover-placeholder"></div>
        {/if}
    </a>
    <div class="meta">
        <a class="title" {href}>{item.manga_title}</a>
        <span class="match-count">
            {item.match_count}
            {item.match_count === 1 ? 'page' : 'pages'}
        </span>
        {#if sampleStrip.length > 0}
            <div class="samples">
                {#each sampleStrip as key (key)}
                    <img src={fileUrl(key)} alt="" class="sample" loading="lazy" decoding="async" />
                {/each}
            </div>
        {/if}
    </div>
</li>

<style>
    .row {
        display: grid;
        grid-template-columns: 56px 1fr;
        gap: var(--space-3);
        align-items: start;
    }

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

    .cover {
        width: 56px;
        aspect-ratio: 2 / 3;
        object-fit: cover;
        border-radius: var(--radius-sm);
        background: var(--surface);
    }

    .cover-placeholder {
        background: var(--surface-elevated);
    }

    .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);
        text-decoration: none;
    }

    .match-count {
        align-self: flex-start;
        background: var(--primary-soft-bg);
        color: var(--primary);
        font-size: var(--font-xs);
        padding: 2px var(--space-2);
        border-radius: var(--radius-pill);
    }

    .samples {
        display: flex;
        gap: var(--space-1);
        margin-top: var(--space-1);
    }

    .sample {
        width: 40px;
        aspect-ratio: 2 / 3;
        object-fit: cover;
        border-radius: var(--radius-sm);
        background: var(--surface);
    }
</style>
