import "server-only";
import type { Metadata } from "next";
import type { ReactNode } from "react";
import type { Lang } from "@/config/constants";
import { getLang, t } from "./lang";
import { buildMetadata } from "./metadata";
import {
    ENTITIES,
    ENTITY_MISSING,
    entityCanonicalPath,
    loadCourseCities,
    loadCourseDistributions,
    loadEntity,
    resolveEntityId,
    type EntityKind,
} from "./entities";
import { JsonLd, breadcrumbLd, entityLd } from "./jsonld";
import { SeedQueries } from "./seed";
import NotFoundView from "@/views/not-found-view";

type Params = Promise<{ id: string }>;

const NOT_FOUND_META = (lang: Lang): Metadata => ({
    title: { absolute: `404 | ${t(lang, "ivory")}` },
    description: t(lang, "custom.no-data-page"),
    robots: { index: false, follow: true },
});

const otherLang = (lang: Lang): Lang => (lang === "ar" ? "en" : "ar");

/**
 * generateMetadata لصفحة كيان ديناميكي:
 *   export const generateMetadata = entityMetadata("blog");
 */
export function entityMetadata(kind: EntityKind) {
    return async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {
        const { id: param } = await params;
        const lang = await getLang();
        const def = ENTITIES[kind];
        const id = resolveEntityId(kind, param);
        if (!id) return NOT_FOUND_META(lang);

        const loaded = await loadEntity(kind, id, lang);
        // كيان محذوف/غير موجود: عنوان 404 + noindex (لا يُفهرس ولا canonical)
        if (loaded === ENTITY_MISSING) return NOT_FOUND_META(lang);
        const e = loaded;
        const name = e?.title || t(lang, def.fallbackTitleKey);
        const title = def.titleWithSection ? `${name} | ${t(lang, def.sectionKey)}` : name;
        const path = entityCanonicalPath(kind, id, e?.record);

        // روابط اللغات: لكل لغة الـ slug المبني من عنوانها (البرامج) — طلب مخزَّن مؤقتاً
        let alternates: Partial<Record<Lang, string>> | undefined;
        if (def.canonicalPath) {
            const other = otherLang(lang);
            const o = await loadEntity(kind, id, other);
            alternates = { [lang]: path, [other]: entityCanonicalPath(kind, id, o && o !== ENTITY_MISSING ? o.record : e?.record) };
        }

        return buildMetadata({
            lang,
            path,
            alternates,
            title,
            description: e?.description,
            keywords: e?.keywords,
            image: e?.image,
            imageAlt: e?.title,
            type: kind === "blog" || kind === "news" ? "article" : "website",
            publishedTime: e?.published,
            modifiedTime: e?.modified,
        });
    };
}

/**
 * يلفّ مكوّن الصفحة الأصلي: يطبع JSON-LD ويحقن بيانات الخادم في React Query.
 * المكوّن الأصلي نفسه لا يتغيّر.
 */
export async function EntitySeo({
    kind,
    params,
    extraSeeds = [],
    children,
}: {
    kind: EntityKind;
    params: Params;
    extraSeeds?: Array<{ queryKey: unknown[]; data: unknown }>;
    children: ReactNode;
}) {
    const { id: param } = await params;
    const lang = await getLang();
    const def = ENTITIES[kind];
    const id = resolveEntityId(kind, param);
    if (!id) return <NotFoundView />;

    const isCourse = kind === "course";
    const [loaded, dist, cities] = await Promise.all([
        loadEntity(kind, id, lang),
        isCourse ? loadCourseDistributions(id, lang) : Promise.resolve(null),
        isCourse ? loadCourseCities(id, lang) : Promise.resolve(null),
    ]);
    // كيان محذوف/غير موجود: صفحة 404 كاملة تُصيَّر على الخادم فوراً (مع الشريط والتذييل)
    // بدل صفحة تفاصيل فارغة أو هيكل تحميل لا ينتهي — والبيانات الوصفية تمنع الفهرسة
    if (loaded === ENTITY_MISSING) return <NotFoundView />;
    const e = loaded;
    const path = entityCanonicalPath(kind, id, e?.record);

    const ld = [
        breadcrumbLd(lang, [
            { name: t(lang, "routes.home"), path: "/" },
            { name: t(lang, def.sectionKey), path: def.listPath },
            { name: e?.title || t(lang, def.fallbackTitleKey), path },
        ]),
    ];
    if (e) ld.unshift(entityLd(e, path, { distribution: dist?.distribution }));

    return (
        <>
            <JsonLd data={ld} />
            <SeedQueries entries={[
                ...(e ? [{ queryKey: e.queryKey, data: e.selected }] : []),
                // مواعيد البرنامج ومدن انعقاده تظهر في HTML الخادم بدل هيكل التحميل
                ...(dist?.data ? [{ queryKey: dist.queryKey, data: dist.data }] : []),
                ...(cities?.data ? [{ queryKey: cities.queryKey, data: cities.data }] : []),
                ...extraSeeds,
            ]}>
                {children}
            </SeedQueries>
        </>
    );
}
