import getJsonLdScriptId from "@insite/client-framework/Common/Utilities/getJsonLdScriptId";
import parseQueryString from "@insite/client-framework/Common/Utilities/parseQueryString";
import prepareBreadcrumbStructuredPageData from "@insite/client-framework/Common/Utilities/prepareBreadcrumbStructuredPageData";
import setPageMetadata from "@insite/client-framework/Common/Utilities/setPageMetadata";
import { trackPageChange } from "@insite/client-framework/Common/Utilities/tracking";
import Zone from "@insite/client-framework/Components/Zone";
import { getContentByVersionPath } from "@insite/client-framework/Services/ContentService";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import sendCategoryPageView from "@insite/client-framework/Store/CommonHandlers/SendCategoryPageView";
import setBreadcrumbs from "@insite/client-framework/Store/Components/Breadcrumbs/Handlers/SetBreadcrumbs";
import prepareCategory from "@insite/client-framework/Store/Components/ProductRecommendations/Handlers/PrepareCategory";
import {
    getSelectedCategoryPath,
    getSettingsCollection,
} from "@insite/client-framework/Store/Context/ContextSelectors";
import { getCatalogPageStateByPath } from "@insite/client-framework/Store/Data/CatalogPages/CatalogPagesSelectors";
import { getCategoryState } from "@insite/client-framework/Store/Data/Categories/CategoriesSelectors";
import { getCurrentPage, getLocation } from "@insite/client-framework/Store/Data/Pages/PageSelectors";
import translate from "@insite/client-framework/Translate";
import PageModule from "@insite/client-framework/Types/PageModule";
import PageProps from "@insite/client-framework/Types/PageProps";
import CurrentCategory from "@insite/content-library/Components/CurrentCategory";
import Page from "@insite/mobius/Page";
import * as React from "react";
import { connect, ResolveThunks } from "react-redux";
import { Dispatch } from "redux";

interface State {
    metadataSetForId?: string;
    odpEventSentFor?: string;
}

const mapStateToProps = (state: ApplicationState) => {
    const location = getLocation(state);
    const categoryPath =
        getSelectedCategoryPath(state) ||
        (location.pathname === getContentByVersionPath
            ? parseQueryString<{ categoryPath: string }>(location.search).categoryPath
            : "") ||
        (location.pathname.toLowerCase().startsWith("/content/") ? "" : location.pathname);
    const catalogPageState = getCatalogPageStateByPath(state, categoryPath);

    return {
        catalogPageState,
        category: getCategoryState(
            state,
            catalogPageState.value?.categoryIdWithBrandId ?? catalogPageState.value?.categoryId,
        ).value,
        location,
        websiteName: state.context.website.name,
        websiteSettings: getSettingsCollection(state).websiteSettings,
        breadcrumbLinks: state.components.breadcrumbs.links,
        page: getCurrentPage(state),
        enableServerSideRendering: getSettingsCollection(state).websiteSettings.enableServerSideRendering,
    };
};

const mapDispatchToProps = {
    setBreadcrumbs,
    prepareCategory,
    sendCategoryPageView,
};

type Props = PageProps & ReturnType<typeof mapStateToProps> & ResolveThunks<typeof mapDispatchToProps>;

class CategoryDetailsPage extends React.Component<Props, State> {
    constructor(props: Props) {
        super(props);

        this.state = {};
    }

    UNSAFE_componentWillMount() {
        this.setMetadata();
        if (this.props.catalogPageState.value) {
            const breadcrumbLinks = this.props.breadcrumbLinks;
            if (
                breadcrumbLinks
                    ?.slice(1)
                    ?.map(o => o.children?.toString())
                    .join(",") !==
                    this.props.catalogPageState.value.breadCrumbs
                        ?.slice(1)
                        ?.map(o => o.text)
                        .join(",") ||
                (breadcrumbLinks?.length && breadcrumbLinks[0].children !== translate("Home_Breadcrumb"))
            ) {
                this.props.setBreadcrumbs({
                    links: this.props.catalogPageState.value!.breadCrumbs!.map(o => ({
                        children: o.text,
                        href: o.url,
                    })),
                });
            }
        }
    }

    componentDidMount(): void {
        if (this.props.enableServerSideRendering) {
            const {
                catalogPageState: { value: catalogPage },
            } = this.props;

            if (!catalogPage) {
                return;
            }

            this.props.prepareCategory({ catalogPage });
        }
    }

    componentDidUpdate() {
        const {
            category,
            catalogPageState: { value: catalogPage },
            breadcrumbLinks,
            prepareCategory,
        } = this.props;

        if (catalogPage && breadcrumbLinks && category && category.id !== this.state.metadataSetForId) {
            trackPageChange();
            this.setMetadata();
            prepareCategory({ catalogPage });
        }
    }

    setMetadata() {
        const { catalogPageState, category, websiteName, location, websiteSettings, sendCategoryPageView } = this.props;
        if (!catalogPageState?.value || !category || !this.props.breadcrumbLinks) {
            return;
        }

        if (!IS_SERVER_SIDE && this.state.odpEventSentFor !== catalogPageState.value.categoryId) {
            this.setState({
                odpEventSentFor: catalogPageState.value.categoryId,
            });
            sendCategoryPageView({ catalogPage: catalogPageState.value });
        }

        const { metaDescription, metaKeywords, openGraphImage, openGraphTitle, openGraphUrl, title, primaryImagePath } =
            catalogPageState.value;

        setPageMetadata(
            {
                metaDescription,
                metaKeywords,
                openGraphImage: openGraphImage || primaryImagePath,
                openGraphTitle,
                openGraphUrl,
                currentPath: location.pathname,
                canonicalPath: catalogPageState.value.canonicalPath,
                alternateLanguageUrls: catalogPageState.value.alternateLanguageUrls ?? undefined,
                title: title || category.name,
                websiteName,
                structuredPageData: websiteSettings.enableBreadcrumbStructuredData
                    ? prepareBreadcrumbStructuredPageData(this.props.breadcrumbLinks)
                    : undefined,
                jsonLdScriptId: getJsonLdScriptId(this.props.page.type),
            },
            websiteSettings,
        );

        this.setState({
            metadataSetForId: category.id,
        });
    }

    render() {
        return (
            <Page>
                <CurrentCategory>
                    <Zone contentId={this.props.id} zoneName="Content" />
                </CurrentCategory>
            </Page>
        );
    }
}

const pageModule: PageModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(CategoryDetailsPage),
    definition: {
        hasEditableUrlSegment: false,
        hasEditableTitle: true,
        supportsCategorySelection: true,
        pageType: "System",
    },
};

export default pageModule;

/**
 * @deprecated Use string literal "CategoryDetailsPage" instead of this constant.
 */
export const CategoryDetailsPageContext = "CategoryDetailsPage";
