import type { MangaSort, SortOrder } from './api/mangas';

/// The catalog's default sort field. A bare `/?` (no `sort`) means this.
export const DEFAULT_SORT: MangaSort = 'updated';

export const SORT_FIELD_LABELS: Record<MangaSort, string> = {
    updated: 'Last updated',
    created: 'Date added',
    title: 'Title',
    author: 'Author'
};

/** Text fields sort A→Z by default; date fields newest-first. */
export function isTextField(f: MangaSort): boolean {
    return f === 'title' || f === 'author';
}

/**
 * The direction applied when `order` is omitted. This mirrors the backend's
 * `SortField::default_order` (backend/src/repo/manga.rs) on purpose: a bare
 * `?sort=<field>` link must read the same in the UI and over the wire.
 */
export function defaultOrderFor(f: MangaSort): SortOrder {
    return isTextField(f) ? 'asc' : 'desc';
}

/** The asc/desc toggle options, labelled for the field type. */
export function dirOptions(f: MangaSort): { label: string; value: SortOrder }[] {
    return isTextField(f)
        ? [
              { label: 'A→Z', value: 'asc' },
              { label: 'Z→A', value: 'desc' }
          ]
        : [
              { label: 'Newest', value: 'desc' },
              { label: 'Oldest', value: 'asc' }
          ];
}

export function dirLabel(sort: MangaSort, order: SortOrder): string {
    return dirOptions(sort).find((o) => o.value === order)?.label ?? '';
}

export function sortLabel(sort: MangaSort, order: SortOrder): string {
    return `${SORT_FIELD_LABELS[sort]} · ${dirLabel(sort, order)}`;
}

/**
 * Coerce a raw `sort` query value to a valid field, falling back to default.
 * `recent` is honored as the same back-compat alias the API exposes (== the
 * `created` field), so a hand-shared or legacy `/?sort=recent` URL resolves to
 * the same field in the browser as over the wire.
 */
export function coerceSort(raw: string | null | undefined): MangaSort {
    if (raw === 'recent') return 'created';
    return raw === 'created' || raw === 'updated' || raw === 'title' || raw === 'author'
        ? raw
        : DEFAULT_SORT;
}

/**
 * Coerce a raw `order` query value, falling back to the field's natural
 * default when absent or invalid — mirroring how {@link sortUrlParams} omits it.
 */
export function coerceOrder(raw: string | null | undefined, sort: MangaSort): SortOrder {
    return raw === 'asc' || raw === 'desc' ? raw : defaultOrderFor(sort);
}

/**
 * The `sort`/`order` params to persist in the shareable URL. Defaults are
 * omitted to keep the common URL clean; because the backend resolves an absent
 * `order` to {@link defaultOrderFor} too, the omission is unambiguous across
 * the UI and direct API callers.
 */
export function sortUrlParams(
    sort: MangaSort,
    order: SortOrder
): { sort?: MangaSort; order?: SortOrder } {
    const out: { sort?: MangaSort; order?: SortOrder } = {};
    if (sort !== DEFAULT_SORT) out.sort = sort;
    if (order !== defaultOrderFor(sort)) out.order = order;
    return out;
}
