/**
 * This Source Code is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright (c) Infonomic Company Limited
 */
import { getCollectionDefinition } from '@byline/core';
import { resolveFallbackDisplayField, resolveRowLabel } from './relation-display';
/** Max titles shown for a hasMany cell before collapsing to "+N more". */
const MAX_SHOWN = 3;
function labelFor(env, displayField) {
    // Unresolved (deleted / out-of-scope target) or not populated → no title.
    if (env == null || env._resolved === false || env.document == null)
        return null;
    return resolveRowLabel(env.document, displayField);
}
/**
 * Pure text projection of a relation cell: the target's title for a single
 * relation, or "A, B, +N more" for `hasMany`. Unresolved targets are skipped;
 * an all-empty cell yields `null` (the formatter renders a muted dash).
 *
 * `displayField` is the resolved chain
 * (`field.displayField` → target `useAsTitle` → first text field).
 */
export function formatRelationCellText(field, value, displayField) {
    const envelopes = field.hasMany
        ? Array.isArray(value)
            ? value
            : []
        : value
            ? [value]
            : [];
    const labels = envelopes
        .map((env) => labelFor(env, displayField))
        .filter((l) => l != null && l.length > 0);
    if (labels.length === 0)
        return null;
    if (!field.hasMany)
        return labels[0] ?? null;
    const shown = labels.slice(0, MAX_SHOWN);
    const extra = labels.length - shown.length;
    return extra > 0 ? `${shown.join(', ')}, +${extra} more` : shown.join(', ');
}
/**
 * The built-in `{ component }` column formatter for a `relation` field. Resolves
 * the target collection's `useAsTitle` at render time and renders the cell text.
 */
export function relationColumnFormatter(field) {
    return {
        component: ({ value }) => {
            const targetDef = getCollectionDefinition(field.targetCollection);
            const displayField = field.displayField ?? targetDef?.useAsTitle ?? resolveFallbackDisplayField(targetDef);
            const text = formatRelationCellText(field, value, displayField);
            return text != null ? (<span className="byline-relation-column">{text}</span>) : (<span className="byline-relation-column-empty muted">—</span>);
        },
    };
}
/**
 * Return a copy of `columns` with {@link relationColumnFormatter} applied to any
 * `relation`-typed column that doesn't already declare its own formatter, so
 * relation cells render target titles by default. Other columns are untouched.
 */
export function applyRelationColumnFormatters(columns, definition) {
    return columns.map((col) => {
        if (col.formatter)
            return col;
        const field = definition.fields.find((f) => f.name === String(col.fieldName));
        if (field?.type === 'relation') {
            return { ...col, formatter: relationColumnFormatter(field) };
        }
        return col;
    });
}
