const NON_PUBLIC_LABEL_SUFFIX = " (non-public)";

export const stripNonPublicSuffix = (label) => {
    const value = `${label || ""}`;
    return value.endsWith(NON_PUBLIC_LABEL_SUFFIX)
        ? value.slice(0, -NON_PUBLIC_LABEL_SUFFIX.length)
        : value;
};

export const normalizePostTypeCatalog = (catalog) => {
    if (!catalog || typeof catalog !== "object") {
        return {};
    }

    const out = {};
    Object.entries(catalog)
        .sort(([left], [right]) => `${left}`.localeCompare(`${right}`))
        .forEach(([postType, value]) => {
            const slug = `${postType || ""}`.trim();
            if (slug === "") {
                return;
            }

            if (typeof value === "string") {
                const label = `${value || ""}`.trim() || slug;
                out[slug] = {
                    slug,
                    label,
                    public: true,
                    publicly_queryable: true,
                    show_ui: true,
                    has_archive: false,
                };
                return;
            }

            const raw = value && typeof value === "object" ? value : {};
            const label = `${raw.label || ""}`.trim() || slug;

            out[slug] = {
                slug,
                label,
                public: raw.public !== false,
                publicly_queryable: !!raw.publicly_queryable,
                show_ui: raw.show_ui !== false,
                has_archive: !!raw.has_archive,
            };
        });

    return out;
};

export const filterPostTypeCatalog = (catalog, includeNonPublic) => {
    const out = {};
    Object.entries(catalog || {}).forEach(([slug, postType]) => {
        if (!postType || typeof postType !== "object") {
            return;
        }

        if (postType.show_ui === false) {
            return;
        }

        if (!includeNonPublic && postType.public === false) {
            return;
        }

        out[slug] = postType;
    });

    return out;
};

export const catalogToLabelMap = (catalog) => {
    const out = {};
    Object.entries(catalog || {}).forEach(([slug, postType]) => {
        if (!postType || typeof postType !== "object") {
            return;
        }

        const normalizedSlug = `${slug || ""}`.trim();
        if (normalizedSlug === "") {
            return;
        }

        out[normalizedSlug] = `${postType.label || normalizedSlug}`;
    });

    return out;
};

export const isDisplayablePostType = (postType, catalog) => {
    const slug = `${postType || ""}`.trim();
    if (slug === "") {
        return false;
    }

    const candidate = catalog?.[slug];
    if (!candidate || typeof candidate !== "object") {
        return false;
    }

    return candidate.show_ui !== false;
};

export const normalizeIds = (ids) => {
    if (!Array.isArray(ids)) {
        return [];
    }

    return Array.from(
        new Set(
            ids
                .map((id) => parseInt(id, 10))
                .filter((id) => Number.isInteger(id) && id > 0),
        ),
    );
};

export const normalizeRelationships = (relationships) => {
    if (!Array.isArray(relationships)) {
        return [];
    }

    return Array.from(
        new Set(
            relationships
                .map((relationship) => `${relationship || ""}`.trim())
                .filter((relationship) => relationship !== ""),
        ),
    );
};

export const defaultPostTypeConfig = () => ({
    archives_enabled: false,
    enabled: true,
    expand_post_types: [],
    relationships: [],
    tags_enabled: false,
    target_mode: "selected",
    target_page_ids: [],
    taxonomy_archives_enabled: false,
    propagation: {
        relationships_enabled: true,
        taxonomies_enabled: true,
        first_publish_single_fanout_enabled: false,
    },
});

export const normalizePostTypeConfig = (config) => {
    const fallback = defaultPostTypeConfig();
    const raw = config && typeof config === "object" ? config : {};
    const rawPropagation =
        raw.propagation && typeof raw.propagation === "object"
            ? raw.propagation
            : {};
    const normalizedRelationships = normalizeRelationships(raw.relationships);

    const mode = `${raw.target_mode || ""}`;
    const archivesEnabled =
        typeof raw.archives_enabled === "boolean"
            ? raw.archives_enabled
            : fallback.archives_enabled;
    const taxonomyArchivesEnabled =
        typeof raw.taxonomy_archives_enabled === "boolean"
            ? raw.taxonomy_archives_enabled
            : fallback.taxonomy_archives_enabled;

    return {
        archives_enabled: archivesEnabled,
        enabled: raw.enabled !== false,
        expand_post_types: normalizeRelationships(raw.expand_post_types),
        relationships: normalizedRelationships,
        tags_enabled: raw.tags_enabled === true,
        target_mode: ["selected", "all", "full_flush"].includes(mode)
            ? mode
            : fallback.target_mode,
        target_page_ids: normalizeIds(raw.target_page_ids),
        taxonomy_archives_enabled: taxonomyArchivesEnabled,
        propagation: {
            // Relationship propagation is implicit in relationship-graph mode.
            relationships_enabled: true,
            taxonomies_enabled: rawPropagation.taxonomies_enabled !== false,
            first_publish_single_fanout_enabled:
                !!rawPropagation.first_publish_single_fanout_enabled,
        },
    };
};

export const normalizePostTypes = (postTypes) => {
    if (!postTypes || typeof postTypes !== "object") {
        return {};
    }

    const out = {};
    Object.entries(postTypes).forEach(([postType, config]) => {
        const slug = `${postType || ""}`.trim();
        if (slug === "") {
            return;
        }

        out[slug] = normalizePostTypeConfig(config);
    });

    return out;
};

export const normalizeInvalidationBehavior = (behavior) => {
    const raw = behavior && typeof behavior === "object" ? behavior : {};
    const out = {
        async_enabled: raw.async_enabled === true,
    };
    const parsedDelay = parseInt(raw.async_delay_seconds, 10);

    if (Number.isInteger(parsedDelay)) {
        out.async_delay_seconds = Math.min(300, Math.max(1, parsedDelay));
    }

    return out;
};
