Source: display.js

/**
 * js/display.js
 * Handles the display and rendering of media items, hero section, details overlay, collections, and notifications.
 * @module display
 */

import { playVideo, getFilmWatchData, getEpisodeWatchData, isSeriesFullyWatched } from './utils.js';

let activeDetailItem = null;
let activeVideoSrc = "";
let activeVideoContext = null;

/**
 * Sets up the hero section with the given media item.
 * @param {Object} item - The media item to display in the hero section.
 */
export function setupHero(item) {
    if (!item) return;

    const isSerie = item.type === 'serie' || item.seasons !== undefined;

    document.getElementById('heroImage').src = item.banner || item.poster;
    document.getElementById('heroTitle').innerText = item.title;
    document.getElementById('heroDesc').innerText = item.description;
    document.getElementById('heroRating').innerText = item.IMDb;
    document.getElementById('heroYear').innerText = item.year;
    document.getElementById('heroType').innerText = isSerie ? 'Série' : 'Film';

    let durationText = item.duration || "2h 15min";
    if (isSerie && item.seasons) {
        const nbSeasons = Object.keys(item.seasons).length;
        durationText = nbSeasons + (nbSeasons > 1 ? " Saisons" : " Saison");
    }
    document.getElementById('heroDuration').innerText = durationText;
    document.getElementById('heroGenre').innerText = item.genres?.[0] || "";

    const heroBtn = document.getElementById('heroPlayBtn');
    const newBtn = heroBtn.cloneNode(true);
    heroBtn.parentNode.replaceChild(newBtn, heroBtn);

    newBtn.onclick = () => {
        openDetails(item);
        if (isSerie && item.seasons?.["1"]?.[0]) {
            const ctx = { 
                type: 'series', 
                title: item.title, 
                season: '1', 
                episodeIndex: 0,
                episodeTitle: item.seasons["1"][0].title || 'Épisode 1'
            };
            activeVideoContext = ctx;
            activeVideoSrc = item.seasons["1"][0].video;
            playVideo(activeVideoSrc, ctx);
        } else if (item.video) {
            const ctx = { type: 'film', title: item.title };
            activeVideoContext = ctx;
            activeVideoSrc = item.video;
            playVideo(item.video, ctx);
        }
    };

    const infoBtn = document.getElementById('heroInfoBtn');
    if (infoBtn) {
        const newInfoBtn = infoBtn.cloneNode(true);
        infoBtn.parentNode.replaceChild(newInfoBtn, infoBtn);
        newInfoBtn.onclick = () => openDetails(item);
    }
}

/**
 * Opens the details overlay for a given media item.
 * @param {Object} item - The media item to display details for.
 */
export function openDetails(item) {
    activeDetailItem = item;
    const overlay = document.getElementById('detailsOverlay');
    const isSerie = item.type === 'serie' || item.seasons !== undefined;
    const playBtn = document.getElementById('detailPlayBtn');

    document.getElementById('detailHeroImg').src = item.banner || item.poster;
    document.getElementById('detailTitle').innerText = item.title;
    document.getElementById('detailDesc').innerText = item.description;
    document.getElementById('detailYear').innerText = item.year;

    const matchScore = item.IMDb ? Math.round(item.IMDb * 10) : 90;
    document.getElementById('detailMatch').innerText = `Recommandé à ${matchScore}%`;

    let durationText = item.duration || "2h 15min";
    if (isSerie && item.seasons) {
        const nbSeasons = Object.keys(item.seasons).length;
        durationText = nbSeasons + (nbSeasons > 1 ? " Saisons" : " Saison");
    }
    document.getElementById('detailDuration').innerText = durationText;

    document.getElementById('detailGenrePills').innerHTML = item.genres?.map(g => `<span class="text-gray-300 text-sm font-medium px-3 py-1 rounded-full bg-white/5 border border-white/10">${g}</span>`).join('') || "";
    document.getElementById('detailCast').innerHTML = item.stars?.map(s => `<span class="bg-red-600/10 text-red-300 px-4 py-2 rounded-full text-sm font-bold">${s}</span>`).join('') || "Non renseigné";
    document.getElementById('detailCreators').innerText = (item.directors || item.creators || []).join(", ") || "Non renseigné";

    const seriesSec = document.getElementById('seriesSection');
    const seasonSelect = document.getElementById('seasonSelect');

    if (isSerie) {
        seriesSec.classList.remove('hidden');
        activeVideoSrc = "";
        activeVideoContext = null;

        seasonSelect.innerHTML = '';
        const seasons = item.seasons || {};
        const seasonKeys = Object.keys(seasons).sort((a, b) => parseInt(a) - parseInt(b));

        if (seasonKeys.length > 0) {
            seasonKeys.forEach(key => {
                const opt = document.createElement('option');
                opt.value = key;
                opt.innerText = `Saison ${key}`;
                seasonSelect.appendChild(opt);
            });
            renderEpisodes(seasons[seasonKeys[0]], seasonKeys[0]);

            seasonSelect.onchange = (e) => {
                const rawValue = e.target && typeof e.target.value === 'string' ? e.target.value : null;
                const selectedKey = rawValue && Object.prototype.hasOwnProperty.call(seasons, rawValue)
                    ? rawValue
                    : null;
                const selectedSeason = selectedKey ? seasons[selectedKey] : null;
                if (selectedSeason) {
                    const safeSeasonId = String(selectedKey);
                    renderEpisodes(selectedSeason, safeSeasonId);
                }
            };
        } else {
            const opt = document.createElement('option');
            opt.innerText = "Saison 1";
            seasonSelect.appendChild(opt);
            renderEpisodes([], 1);
        }
    } else {
        seriesSec.classList.add('hidden');
        activeVideoSrc = item.video;
        activeVideoContext = item.video ? { type: 'film', title: item.title } : null;
    }

    if (playBtn) {
        const hasVideo = activeVideoSrc && activeVideoSrc.trim() !== '';
        playBtn.disabled = !hasVideo;
        if (hasVideo) {
            playBtn.classList.remove('opacity-50', 'cursor-not-allowed');
        } else {
            playBtn.classList.add('opacity-50', 'cursor-not-allowed');
        }
    }

    overlay.classList.remove('hidden');
    document.body.style.overflow = 'hidden';
}

/**
 * Closes the details overlay.
 */
export function closeDetails() {
    document.getElementById('detailsOverlay').classList.add('hidden');
    document.body.style.overflow = '';
}

/**
 * Plays the currently selected media in the details overlay.
 */
export function playCurrentMedia() {
    if (!activeVideoSrc && activeDetailItem && activeDetailItem.seasons) {
        // fallback: select first episode if none chosen yet
        const firstSeasonKey = Object.keys(activeDetailItem.seasons || {})[0];
        const firstEpisode = firstSeasonKey ? activeDetailItem.seasons[firstSeasonKey]?.[0] : null;
        if (firstEpisode) {
            activeVideoSrc = firstEpisode.video;
            activeVideoContext = { 
                type: 'series', 
                title: activeDetailItem.title, 
                season: firstSeasonKey, 
                episodeIndex: 0,
                episodeTitle: firstEpisode.title || 'Épisode 1'
            };
        }
    }

    if (activeVideoSrc) {
        playVideo(activeVideoSrc, activeVideoContext);
    } else {
        alert("Vidéo non disponible");
    }
}

/**
 * Renders the list of episodes for a given season.
 * @param {Array} episodes - The list of episodes to render.
 * @param {number|string} seasonNum - The season number.
 */
function renderEpisodes(episodes, seasonNum) {
    const list = document.getElementById('episodesList');
    list.innerHTML = '';

    if (!episodes || episodes.length === 0) {
        episodes = [
            { title: "Épisode 1", desc: "Description indisponible.", duration: "45m", video: "" },
            { title: "Épisode 2", desc: "Description indisponible.", duration: "42m", video: "" }
        ];
    }

    const safeSeasonNum = typeof seasonNum === 'string'
        ? seasonNum.replace(/[^0-9]/g, '') || '1'
        : String(Number.isFinite(seasonNum) ? seasonNum : 1);

    if (episodes.length > 0) {
        activeVideoSrc = episodes[0].video;
        activeVideoContext = {
            type: 'series',
            title: activeDetailItem?.title || '',
            season: safeSeasonNum,
            episodeIndex: 0,
            episodeTitle: episodes[0].title || 'Épisode 1',
        };
    }

    const playBtn = document.getElementById('detailPlayBtn');
    if (playBtn) {
        const hasVideo = activeVideoSrc && activeVideoSrc.trim() !== '';
        playBtn.disabled = !hasVideo;
        if (hasVideo) {
            playBtn.classList.remove('opacity-50', 'cursor-not-allowed');
        } else {
            playBtn.classList.add('opacity-50', 'cursor-not-allowed');
        }
    }

    episodes.forEach((ep, idx) => {
        const watchData = getEpisodeWatchData(activeDetailItem?.title, safeSeasonNum, idx);
        const isWatched = watchData.watched;
        const hasProgress = !isWatched && watchData.time > 0;

        const row = document.createElement('div');
        row.className = "episode-item flex flex-col md:flex-row items-center gap-6 p-4 rounded-2xl cursor-pointer transition-all border border-transparent hover:border-white/5 hover:bg-white/[0.02] group bg-[#0a0a0a]";
        if (isWatched) row.classList.add('episode-watched');

        const fallbackThumb = `https://placehold.co/300x200/333/666?text=S${safeSeasonNum}-EP${idx + 1}`;
        const thumbUrl = activeDetailItem ? activeDetailItem.poster : fallbackThumb;

        const leftContainer = document.createElement('div');
        leftContainer.className = "flex items-center gap-6 w-full md:w-auto";

        const indexSpan = document.createElement('span');
        indexSpan.className = "text-2xl font-black text-gray-600 group-hover:text-red-500 transition-colors w-8 text-center";
        indexSpan.textContent = String(idx + 1);
        leftContainer.appendChild(indexSpan);

        const thumbContainer = document.createElement('div');
        thumbContainer.className = "relative w-40 h-24 flex-shrink-0 bg-gray-900 rounded-lg overflow-hidden shadow-lg";

        const img = document.createElement('img');
        img.src = thumbUrl;
        img.className = "w-full h-full object-cover opacity-70 group-hover:opacity-100 transition-all duration-500 scale-100 group-hover:scale-110";
        img.onerror = function () {
            this.src = fallbackThumb;
        };
        img.alt = `Thumbnail for ${ep.title}`;
        thumbContainer.appendChild(img);

        const overlay = document.createElement('div');
        overlay.className = "absolute inset-0 flex items-center justify-center bg-black/20 group-hover:bg-black/40 transition-colors";

        const playIcon = document.createElement('i');
        playIcon.className = "fas fa-play text-white text-xl opacity-0 group-hover:opacity-100 transition-all";
        overlay.appendChild(playIcon);

        thumbContainer.appendChild(overlay);
        leftContainer.appendChild(thumbContainer);

        const rightContainer = document.createElement('div');
        rightContainer.className = "flex-1 w-full text-center md:text-left overflow-hidden";

        const titleRow = document.createElement('div');
        titleRow.className = "flex flex-col md:flex-row md:items-center justify-between gap-2 mb-2";

        const titleEl = document.createElement('h4');
        titleEl.className = "font-bold text-white text-xl truncate group-hover:text-red-400 transition-colors";
        titleEl.textContent = ep.title;

        const durationEl = document.createElement('span');
        durationEl.className = "text-sm font-bold text-gray-400 bg-black/30 px-2 py-1 rounded-md";
        durationEl.textContent = ep.duration || '45m';

        const metaRow = document.createElement('div');
        metaRow.className = "flex items-center gap-2 flex-wrap justify-center md:justify-end";
        metaRow.appendChild(durationEl);

        if (isWatched) {
            const watchedBadge = document.createElement('span');
            watchedBadge.className = "watched-pill";
            watchedBadge.innerHTML = '<i class="fas fa-eye text-xs"></i> Vu';
            metaRow.appendChild(watchedBadge);
        } else if (hasProgress) {
            const resumeBadge = document.createElement('span');
            resumeBadge.className = "resume-pill";
            resumeBadge.textContent = "Reprendre";
            metaRow.appendChild(resumeBadge);
        }

        titleRow.appendChild(titleEl);
        titleRow.appendChild(metaRow);

        const descEl = document.createElement('p');
        descEl.className = "text-gray-400 text-sm leading-relaxed line-clamp-2";
        descEl.textContent = ep.desc || "...";

        rightContainer.appendChild(titleRow);
        rightContainer.appendChild(descEl);

        row.appendChild(leftContainer);
        row.appendChild(rightContainer);

        row.onclick = (e) => {
            e.stopPropagation();
            const ctx = {
                type: 'series',
                title: activeDetailItem?.title || '',
                season: safeSeasonNum,
                episodeIndex: idx,
                episodeTitle: ep.title || `Épisode ${idx + 1}`,
            };
            activeVideoSrc = ep.video;
            activeVideoContext = ctx;
            playVideo(ep.video, ctx);
        };
        list.appendChild(row);
    });
}

/**
 * Creates a media card element for a given media item.
 * @param {Object} item - The media item to create a card for.
 * @param {string} [extraClasses=""] - Additional CSS classes to apply to the card.
 * @returns {HTMLElement} The created media card element.
 */
export function createMediaCard(item, extraClasses = "") {
    const card = document.createElement('div');
    card.className = `media-card group relative rounded-xl overflow-hidden cursor-pointer bg-[#1a1a1a] shadow-lg transition-all duration-300 ${extraClasses}`;

    const fallback = `https://placehold.co/400x600/1a1a1a/e50914?text=${encodeURIComponent(item.title)}`;

    const isSerie = item.type === 'serie' || item.seasons !== undefined;
    const filmWatch = !isSerie ? getFilmWatchData(item.title) : null;

    let watched = false;
    let hasResume = false;

    if (isSerie) {
        watched = isSeriesFullyWatched(item);
        if (!watched && item.seasons) {
            const seasonKeys = Object.keys(item.seasons).sort((a, b) => parseInt(a) - parseInt(b));
            for (const sKey of seasonKeys) {
                const episodes = item.seasons[sKey] || [];
                for (let i = 0; i < episodes.length; i++) {
                    const w = getEpisodeWatchData(item.title, sKey, i);
                    if (w.time > 0 && !w.watched) {
                        hasResume = true;
                        break;
                    }
                }
                if (hasResume) break;
            }
        }
    } else {
        watched = filmWatch?.watched || false;
        hasResume = !watched && filmWatch && (filmWatch.time || 0) > 0;
    }

    const watchedBadge = watched ? '<span class="watched-pill"><i class="fas fa-eye text-xs"></i> Vu</span>' : '';
    const resumeBadge = !watched && hasResume ? '<span class="resume-pill">Reprendre</span>' : '';
    const badgeStack = watchedBadge || resumeBadge ? `<div class="status-badges">${watchedBadge}${resumeBadge}</div>` : '';

    card.innerHTML = `
        ${badgeStack}
        <img src="${item.poster}" alt="Poster for ${item.title}" onerror="this.src='${fallback}'" class="w-full h-full object-cover object-center transition-transform duration-700 loading='lazy'">
        <div class="absolute inset-x-0 bottom-0 p-4 z-20 bg-gradient-to-t from-black/90 via-black/50 to-transparent translate-y-2 group-hover:translate-y-0 transition-transform duration-300">
            <h3 class="font-bold text-white text-base md:text-lg leading-tight mb-1 drop-shadow-md line-clamp-1">${item.title}</h3>
            <div class="flex items-center gap-3 text-xs font-bold text-gray-300 opacity-0 group-hover:opacity-100 transition-opacity delay-100">
                <span class="text-green-400"><i class="fas fa-star text-[10px]"></i> ${item.IMDb}</span>
                <span>${item.year}</span>
            </div>
        </div>
    `;
    card.onclick = () => openDetails(item);
    return card;
}

/**
 * Renders a grid of media items.
 * @param {Array} items - The list of media items to render.
 */
export function renderGrid(items) {
    const grid = document.getElementById('contentGrid');
    grid.innerHTML = '';
    items.forEach(item => grid.appendChild(createMediaCard(item, "aspect-[2/3]")));
}

/**
 * Renders a horizontal row of media items.
 * @param {string} containerId - The ID of the container element.
 * @param {Array} items - The list of media items to render.
 */
export function renderHorizontalRow(containerId, items) {
    const container = document.getElementById(containerId);
    container.innerHTML = '';
    container.classList.add("scroll-row");
    if (items.length === 0) return;
    items.forEach(item => {
        const card = createMediaCard(item, "min-w-[200px] md:min-w-[280px] aspect-[2/3] snap-start");
        container.appendChild(card);
    });
}

/**
 * Renders collections of media items.
 * @param {Object} collectionsData - The collections data.
 * @param {Object} appData - The application data containing films and series.
 */
export function renderCollections(collectionsData, appData) {
    const container = document.getElementById('collectionsContent');
    container.innerHTML = '';

    if (Object.keys(collectionsData).length === 0) {
        container.innerHTML = '<div class="text-center text-gray-500 py-10">Aucune collection disponible.</div>';
        return;
    }

    const sortedCollections = Object.entries(collectionsData).sort(([, a], [, b]) => {
        return a.name.localeCompare(b.name);
    });

    for (const [key, collection] of sortedCollections) {
        const items = [];
        
        if (collection.films && Array.isArray(collection.films)) {
            collection.films.forEach(title => {
                const foundFilm = Object.values(appData.films).find(f => f.title === title);
                if (foundFilm) items.push(foundFilm);
            });
        }

        if (collection.series && Array.isArray(collection.series)) {
            collection.series.forEach(title => {
                const foundSerie = Object.values(appData.series).find(s => s.title === title);
                if (foundSerie) items.push(foundSerie);
            });
        }

        if (items.length > 0) {
            items.sort((a, b) => a.year - b.year);

            const section = document.createElement('section');
            section.className = "animate-fade-in-up";
            
            const titleHTML = `
                <h2 class="text-2xl font-bold mb-6 flex items-center gap-3">
                    <span class="w-1.5 h-8 bg-red-600 rounded-full shadow-[0_0_15px_#dc2626]"></span>
                    <span class="tracking-tight">${collection.name}</span>
                </h2>
            `;
            section.innerHTML = titleHTML;

            const rowDiv = document.createElement('div');
            rowDiv.className = "scroll-row flex gap-6 overflow-x-auto pb-8 hide-scrollbar scroll-smooth snap-x pl-1";
            
            items.forEach(item => {
                const card = createMediaCard(item, "min-w-[200px] md:min-w-[280px] aspect-[2/3] snap-start");
                rowDiv.appendChild(card);
            });

            section.appendChild(rowDiv);
            container.appendChild(section);
        }
    }
}

/**
 * Renders the list of notifications.
 * @param {Array} list - The list of notifications to render.
 */
export function renderNotifs(list) {
    const container = document.getElementById('notifList');
    const badge = document.getElementById('notifBadge');

    if (list.length > 0) badge.classList.remove('hidden');

    container.innerHTML = list.map(n => `
        <div class="p-4 border-b border-white/5 hover:bg-white/5 transition-colors cursor-pointer group">
            <div class="flex justify-between items-start mb-1">
                <span class="font-bold text-red-500 text-xs uppercase tracking-wide">${n.title}</span>
                <span class="text-[10px] text-gray-500">${n.time}</span>
            </div>
            <p class="text-sm text-gray-300 group-hover:text-white transition-colors">${n.message}</p>
        </div>
    `).join('');

    if (list.length === 0) container.innerHTML = '<div class="p-4 text-center text-gray-500 text-xs">Aucune notification</div>';
}

function computeAge(dateStr) {
    if (!dateStr) return null;
    const dob = new Date(dateStr);
    if (Number.isNaN(dob.getTime())) return null;
    const now = new Date();
    let age = now.getFullYear() - dob.getFullYear();
    const monthDiff = now.getMonth() - dob.getMonth();
    if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < dob.getDate())) age -= 1;
    return age;
}

function formatBirthDate(dateStr) {
    if (!dateStr) return "Date inconnue";
    const d = new Date(dateStr);
    if (Number.isNaN(d.getTime())) return "Date inconnue";
    return d.toLocaleDateString('fr-FR', { day: '2-digit', month: 'short', year: 'numeric' });
}

function availabilityBadge(isAvailable) {
    return isAvailable
        ? '<span class="badge badge-available">Disponible</span>'
        : '<span class="badge badge-missing">Hors catalogue</span>';
}

function typeBadge(type) {
    const label = type === 'serie' ? 'Série' : 'Film';
    return `<span class="badge badge-type">${label}</span>`;
}

function renderTimeline(timelineEl, filmography, filmsData, seriesData) {
    timelineEl.innerHTML = '';

    if (!filmography || filmography.length === 0) {
        timelineEl.innerHTML = '<div class="text-gray-500 text-sm">Aucun projet enregistré.</div>';
        return;
    }

    // Group films by year
    const grouped = {};
    filmography.forEach(item => {
        const year = item.year || 0;
        if (!grouped[year]) grouped[year] = [];
        grouped[year].push(item);
    });

    // Process grouped years in order
    Object.keys(grouped)
        .sort((a, b) => b - a)
        .forEach(year => {
            const items = grouped[year];
            const row = document.createElement('div');
            row.className = "timeline-item";

            // Check if all items in this year are available
            const allAvailable = items.every(item =>
                item.type === 'serie' ? Boolean(seriesData[item.title]) : Boolean(filmsData[item.title])
            );

            let projectsHTML = '';
            items.forEach(item => {
                const isAvailable = item.type === 'serie'
                    ? Boolean(seriesData[item.title])
                    : Boolean(filmsData[item.title]);

                const episodesLabel = item.type === 'serie' && item.episodes
                    ? `${item.episodes} ${item.episodes > 1 ? 'épisodes' : 'épisode'}`
                    : '';

                const roleText = ['Executive Producer', 'Director', 'Screenplay', 'Co-Executive Producer', 'Producer', 'Songs', 'Associate Producer', 'Thanks', 'Writer', 'Musician', 'Vocals'].includes(item.role) ? 'En tant que' : 'Incarnant';

                projectsHTML += `
                    <div class="timeline-project mb-2 pb-2 last:mb-0 last:pb-0 border-b border-white/5 last:border-b-0">
                        <div class="flex flex-wrap items-center gap-2 mb-1">
                            <span class="font-bold text-white">${item.title || 'Titre inconnu'}</span>
                            ${availabilityBadge(isAvailable)}
                            ${typeBadge(item.type)}
                        </div>
                        <div class="text-sm text-gray-400 leading-relaxed">
                            ${item.role ? `<strong><u>${episodesLabel}</u></strong> ${roleText} <a style="color: #f87171;">${item.role}</a>` : `<strong><u>${episodesLabel}</u></strong> Rôle non renseigné.`}
                        </div>
                    </div>
                `;
            });

            row.innerHTML = `
                <div class="timeline-year">${year || '—'}</div>
                <div class="timeline-body">
                    ${projectsHTML}
                </div>
            `;
            timelineEl.appendChild(row);
        });
}

/**
 * Opens the actor details overlay.
 * @param {Object} actor - Actor object.
 * @param {Object} filmsData - Films data keyed by title.
 * @param {Object} seriesData - Series data keyed by title.
 */
export function openActorDetails(actor, filmsData = {}, seriesData = {}) {
    const overlay = document.getElementById('actorOverlay');

    if (!overlay || !actor) return;

    const photo = actor.photo || `https://placehold.co/500x700/111/fff?text=${encodeURIComponent(actor.name || 'Acteur')}`;
    const filmography = Array.isArray(actor.filmography) ? [...actor.filmography] : [];
    filmography.sort((a, b) => (b.year || 0) - (a.year || 0));

    const age = computeAge(actor.birthDate);
    const ageLabel = age !== null ? `${age} ans` : 'Âge inconnu';
    const birthLabel = formatBirthDate(actor.birthDate);

    const photoEl = document.getElementById('actorDetailPhoto');
    if (photoEl) {
        photoEl.src = photo;
        photoEl.onerror = function () {
            this.src = 'https://placehold.co/500x700/111/fff?text=Acteur';
        };
    }

    const nameEl = document.getElementById('actorDetailName');
    const bioEl = document.getElementById('actorDetailBio');
    const genderEl = document.getElementById('actorDetailGender');
    const ageEl = document.getElementById('actorDetailAge');
    const birthEl = document.getElementById('actorDetailBirth');
    const nationalityEl = document.getElementById('actorDetailNationality');
    const projectsEl = document.getElementById('actorDetailProjects');
    const timelineEl = document.getElementById('actorTimeline');

    if (nameEl) nameEl.textContent = actor.name || 'Nom inconnu';
    if (bioEl) bioEl.textContent = actor.bio || 'Biographie non renseignée.';
    if (genderEl) genderEl.textContent = actor.gender || 'Non renseigné';
    if (ageEl) ageEl.textContent = ageLabel;
    if (birthEl) birthEl.textContent = actor.birthPlace ? `${birthLabel} • ${actor.birthPlace}` : birthLabel;
    if (nationalityEl) nationalityEl.textContent = actor.nationality || '—';
    if (projectsEl) projectsEl.textContent = `${filmography.length} projets`;

    if (timelineEl) renderTimeline(timelineEl, filmography, filmsData, seriesData);

    overlay.classList.remove('hidden');
    document.body.style.overflow = 'hidden';
}

/**
 * Closes the actor details overlay.
 */
export function closeActorDetails() {
    const overlay = document.getElementById('actorOverlay');
    if (!overlay) return;
    overlay.classList.add('hidden');
    document.body.style.overflow = '';
}

/**
 * Renders the grid of actors (photo + nom).
 * @param {Object} actorsData - Actors keyed by slug/id.
 * @param {Object} filmsData - Films data keyed by title.
 * @param {Object} seriesData - Series data keyed by title.
 */
export function renderActorsList(actorsData, filmsData = {}, seriesData = {}) {
    const container = document.getElementById('actorsContent');
    if (!container) return;

    const actors = Object.values(actorsData || {});
    if (actors.length === 0) {
        container.innerHTML = '<div class="text-center text-gray-500 py-12">Aucun acteur enregistré pour le moment.</div>';
        return;
    }

    actors.sort((a, b) => a.name.localeCompare(b.name));
    container.innerHTML = '';

    const grid = document.createElement('div');
    grid.className = "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6 gap-y-8";

    actors.forEach(actor => {
        const photo = actor.photo || `https://placehold.co/500x700/111/fff?text=${encodeURIComponent(actor.name || 'Acteur')}`;
        const card = document.createElement('div');
        card.className = "relative overflow-hidden rounded-2xl group shadow-lg bg-[#121212] border border-white/5 cursor-pointer actor-thumb";
        card.innerHTML = `
            <img src="${photo}" alt="${actor.name || 'Acteur'}" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" onerror="this.src='https://placehold.co/500x700/111/fff?text=Acteur'" />
            <div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
            <div class="absolute bottom-0 left-0 right-0 p-4 flex items-center justify-between">
                <h4 class="font-black text-white text-lg drop-shadow-md line-clamp-2">${actor.name || 'Nom inconnu'}</h4>
                <span class="text-xs font-bold text-gray-300 bg-white/10 rounded-full px-3 py-1 border border-white/10">Voir</span>
            </div>
        `;

        card.onclick = () => openActorDetails(actor, filmsData, seriesData);
        grid.appendChild(card);
    });

    container.appendChild(grid);
}

/**
 * Renders a list of actors in a search results section.
 * @param {Array} actorsData - Array of actor objects to display.
 * @param {Object} filmsData - Films data for opening actor details.
 * @param {Object} seriesData - Series data for opening actor details.
 */
export function renderActorsListSearch(actorsData, filmsData = {}, seriesData = {}) {
    const container = document.getElementById('contentGrid');
    if (!container) return;

    if (!actorsData || actorsData.length === 0) {
        return;
    }

    // Create a section title for actors
    const section = document.createElement('div');
    section.className = "col-span-full mt-12 mb-6";

    const titleDiv = document.createElement('div');
    titleDiv.className = "flex items-center gap-4 mb-6";
    
    const accentSpan = document.createElement('span');
    accentSpan.className = 'w-1 h-8 bg-red-600 rounded-full shadow-[0_0_15px_#dc2626]';
    titleDiv.appendChild(accentSpan);

    const titleText = document.createElement('span');
    titleText.className = 'tracking-tight text-xl font-bold';
    titleText.textContent = `Acteurs (${actorsData.length})`;
    titleDiv.appendChild(titleText);

    section.appendChild(titleDiv);

    const grid = document.createElement('div');
    grid.className = "col-span-full grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6 gap-y-8";

    actorsData.forEach(actor => {
        const photo = actor.photo || `https://placehold.co/500x700/111/fff?text=${encodeURIComponent(actor.name || 'Acteur')}`;
        const card = document.createElement('div');
        card.className = "relative overflow-hidden rounded-2xl group shadow-lg bg-[#121212] border border-white/5 cursor-pointer actor-thumb";
        card.innerHTML = `
            <img src="${photo}" alt="${actor.name || 'Acteur'}" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" onerror="this.src='https://placehold.co/500x700/111/fff?text=Acteur'" />
            <div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
            <div class="absolute bottom-0 left-0 right-0 p-4 flex items-center justify-between">
                <h4 class="font-black text-white text-lg drop-shadow-md line-clamp-2">${actor.name || 'Nom inconnu'}</h4>
                <span class="text-xs font-bold text-gray-300 bg-white/10 rounded-full px-3 py-1 border border-white/10">Voir</span>
            </div>
        `;

        card.onclick = () => openActorDetails(actor, filmsData, seriesData);
        grid.appendChild(card);
    });

    section.appendChild(grid);
    container.appendChild(section);
}