export interface JournalEntrySearchParams {
    str?: string;
    cat?: string | null;
    enabled?: 'enabled' | 'all' | 'not_enabled';
    hidden?: 'hidden' | 'all' | 'not_hidden';
    limit?: number;
}

function normalize_search_value(value: unknown): string {
    if (value === null || value === undefined) return '';

    if (typeof value === 'string') return value.toLowerCase();
    if (typeof value === 'number' || typeof value === 'boolean') {
        return String(value).toLowerCase();
    }

    try {
        return JSON.stringify(value).toLowerCase();
    } catch {
        return String(value).toLowerCase();
    }
}

function build_journal_entry_search_blob(entry: any): string {
    return [
        entry?.code,
        entry?.name,
        entry?.short_name,
        entry?.summary,
        entry?.outline,
        entry?.content,
        entry?.history,
        entry?.notes,
        entry?.tags,
        entry?.activity_code,
        entry?.category_code,
        entry?.type_code,
        entry?.topic_code,
        entry?.group,
        entry?.journal_code,
        entry?.journal_name,
        entry?.alert_msg,
        entry?.default_qry_str
    ]
        .map(normalize_search_value)
        .filter(Boolean)
        .join(' ');
}

export function journal_entry_matches_search(
    entry: any,
    params: JournalEntrySearchParams
): boolean {
    if (!entry) return false;

    const qry_str = (params.str ?? '').toLowerCase().trim();
    const category_code = params.cat ?? '';
    const enabled_mode = params.enabled ?? 'all';
    const hidden_mode = params.hidden ?? 'all';

    const is_hidden = entry.hide === true || entry.hide === 1;
    const is_disabled = entry.enable === false || entry.enable === 0;

    if (category_code && entry.category_code !== category_code) return false;

    if (enabled_mode === 'enabled' && is_disabled) return false;
    if (enabled_mode === 'not_enabled' && !is_disabled) return false;

    if (hidden_mode === 'hidden' && !is_hidden) return false;
    if (hidden_mode === 'not_hidden' && is_hidden) return false;

    if (!qry_str) return true;

    return build_journal_entry_search_blob(entry).includes(qry_str);
}

export function journal_entry_compare_for_list(a: any, b: any): number {
    // tmp_sort_1 is built by build_tmp_sort() for ascending comparison:
    // priority=true encodes as '0', priority=false as '1', so ASC puts priority first.
    return (
        (a?.tmp_sort_1 ?? '').localeCompare(b?.tmp_sort_1 ?? '') ||
        (b?.updated_on ?? '').localeCompare(a?.updated_on ?? '') ||
        (b?.journal_entry_id ?? '').localeCompare(a?.journal_entry_id ?? '')
    );
}

export function journal_entry_filter_list(
    list: any[] | null | undefined,
    params: JournalEntrySearchParams
): any[] | null {
    if (list === undefined || list === null) return null;
    if (!Array.isArray(list)) return [];

    const has_text_search = Boolean((params.str ?? '').trim());

    const filtered = list
        .filter((entry) => journal_entry_matches_search(entry, params))
        .sort(journal_entry_compare_for_list);

    // Broad views should show the full local result set; only text searches
    // should be sliced to a page-sized window.
    if (has_text_search && params.limit && params.limit > 0) {
        return filtered.slice(0, params.limit);
    }

    return filtered;
}