import { SWRConfig } from "swr";
import Script from "next/script";
import type { NextPage } from "next";
import { useRouter } from "next/router";
import type { AppProps } from "next/app";
import App, { AppContext } from "next/app";
import { ReactElement, ReactNode, useEffect } from "react";

import { Context } from "../libs/context";
import Layout from "../components/common/Layout";

import "../styles/globals.scss";
import { pageview } from "../libs/gtag";
import { GA_TRACKING_ID } from "../libs/config";
import { get } from "../utils/http";

export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
  getLayout?: (page: ReactElement) => ReactNode;
};

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout;
  pageProps: {
    fallback?: {
      [key: string]: any;
    };
    [key: string]: any;
  };
};

const MyApp = ({ Component, pageProps }: AppPropsWithLayout) => {
  const { fallback, genre, ...otherProps } = pageProps;
  const router = useRouter();

  useEffect(() => {
    const handleRouteChange = (url: string) => {
      pageview(url);
    };
    router.events.on("routeChangeComplete", handleRouteChange);
    router.events.on("hashChangeComplete", handleRouteChange);
    return () => {
      router.events.off("routeChangeComplete", handleRouteChange);
      router.events.off("hashChangeComplete", handleRouteChange);
    };
  }, [router.events]);

  return (
    <>
      <Script
        strategy="afterInteractive"
        src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
      />
      <Context.Provider value={{ genre }}>
        <SWRConfig value={{ fallback, revalidateIfStale: false }}>
          {Component.getLayout ? (
            Component.getLayout(<Component {...otherProps} />)
          ) : (
            <Layout>
              <Component {...otherProps} />
            </Layout>
          )}
        </SWRConfig>
      </Context.Provider>
    </>
  );
};

MyApp.getInitialProps = async function (context: AppContext) {
  App.getInitialProps(context);

  const { data } = await get("/api/genre/list");

  return {
    pageProps: { genre: data },
  };
};

export default MyApp;
