import { Duration } from '../../../../modules/shared-kernel/entities/shared/duration.valueObject.js';
const SPARKLINE_MAX_POINTS = 10;
const RECENT_FEED_MAX_ITEMS = 10;
const EMPTY_ELAPSED_LABEL = '—';
const EMPTY_PROJECT_LABEL = '—';
const EMPTY_SCORE_LABEL = '-';
function resolveProjectName(repositories, localPath) {
    const match = repositories.find((repository) => repository.localPath === localPath);
    return match ? match.name : null;
}
function resolveProjectNameFromFilePath(repositories, filePath) {
    const match = repositories.find((repository) => filePath.startsWith(`${repository.localPath}/`));
    return match ? match.name : null;
}
function resolvePlatformForProject(repositories, localPath) {
    const match = repositories.find((repository) => repository.localPath === localPath);
    return match ? match.platform : 'gitlab';
}
function formatElapsed(now, startedAt) {
    if (startedAt === null)
        return EMPTY_ELAPSED_LABEL;
    const startedMs = new Date(startedAt).getTime();
    if (Number.isNaN(startedMs))
        return EMPTY_ELAPSED_LABEL;
    const elapsedMs = Math.max(0, now.getTime() - startedMs);
    return Duration.fromMilliseconds(elapsedMs).formatted;
}
function formatAverageScore(averageScore) {
    if (averageScore === null)
        return EMPTY_SCORE_LABEL;
    return averageScore.toFixed(1);
}
function buildSparklinePoints(reviews) {
    const sorted = [...reviews].sort((left, right) => left.timestamp.localeCompare(right.timestamp));
    const lastTen = sorted.slice(-SPARKLINE_MAX_POINTS);
    return lastTen
        .filter((review) => review.score !== null && review.score !== undefined)
        .map((review) => review.score);
}
function buildActiveReviewItem(job, repositories, now) {
    const projectName = resolveProjectName(repositories, job.project) ?? EMPTY_PROJECT_LABEL;
    const platform = resolvePlatformForProject(repositories, job.project);
    return {
        jobId: job.id,
        projectName,
        projectPath: job.project,
        mrPrefix: platform === 'github' ? 'PR' : 'MR',
        mrNumber: job.mrNumber,
        mrUrl: job.mrUrl,
        elapsedLabel: formatElapsed(now, job.startedAt),
        jobType: job.jobType ?? 'review',
    };
}
function resolveExternalLink(projectConfigs, localPath) {
    if (!projectConfigs)
        return undefined;
    const entry = projectConfigs[localPath];
    if (!entry || typeof entry.externalLink !== 'string' || entry.externalLink.length === 0) {
        return undefined;
    }
    return entry.externalLink;
}
function buildProjectCard(repository, statsByPath, projectConfigs) {
    const externalLink = resolveExternalLink(projectConfigs, repository.localPath);
    const statsEntry = statsByPath.get(repository.localPath) ?? null;
    if (statsEntry === null) {
        const emptyCard = {
            projectName: repository.name,
            projectPath: repository.localPath,
            platform: repository.platform,
            totalReviews: 0,
            averageScoreLabel: EMPTY_SCORE_LABEL,
            sparklinePoints: [],
            isEmptyHistory: true,
        };
        if (externalLink !== undefined)
            emptyCard.externalLink = externalLink;
        return emptyCard;
    }
    const sparklinePoints = buildSparklinePoints(statsEntry.stats.reviews);
    const card = {
        projectName: repository.name,
        projectPath: repository.localPath,
        platform: repository.platform,
        totalReviews: statsEntry.summary.totalReviews,
        averageScoreLabel: formatAverageScore(statsEntry.summary.averageScore),
        sparklinePoints,
        isEmptyHistory: statsEntry.summary.totalReviews === 0,
    };
    if (externalLink !== undefined)
        card.externalLink = externalLink;
    return card;
}
function buildRecentReviewItem(review, repositories) {
    const projectName = resolveProjectNameFromFilePath(repositories, review.path) ?? EMPTY_PROJECT_LABEL;
    const mrPrefix = review.type === 'PR' ? 'PR' : 'MR';
    return {
        filename: review.filename,
        projectName,
        mrPrefix,
        mrNumber: review.mrNumber,
        title: review.title ?? '',
        mtime: review.mtime,
    };
}
export class OverviewPresenter {
    now;
    constructor(dependencies = {}) {
        this.now = dependencies.now ?? (() => new Date());
    }
    present(input) {
        const now = this.now();
        const activeItems = [...input.activeJobs]
            .map((job) => ({ job, startedAtMs: job.startedAt === null ? 0 : new Date(job.startedAt).getTime() }))
            .sort((left, right) => right.startedAtMs - left.startedAtMs)
            .map(({ job }) => buildActiveReviewItem(job, input.repositories, now));
        const statsByPath = new Map();
        for (const entry of input.projectStats) {
            statsByPath.set(entry.path, entry);
        }
        const cardItems = input.repositories.map((repository) => buildProjectCard(repository, statsByPath, input.projectConfigs));
        const recentItems = [...input.recentReviews]
            .sort((left, right) => right.mtime.localeCompare(left.mtime))
            .slice(0, RECENT_FEED_MAX_ITEMS)
            .map((review) => buildRecentReviewItem(review, input.repositories));
        const capacity = input.capacity ?? { running: 0, max: 0 };
        const headerCapacity = {
            runningCount: capacity.running,
            totalCapacity: capacity.max,
            label: `${capacity.running} / ${capacity.max}`,
            isSaturated: capacity.max > 0 && capacity.running >= capacity.max,
        };
        return {
            activeReviews: {
                items: activeItems,
                isEmpty: activeItems.length === 0,
                emptyMessage: 'Aucune review en cours',
            },
            projectCards: {
                items: cardItems,
                isEmpty: cardItems.length === 0,
                emptyMessage: 'Aucun projet configuré',
            },
            recentReviewsFeed: {
                items: recentItems,
                isEmpty: recentItems.length === 0,
                emptyMessage: 'Aucune review récente',
            },
            headerCapacity,
        };
    }
}
//# sourceMappingURL=overview.presenter.js.map