import { getBlockComponent } from "@/components/page-blocks";
import { slugFromComponentName } from "@/lib/blockSlug";

export type CompetitionNavItem = {
    id: string;
    label: string;
    icon: string;
    targetComponent: string;
    badgeCount: string;
};

type ContentMap = Record<string, unknown>;

type ComponentLookup = {
    id?: number;
    name: string;
    slug: string;
};

type PageBlockRef = {
    componentId?: number;
    componentSlug?: string;
    componentName?: string;
    content?: ContentMap;
};

function str(value: unknown): string {
    return typeof value === "string" ? value : "";
}

type CompetitionNavOptions = {
    /** When true, only items with a linked Target Component are kept (page switching). */
    requireTarget?: boolean;
};

/**
 * Read Competition Navigation items.
 * Default: keep any row with a label so the editor preview updates while Target is still empty.
 * Pass requireTarget: true for live show/hide switching.
 */
export function getCompetitionNavigation(
    content?: ContentMap,
    options: CompetitionNavOptions = {},
): CompetitionNavItem[] {
    if (!Array.isArray(content?.competitionNavigation)) return [];

    const requireTarget = options.requireTarget === true;

    return content.competitionNavigation
        .map((item, index) => {
            const record = item != null && typeof item === "object"
                ? (item as Record<string, unknown>)
                : {};
            const label = str(record.label).trim();
            const targetComponent = str(record.targetComponent ?? record.targetSlug ?? record.target).trim();

            return {
                id: str(record.id).trim() || `competition-nav-${index + 1}`,
                label,
                icon: str(record.icon).trim(),
                targetComponent,
                badgeCount: str(record.badgeCount).trim(),
            };
        })
        .filter((item) => item.label && (!requireTarget || item.targetComponent));
}

export function slugifyComponentTarget(value: string): string {
    return value
        .trim()
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, "-")
        .replace(/^-+|-+$/g, "");
}

/** Resolve a configured target name/slug to a registry/component slug without hardcoded pairs. */
export function resolveCompetitionTargetSlug(
    target: string,
    components: ComponentLookup[] = [],
): string {
    const value = target.trim();
    if (!value) return "";

    if (getBlockComponent(value)) return value;

    const bySlug = components.find((component) => component.slug === value);
    if (bySlug) return bySlug.slug;

    const normalizedValue = value.toLowerCase();
    const byName = components.find((component) => {
        const name = str(component.name).trim();
        return name !== "" && name.toLowerCase() === normalizedValue;
    });
    if (byName) return byName.slug;

    const byId = components.find((component) => String(component.id ?? "") === value);
    if (byId) return byId.slug;

    const mapped = slugFromComponentName(value);
    if (
        mapped
        && mapped !== "hero"
        && (getBlockComponent(mapped) || components.some((component) => component.slug === mapped))
    ) {
        return mapped;
    }

    const slugified = slugifyComponentTarget(value);
    if (slugified && getBlockComponent(slugified)) return slugified;
    if (slugified && components.some((component) => component.slug === slugified)) {
        return slugified;
    }
    if (slugified) return slugified;

    return value;
}

/** True when a page block is the competition target currently configured in navigation. */
export function blockMatchesCompetitionTarget(
    block: PageBlockRef,
    targetSlug: string,
    components: ComponentLookup[] = [],
    resolveSlug: (block: PageBlockRef) => string = (item) => item.componentSlug ?? "",
): boolean {
    if (!targetSlug) return false;

    const blockSlug = resolveSlug(block);
    if (blockSlug && blockSlug === targetSlug) return true;

    const blockName = str(block.componentName).trim();
    if (blockName) {
        const nameSlug = resolveCompetitionTargetSlug(blockName, components);
        if (nameSlug && nameSlug === targetSlug) return true;
    }

    if (block.componentId != null) {
        const byId = components.find((component) => component.id === block.componentId);
        if (byId?.slug === targetSlug) return true;
    }

    return false;
}

export function collectCompetitionNavState(
    blocks: PageBlockRef[],
    components: ComponentLookup[] = [],
    resolveSlug: (block: PageBlockRef) => string,
): {
    items: CompetitionNavItem[];
    targetSlugs: string[];
    defaultTargetSlug: string;
    hasCompetitionNavigation: boolean;
} {
    const items: CompetitionNavItem[] = [];

    for (const block of blocks) {
        const slug = resolveSlug(block);
        if (slug !== "grade-hero" && slug !== "design-to-impact-hero") continue;
        // Page switching only uses fully linked targets.
        items.push(...getCompetitionNavigation(block.content, { requireTarget: true }));
    }

    const targetSlugs = items
        .map((item) => resolveCompetitionTargetSlug(item.targetComponent, components))
        .filter(Boolean);

    return {
        items,
        targetSlugs: Array.from(new Set(targetSlugs)),
        defaultTargetSlug: targetSlugs[0] ?? "",
        hasCompetitionNavigation: items.length > 0,
    };
}

export function isCompetitionTargetBlock(blockSlug: string, targetSlugs: string[]): boolean {
    return targetSlugs.includes(blockSlug);
}

/**
 * Whether a competition-target block should be visible for the active selection.
 * Non-target blocks always stay visible (except legacy competition-tabs when Grade Hero owns nav).
 */
export function isCompetitionTargetVisible(
    block: PageBlockRef,
    targetSlugs: string[],
    activeTargetSlug: string,
    components: ComponentLookup[] = [],
    resolveSlug: (block: PageBlockRef) => string = (item) => item.componentSlug ?? "",
): boolean {
    const blockSlug = resolveSlug(block);

    // Legacy Competition Tabs chrome/content is superseded by Grade Hero navigation.
    if (targetSlugs.length > 0 && blockSlug === "competition-tabs") {
        return false;
    }

    const isTarget = targetSlugs.some((targetSlug) => (
        blockMatchesCompetitionTarget(block, targetSlug, components, resolveSlug)
    ));
    if (!isTarget) return true;

    const active = activeTargetSlug || targetSlugs[0] || "";
    if (!active) return true;

    return blockMatchesCompetitionTarget(block, active, components, resolveSlug);
}

/** @deprecated Prefer isCompetitionTargetVisible for name/id-aware matching. */
export function shouldRenderCompetitionTarget(
    blockSlug: string,
    targetSlugs: string[],
    activeTargetSlug: string,
): boolean {
    if (targetSlugs.length > 0 && blockSlug === "competition-tabs") return false;
    if (!isCompetitionTargetBlock(blockSlug, targetSlugs)) return true;
    if (!activeTargetSlug) return targetSlugs[0] === blockSlug;
    return blockSlug === activeTargetSlug;
}

export function emptyCompetitionNavItem(): CompetitionNavItem {
    return {
        id: `competition-nav-${Date.now()}`,
        label: "",
        icon: "",
        targetComponent: "",
        badgeCount: "",
    };
}
