import { formatImageUrl } from "@/utils/helpers";

import { apiEndpoints } from "@/server_api/config/api.endpoints";
import FetchAPIData from "@/server_api/api-functions/apifetch"
import { find, get, isEmpty, trim } from "lodash";
import { routes } from "@/config/routes";
import { Metadata } from "next";
import { SitemapEntry } from "@/types/sitemap/sitemap-types";
import { blockReferences, websiteSetup } from "@/src/constants/website-setup";
import { dynamicPage } from "@/src/constants/page";
import { fetchAPIData } from "@/src/server_api/api-functions/api-fetch-fetch";

const googleSiteVerification = "";

export const getLayoutSeo = async (): Promise<Metadata> => {
    try {
        const [retVal, homeRetVal]: [any, any] = await Promise.all([
            FetchAPIData.fetchAPIData({
                apiEndpoint: apiEndpoints.common.website_setup,
                block: websiteSetup.basicSettings,
                blockReference: `${blockReferences.websiteSettings},${blockReferences.basicDetailsSettings},${blockReferences.marketingScripts}`,
            }),
            FetchAPIData.fetchAPIData({
                apiEndpoint: apiEndpoints.pages.pageBySlug(dynamicPage.home),
            }),
        ]);

        const requestedData = get(retVal, "requestedData", []) as any[];
        const marketingAnalytics = find(requestedData, (data: any) => data.blockReference === blockReferences.marketingScripts)?.blockValues;
        const websiteSettings = find(requestedData, (data: any) => data.blockReference === blockReferences.websiteSettings)?.blockValues;
        const homeData = get(homeRetVal, "requestedData");
        const ogImage = trim(get(homeData, 'ogImageUrl')) !== "" ? (get(homeData, 'ogImageUrl')) : (websiteSettings?.websiteLogoUrl);
        const favIcon = websiteSettings?.favIconUrl;

        console.log("retval", retVal)

        if (homeData) {
            return mapMetadata(homeData, {
                favIcon: formatImageUrl(favIcon),
                ogImage: formatImageUrl(ogImage),
                verification: extractVerification(marketingAnalytics),
            });
        }

        return getDefaultFallbackSeo();
    } catch (error) {
        console.log("Error in getLayoutSeo:", error);
        return getDefaultFallbackSeo();
    }
};

export const getProductListingSeo = async ({ category }: { category: any }): Promise<Metadata> => {
    try {
        const rawCategory = Array.isArray(category) ? category.join("/") : String(category || "");
        const lastSegment = rawCategory ? rawCategory.split("/").pop() || "" : "";

        let homeRetVal: any = null;
        let categoryData: any = null;

        if (rawCategory) {
            homeRetVal = await fetchAPIData(null, apiEndpoints.products.findCategory(rawCategory));
            categoryData = get(homeRetVal, "requestedData");
        }

        if (!categoryData && lastSegment && lastSegment !== rawCategory) {
            homeRetVal = await fetchAPIData(null, apiEndpoints.products.findCategory(lastSegment));
            categoryData = get(homeRetVal, "requestedData");
        }

        if (!categoryData && lastSegment) {
            const underscoreSlug = lastSegment.replace(/-/g, "_");
            if (underscoreSlug !== lastSegment) {
                homeRetVal = await fetchAPIData(null, apiEndpoints.products.findCategory(underscoreSlug));
                categoryData = get(homeRetVal, "requestedData");
            }
        }

        if (!categoryData && lastSegment) {
            const hyphenSlug = lastSegment.replace(/_/g, "-");
            if (hyphenSlug !== lastSegment) {
                homeRetVal = await fetchAPIData(null, apiEndpoints.products.findCategory(hyphenSlug));
                categoryData = get(homeRetVal, "requestedData");
            }
        }

        if (categoryData) {
            const ogImage = trim(get(categoryData, 'ogImageUrl')) !== "" ? get(categoryData, 'ogImageUrl') : get(categoryData, 'categoryImageUrl');
            return mapMetadata(categoryData, {
                slug: routes.productList(rawCategory),
                canonical: routes.productList(rawCategory),
                ogImage: formatImageUrl(ogImage),
            });
        }
        return getDefaultFallbackSeo(routes.productList(rawCategory));
    } catch (error) {
        console.error("Error in getProductListingSeo:", error);
        return getDefaultFallbackSeo(routes.productList(category), "Product Listing");
    }
};



// export const getBlogSeo = async ({ slug }: { slug: any }): Promise<Metadata> => {
//     try {
//         const retVal = await fetchAPIData({ slug, getseo: "1" }, apiEndpoints.common.blogs);
//         const blogData = get(retVal, "requestedData.blogDetails");

//         if (blogData) {
//             return mapMetadata({ ...blogData, ogImageUrl: blogData?.ogImageUrl || blogData?.blogImageUrl }, {
//                 slug: routes.pages.blogDetails(slug),
//                 canonical: routes.pages.blogDetails(slug),
//             });
//         }

//         return getDefaultFallbackSeo(routes.pages.blogDetails(slug), "Blog Details");
//     } catch (error) {
//         console.error("Error in getBlogSeo:", error);
//         return getDefaultFallbackSeo(routes.pages.blogDetails(slug), "Blog Details");
//     }
// };

// export const getProjectsSeo = async ({ slug }: { slug: any }): Promise<Metadata> => {
//     try {
//         const retVal = await fetchAPIData({ slug, getseo: "1" }, apiEndpoints.common.projects);
//         const projectData = get(retVal, "requestedData");

//         if (projectData) {
//             return mapMetadata({ ...projectData, ogImageUrl: projectData?.ogImageUrl || projectData?.projectImageUrl }, {
//                 slug: routes.pages.projectDetails(slug),
//                 canonical: routes.pages.projectDetails(slug),
//             });
//         }

//         return getDefaultFallbackSeo(routes.pages.projectDetails(slug), "Project Details");
//     } catch (error) {
//         console.error("Error in getProjectsSeo:", error);
//         return getDefaultFallbackSeo(routes.pages.projectDetails(slug), "Project Details");
//     }
// };

export const getDefaultFallbackSeo = (canonical?: string, title?: string): Metadata => {
    const baseUrl = process.env.NEXT_PUBLIC_APP_BASE_URL || "";
    return {
        title: title || process.env.NEXT_PUBLIC_APP_NAME,
        description: "",
        icons: {
            icon: `${process.env.NEXT_PUBLIC_APP_BASE_URL}/images/logo-icon.png`,
        },
        alternates: {
            canonical: canonical ? baseUrl + (canonical.startsWith("/") ? canonical : "/" + canonical) : baseUrl,
        },
        other: {
            "google-site-verification": googleSiteVerification,
        },
    };
};

export const getProductDetailsSeo = async ({ slug }: { slug: any }): Promise<Metadata> => {

    try {
        const retVal: any = await FetchAPIData.fetchAPIData({
            apiEndpoint: apiEndpoints.products.productDetailSeo(slug),
        });

        const productData = get(retVal, "requestedData");
        console.log("product details.....", productData)
        const ogImageUrl = trim(get(productData, "ogImageUrl")) !== "" ? get(productData, "ogImageUrl") : get(productData, "productImageUrl");
        console.log(
            "seo product data............", productData,
        )
        if (productData) {
            return mapMetadata(productData, {
                slug: routes.productDetails(slug),
                canonical: routes.productDetails(slug),
                ogImage: formatImageUrl(ogImageUrl)
            });
        }

        return getDefaultFallbackSeo(routes.productDetails(slug), "Product Details");
    } catch (error) {
        console.error("Error in getProductDetailsSeo:", error);
        return getDefaultFallbackSeo(routes.productDetails(slug), "Product Details");
    }
};

export const getBlogSeo = async ({
    slug,
}: {
    slug: string;
}): Promise<Metadata> => {
    try {
        const retVal = await fetchAPIData(
            {
                blogId: slug,
                getseo: "1",
            },
            apiEndpoints.common.blogs()
        );
        console.log("BLOG SEO RESPONSE:", retVal);

        const blogData = get(
            retVal,
            "requestedData.blogDetails"
        );

        console.log("BLOG SEO DATA:", blogData);

        if (blogData) {
            return mapMetadata(
                {
                    ...blogData,
                    ogImageUrl:
                        blogData?.ogImageUrl ||
                        blogData?.blogImageUrl,
                },
                {
                    slug: routes.blogDetails(slug),
                    canonical:
                        process.env.NEXT_PUBLIC_APP_BASE_URL +
                        routes.blogDetails(slug),
                }
            );
        }

        return getDefaultFallbackSeo(
            process.env.NEXT_PUBLIC_APP_BASE_URL +
            routes.blogDetails(slug)
        );
    } catch (error) {
        console.error("Error in getBlogSeo:", error);

        return getDefaultFallbackSeo(
            process.env.NEXT_PUBLIC_APP_BASE_URL +
            routes.blogDetails(slug)
        );
    }
};

export const getTrainingsSeo = async ({
    slug,
}: {
    slug: string;
}): Promise<Metadata> => {
    try {
        const retVal = await fetchAPIData(
            {
                contentSlug: "trainings",
                slug,
                isrelation: "1",
                random: "1",
            },
            apiEndpoints.common.content_management
        );

        console.log("TRAINING SEO RESPONSE:", retVal);

        const trainingData = get(
            retVal,
            "requestedData"
        );

        console.log("TRAINING SEO DATA:", trainingData);

        if (trainingData) {
            return mapMetadata(
                {
                    ...trainingData,
                    ogImageUrl:
                        trainingData?.ogImageUrl ||
                        trainingData?.imageUrl ||
                        trainingData?.blogImageUrl,
                },
                {
                    slug: routes.trainingDetails(slug),
                    canonical:
                        process.env.NEXT_PUBLIC_APP_BASE_URL +
                        routes.trainingDetails(slug),
                }
            );
        }

        return getDefaultFallbackSeo(
            process.env.NEXT_PUBLIC_APP_BASE_URL +
            routes.trainingDetails(slug)
        );
    } catch (error) {
        console.error("Error in getTrainingsSeo:", error);

        return getDefaultFallbackSeo(
            process.env.NEXT_PUBLIC_APP_BASE_URL +
            routes.trainingDetails(slug)
        );
    }
};

export const getDynamicPageSeo = async ({ slug, externalCanonical, fallbackPageTitle }: { slug: any, externalCanonical?: string, fallbackPageTitle?: string }): Promise<any> => {
    const finalCanonical = externalCanonical ? externalCanonical : slug;

    try {
        const apiEndpoint = apiEndpoints.pages.pageBySlug(slug)
        const retVal = await fetchAPIData(null, apiEndpoint);
        const pageData = get(retVal, "requestedData");

        if (pageData) {
            return mapMetadata(pageData, {
                slug: slug,
                canonical: finalCanonical,
            });
        }
        console.log("page...", pageData, slug, retVal)
        return { ...getDefaultFallbackSeo(finalCanonical, fallbackPageTitle), pageNotFound: true };
    } catch (error) {
        console.error("Error in getDynamicPageSeo:", error);
        return getDefaultFallbackSeo(finalCanonical, fallbackPageTitle);
    }
};

// export const getPuckTemplateSeo = async (
//     page: any
// ): Promise<Metadata> => {

//     try {
//         const pageData: any = await FetchAPIData.fetchAPIData({ apiEndpoint: apiEndpoints.common.puckTemplatePage, pageEndPoint: page, getseo: 1 });

//         if (isEmpty(get(pageData, "requestedData"))) {
//             return { title: "Page Not Found" };
//         }

//         const seoContent = mapMetadata(get(pageData, "requestedData"), {
//             canonical: `/${page}`,
//         });

//         return seoContent;
//     } catch (error) {
//         console.error("Metadata Error:", error);
//         return { title: "Page Not Found" };
//     }
// };

export const mapMetadata = (
    data: any,
    options: {
        slug?: string;
        canonical?: string;
        ogImage?: string;
        favIcon?: string;
        verification?: any;
    } = {}
): Metadata => {
    const { slug, canonical, ogImage, favIcon, verification } = options;

    const baseUrl = process.env.NEXT_PUBLIC_APP_BASE_URL || "";
    const finalCanonical = canonical ? `${baseUrl}${canonical.startsWith("/") ? canonical : "/" + canonical}` : `${baseUrl}`;

    const title = data?.metaTitle || data?.categoryTitle || data?.productTitle || data?.title || data?.blogTitle || data?.projectTitle || process.env.NEXT_PUBLIC_APP_NAME;

    let rawDescription = data?.metaDescription || data?.description || data?.blogDescription || data?.projectDescription || "";
    if (typeof rawDescription === "string" && rawDescription.includes("<")) {
        rawDescription = rawDescription.replace(/<[^>]*>?/gm, "").trim();
    }
    const description = rawDescription;
    const keywords = data?.metaKeywords || "";

    const finalOgImage = ogImage || formatImageUrl(data?.ogImageUrl || data?.categoryImageUrl);
    const finalTwitterImage = formatImageUrl(data?.twitterImage) || finalOgImage;

    return {
        title,
        description,
        keywords,
        icons: {
            icon: favIcon || '/images/logo-icon.png',
        },
        openGraph: {
            title: data?.ogTitle || data?.metaTitle || title,
            description: data?.ogDescription || data?.metaDescription || description,
            url: finalCanonical,
            siteName: process.env.NEXT_PUBLIC_APP_NAME,
            images: finalOgImage ? [{ url: finalOgImage, width: 800, height: 600 }] : [],
            locale: "en_US",
            type: "website",
        },
        twitter: {
            card: "summary_large_image",
            title: data?.twitterTitle || data?.ogTitle || data?.metaTitle || title,
            description: data?.twitterDescription || data?.ogDescription || data?.metaDescription || description,
            images: finalTwitterImage ? [finalTwitterImage] : [],
        },
        alternates: {
            canonical: finalCanonical,
        },
        other: {
            "google-site-verification": googleSiteVerification,
        },
        verification: verification,
    };
};

export const mapSeoFromBlocks = (
    requestedData: any[],
    blockReference: string,
    options: {
        slug?: string;
        canonical?: string;
        ogImage?: string;
        favIcon?: string;
        verification?: any;
    } = {}
): Metadata => {
    const data = find(requestedData, (d: any) => d.blockReference === blockReference)?.blockValues;
    return mapMetadata(data, options);
};

export const extractVerification = (marketingAnalytics: any) => {
    const otherMetaVerification: any = {};

    if (marketingAnalytics?.otherHeadScripts) {
        Object.entries(marketingAnalytics.otherHeadScripts).forEach(([key, value]: any) => {
            if (value?.type === "meta" && value?.code) {
                otherMetaVerification[key] = value.code;
            }
        });
    }

    return {
        google: marketingAnalytics?.enableGoogleSiteVerification ? marketingAnalytics.googleSiteVerification : undefined,
        other: otherMetaVerification,
    };
};

export function generateSitemapXml(sitemapEntries: SitemapEntry[]): string {
    const xml = `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      ${sitemapEntries
            .map(
                (entry) => `
        <url>
          <loc>${entry.url}</loc>
            <lastmod>${new Date().toISOString()}</lastmod>
          <priority>${entry.priority}</priority>
        </url>
      `,
            )
            .join('')}
    </urlset>`
    return xml
}