import NovelDetailPage from "@/components/novel/detail/novelDetailPage";
import { getPostChapters, getPostChaptersAuthenticated, getPostDetail, getPostDetailAuthenticated } from "@/libs/axios/modules/post";
import { ChapterModel, PostModel } from "@/models";
import { extractId, withSlug } from "@/utils/slug";
import type { Metadata } from "next";
import { cookies } from "next/headers";
import { cache } from "react";

const getCachedNovel = cache(async (novel_id: string, rawToken?: string): Promise<PostModel> => {
    return rawToken
        ? (await getPostDetailAuthenticated(rawToken, novel_id)).data.data
        : (await getPostDetail(novel_id)).data.data;
});

async function getRouteContext(params: Promise<{ locale: string; novel_id: string }>) {
    const cookieStore = await cookies();
    const token = cookieStore.get("token");
    const rawToken = token?.value?.slice(1, -1);

    const { locale, novel_id: novelIdParam } = await params;
    const novel_id = extractId(novelIdParam);

    return { locale, novel_id, rawToken };
}

export async function generateMetadata({
    params,
}: {
    params: Promise<{ locale: string; novel_id: string }>;
}): Promise<Metadata> {
    try {
        const { locale, novel_id, rawToken } = await getRouteContext(params);
        const novel = await getCachedNovel(novel_id, rawToken);
        const description = novel.description
            ? novel.description.slice(0, 160)
            : undefined;
        const canonical = `/${locale}/novel/${withSlug(novel.id, novel.slug)}`;

        return {
            title: novel.title,
            description,
            alternates: { canonical },
            openGraph: {
                title: novel.title,
                description,
                type: "article",
                url: canonical,
                images: novel.image ? [{ url: novel.image }] : undefined,
            },
            twitter: {
                card: "summary_large_image",
                title: novel.title,
                description,
                images: novel.image ? [novel.image] : undefined,
            },
        };
    } catch {
        return {};
    }
}

function buildJsonLd(novel: PostModel) {
    const hasRating = (novel.total_reviews ?? 0) > 0;

    const jsonLd = {
        "@context": "https://schema.org",
        "@type": "Book",
        name: novel.title,
        image: novel.image || undefined,
        description: novel.description || undefined,
        genre: novel.genre?.title || undefined,
        author: novel.author?.name
            ? { "@type": "Person", name: novel.author.name }
            : undefined,
        aggregateRating: hasRating
            ? {
                "@type": "AggregateRating",
                ratingValue: (novel.total_sum_reviews / novel.total_reviews).toFixed(1),
                reviewCount: novel.total_reviews,
                bestRating: 5,
                worstRating: 1,
            }
            : undefined,
    };

    return JSON.stringify(jsonLd).replace(/</g, "\\u003c");
}

export default async function NovelDetail({ params }: { params: Promise<{ locale: string; novel_id: string }> }) {
    const { novel_id, rawToken } = await getRouteContext(params);

    const novel = await getCachedNovel(novel_id, rawToken);
    const chapters: ChapterModel[] = rawToken
        ? (await getPostChaptersAuthenticated(rawToken, { post_id: novel_id, page: 1, limit: 5 })).data.data
        : (await getPostChapters(novel_id, { page: 1, limit: 0 })).data.data;

    const updatedChapters = chapters.map((chapter: ChapterModel) => {
        return {
            ...chapter,
            is_paid: chapter.order > 5 ? true : false,
        };
    });

    if (novel.last_view_chapter.order <= 5) {
        novel.last_view_chapter.is_paid = false;
    }

    return novel && chapters && (
        <>
            <script
                type="application/ld+json"
                dangerouslySetInnerHTML={{ __html: buildJsonLd(novel) }}
            />
            <NovelDetailPage novel={novel} chapters={updatedChapters} />
        </>
    );
}
