<section
    class="rails-page"
    [class.rails-page--empty]="ready() && !hasPlaylists()"
    data-test-id="dashboard-page"
>
    @if (data.playlistsLoaded() && !hasPlaylists()) {
        <app-empty-state
            [type]="'welcome-dashboard'"
            [showElectronOnlyValueProps]="isElectron"
            (addPlaylistClicked)="onAddPlaylist($event)"
        />
    } @else {
        <!-- Hero: real card if a recent item resolved, skeleton while still
             loading the first global recent item, nothing if no recent items
             exist. Each block below renders as soon as ITS data is ready —
             no longer pinned on the slowest rail's I/O. -->
        @if (hero(); as item) {
            <a
                class="hero"
                data-test-id="dashboard-hero"
                [class.hero--with-image]="
                    !!item.posterUrl || !!item.backdropUrl
                "
                [class.hero--has-backdrop]="item.hasBackdrop"
                [class.hero--has-default-backdrop]="
                    item.backdropSource === 'fallback'
                "
                [class.hero--live]="item.contentType === 'live'"
                [routerLink]="item.link"
                [state]="item.state ?? {}"
            >
                <span
                    class="hero__backdrop"
                    aria-hidden="true"
                    [style.backgroundImage]="
                        item.backdropUrl
                            ? 'url(' + item.backdropUrl + ')'
                            : item.fallbackBackdropBackground
                    "
                ></span>
                @if (item.backdropUrl; as backdropUrl) {
                    <img
                        class="hero__image-probe"
                        [src]="backdropUrl"
                        alt=""
                        aria-hidden="true"
                        loading="eager"
                        decoding="async"
                        (error)="markHeroImageFailed(backdropUrl)"
                    />
                }
                <span class="hero__vignette" aria-hidden="true"></span>

                <span class="hero__poster">
                    @if (item.posterUrl; as posterUrl) {
                        <img
                            [src]="posterUrl"
                            [alt]="item.title"
                            loading="eager"
                            decoding="async"
                            (error)="markHeroImageFailed(posterUrl)"
                        />
                    } @else {
                        <span
                            class="hero__poster-fallback"
                            [style.backgroundImage]="
                                item.fallbackPosterBackground
                            "
                        >
                            <mat-icon>{{ item.icon }}</mat-icon>
                        </span>
                    }
                </span>

                <span class="hero__body">
                    <h1 class="hero__title">{{ item.title }}</h1>
                    <p class="hero__subtitle">{{ item.subtitle }}</p>

                    @if (item.watchProgress !== null && item.watchProgress !== undefined) {
                        <span class="hero__progress" aria-hidden="true">
                            <span
                                class="hero__progress-bar"
                                [style.width.%]="item.watchProgress"
                            ></span>
                        </span>
                        <span class="hero__progress-meta">
                            @if (item.remainingLabel) {
                                <span>{{
                                    item.remainingLabel.key
                                        | translate: item.remainingLabel.params
                                }}</span>
                                <span class="hero__progress-meta-sep"
                                    >·</span
                                >
                            }
                            <span>{{
                                'WORKSPACE.DASHBOARD.PERCENT_WATCHED'
                                    | translate: { value: item.watchProgress }
                            }}</span>
                        </span>
                    }

                    <span class="hero__cta">
                        <mat-icon>play_arrow</mat-icon>
                        <span>{{
                            'WORKSPACE.DASHBOARD.CONTINUE_WATCHING' | translate
                        }}</span>
                    </span>
                </span>
            </a>
        } @else if (data.globalRecentLoading()) {
            <section
                class="rails-page__skeleton-hero"
                aria-hidden="true"
                aria-busy="true"
            >
                <div class="rails-page__skeleton-hero-poster"></div>
                <div class="rails-page__skeleton-hero-body">
                    <div class="rails-page__skeleton-hero-title"></div>
                    <div
                        class="rails-page__skeleton-hero-title rails-page__skeleton-hero-title--short"
                    ></div>
                    <div class="rails-page__skeleton-hero-subtitle"></div>
                    <div class="rails-page__skeleton-hero-cta"></div>
                </div>
            </section>
        }

        <!-- Continue watching (movies + series) -->
        @if (continueWatchingCards().length > 0) {
            <lib-dashboard-rail
                [label]="'WORKSPACE.DASHBOARD.CONTINUE_WATCHING' | translate"
                [items]="continueWatchingCards()"
                [totalCount]="data.globalRecentVodItems().length"
                [seeAllLink]="['/workspace/global-recent']"
                [testId]="'dashboard-continue-watching-rail'"
            />
        }

        <!-- Live rail — favorited live channels first, falls back to
             recently-watched live. Title flips based on source so the label
             is always honest about what's rendered. -->
        @if (liveOnFavoritesCardsEnriched().length > 0) {
            <lib-dashboard-rail
                [label]="liveRailTitleKey() | translate"
                [items]="liveOnFavoritesCardsEnriched()"
                [totalCount]="liveRailTotalCount()"
                [seeAllLink]="
                    liveRailSource() === 'favorites'
                        ? ['/workspace/global-favorites']
                        : ['/workspace/global-recent']
                "
                layout="channel"
                [testId]="'dashboard-live-recent-rail'"
            />
        }

        @if (
            continueWatchingCards().length === 0 &&
            liveOnFavoritesCards().length === 0 &&
            data.globalRecentLoading()
        ) {
            <section
                class="rails-page__skeleton-rail"
                aria-hidden="true"
                aria-busy="true"
            >
                <div class="rails-page__skeleton-header"></div>
                <div class="rails-page__skeleton-track">
                    @for (slot of skeletonSlots; track slot) {
                        <div class="rails-page__skeleton-card"></div>
                    }
                </div>
            </section>
        }

        <!-- Mixed Global Favorites rail intentionally NOT rendered on the
             dashboard. Live favorites are promoted into the live rail above
             (with current EPG), and the full mixed catalogue lives on the
             dedicated /workspace/global-favorites page where the collection
             UI can give it the per-type filters it needs. -->

        <!-- Sources rail -->
        @if (sourceCards().length > 0) {
            <lib-dashboard-rail
                [label]="'WORKSPACE.DASHBOARD.RECENT_SOURCES' | translate"
                [items]="sourceCards()"
                [totalCount]="data.playlists().length"
                [seeAllLink]="['/workspace/sources']"
                aspectRatio="16 / 9"
                [testId]="'dashboard-recent-sources-rail'"
                (actionSelected)="onSourceActionSelected($event)"
            />
        } @else if (!data.playlistsLoaded()) {
            <section
                class="rails-page__skeleton-rail"
                aria-hidden="true"
                aria-busy="true"
            >
                <div class="rails-page__skeleton-header"></div>
                <div class="rails-page__skeleton-track">
                    @for (slot of skeletonSlots; track slot) {
                        <div class="rails-page__skeleton-card"></div>
                    }
                </div>
            </section>
        }

        <!-- Xtream recently-added rail (only relevant if there are Xtream playlists) -->
        @if (xtreamRecentlyAddedCards().length > 0) {
            <lib-dashboard-rail
                [label]="
                    'WORKSPACE.DASHBOARD.XTREAM_RECENTLY_ADDED' | translate
                "
                [items]="xtreamRecentlyAddedCards()"
                [totalCount]="data.xtreamRecentlyAddedItems().length"
                [testId]="'dashboard-xtream-recently-added-rail'"
            />
        } @else if (
            xtreamPlaylistCount() > 0 && data.xtreamRecentlyAddedLoading()
        ) {
            <section
                class="rails-page__skeleton-rail"
                aria-hidden="true"
                aria-busy="true"
            >
                <div class="rails-page__skeleton-header"></div>
                <div class="rails-page__skeleton-track">
                    @for (slot of skeletonSlots; track slot) {
                        <div class="rails-page__skeleton-card"></div>
                    }
                </div>
            </section>
        }
    }
</section>
