import clsx from "clsx";
import moment from "moment";
import Link from "next/link";
import { useMemo } from "react";
import { useRouter } from "next/router";
import Tab from "@mui/base/TabUnstyled";
import Tabs from "@mui/base/TabsUnstyled";
import TabsList from "@mui/base/TabsListUnstyled";
import TabPanel from "@mui/base/TabPanelUnstyled";
import type { GetServerSideProps, NextPage } from "next";

import { get } from "libs/http";
import MyError from "pages/_error";
import useGet from "libs/hooks/useGet";
import errorProps from "libs/errorProps";
import useStore from "libs/hooks/useStore";
import NovelCover from "components/NovelCover";
import { SeoHead, SeoHeadConfig } from "components/SeoHead";

import styles from "styles/novel-info.module.scss";

import { useHistory } from "libs/hooks/useDbItem";

interface NovelPageProps {
  detail?: Detail;
  chapters?: ChapterListData;
  statusCode?: number;
}

function mergeHistory(
  detail: Detail,
  chapters: ChapterListData["chapters"],
  history?: HistoryItem
) {
  return {
    uri: detail.uri,
    readTime: history?.readTime ?? new Date(),
    img: detail.img,
    name: detail.name,
    status: detail.status,
    chapterUri: chapters[0].uri,
    chapterName: chapters[0].name,
    chapterCount: chapters.length,
    chapterIndex: history?.chapterIndex ?? 1,
    isReading: history?.isReading ?? 0,
    isFavorite: 1,
  } as HistoryItem;
}

const Novel: NextPage<NovelPageProps> = (props) => {
  const { statusCode } = props;
  const { siteConfig } = useStore();
  const { query } = useRouter();
  const [history, putHistoryItem, delHistoryItem] = useHistory(
    query.slug as string
  );

  const { data: { data: detail } = { data: null } } = useGet<Detail>(
    `/api/novel/${query.slug}`
  );

  const { data: { data: chapters } = { data: null } } = useGet<ChapterListData>(
    `/api/novel/${query.slug}/chapters`
  );

  const seoConfig: SeoHeadConfig = useMemo(() => {
    const keys = detail?.genres.map((item) => item.name).join(", ");
    const url = `https://${siteConfig.host}/novel/${query.slug}`;

    return {
      title: `${detail?.name} - ${siteConfig.siteName}`,
      description: `${detail?.name} is ${keys} web novel. Read ${detail?.name} novel written by the author ${detail?.author} on ${siteConfig.siteName} for Free.`,
      keywords: `${[
        detail?.name,
        detail?.author,
        detail?.other_name,
        keys,
        siteConfig.keywords,
        siteConfig.siteName,
      ]
        .filter((item) => item)
        .join(", ")}`,
      url,
      canonical: url,
      siteName: siteConfig.siteName,
      img: detail?.img,
      jsonLd: JSON.stringify([
        {
          "@context": "https://schema.org",
          "@type": "Book",
          mainEntityOfPage: `https://${siteConfig.host}/novel/${query.slug}`,
          headline: detail?.name,
          name: detail?.name,
          genre: detail?.genres[0].name,
          image: {
            "@type": "ImageObject",
            url: detail?.img,
          },
          bookFormat: "https://schema.org/EBook",
          datePublished: detail?.create_time,
          dateModified: detail?.update_time,
          author: {
            "@type": "Person",
            name: detail?.author,
          },
          copyrightHolder: detail?.author,
          publisher: {
            "@type": "Organization",
            name: siteConfig.siteName,
            logo: {
              "@type": "ImageObject",
              url: `https://${siteConfig.host}/favicon-32x32.png`,
            },
          },
          description: detail?.desc,
          // aggregateRating: {
          //   "@type": "AggregateRating",
          //   bestRating: "5.0",
          //   ratingValue: "4.62",
          //   ratingCount: "159",
          // },
          potentialAction: {
            "@type": "ReadAction",
            target: {
              "@type": "EntryPoint",
              urlTemplate: `https://${siteConfig.host}/novel/${chapters?.chapters[0].uri}`,
            },
          },
        },
        {
          "@context": "https://schema.org",
          "@type": "BreadcrumbList",
          itemListElement: [
            {
              "@type": "ListItem",
              position: 1,
              name: "Home",
              item: `https://${siteConfig.host}`,
            },
            {
              "@type": "ListItem",
              position: 2,
              name: detail?.genres[0].name,
              item: `https://${siteConfig.host}/novels/${detail?.genres[0].uri}`,
            },
            {
              "@type": "ListItem",
              position: 3,
              name: `${detail?.name || ""}`,
              item: `https://${siteConfig.host}/novel/${query.slug}`,
            },
          ],
        },
        ...siteConfig.jsonLd,
      ]),
    };
  }, [
    chapters?.chapters,
    detail?.author,
    detail?.create_time,
    detail?.desc,
    detail?.genres,
    detail?.img,
    detail?.name,
    detail?.other_name,
    detail?.update_time,
    query.slug,
    siteConfig.host,
    siteConfig.jsonLd,
    siteConfig.keywords,
    siteConfig.siteName,
  ]);

  const chapterLists = useMemo(() => {
    if (!chapters || !chapters.chapters.length) return [];
    const len = Math.ceil(chapters.chapters.length / 100);
    const list = [];
    for (let i = 0; i < len; i++) {
      list.push({
        title: `${i * 100 + 1}-${(i + 1) * 100}`,
        list: chapters.chapters.slice(
          i * 100,
          Math.min(chapters.chapters.length, (i + 1) * 100)
        ),
      });
    }
    return list;
  }, [chapters]);

  const handleTogleFavorite = () => {
    if (!detail || !chapters) return;
    const data = mergeHistory(detail, chapters.chapters, history);

    if (history?.isFavorite === 1) {
      const isReading = history?.isReading === 1;

      if (isReading) data.isFavorite = 0;

      isReading ? putHistoryItem(data) : delHistoryItem(detail.uri);
    } else {
      data.isFavorite = 1;
      putHistoryItem(data);
    }
  };

  if (statusCode) {
    return <MyError statusCode={statusCode} />;
  }

  if (!detail || !chapters) {
    return null;
  }
  return (
    <main>
      <SeoHead seoConfig={seoConfig} />
      <div
        className={styles["novel-wrap"]}
        style={{
          backgroundImage: `url(${detail?.img})`,
        }}
      >
        <div className={styles["novel-container"]}>
          <div className="text-sm py-4 breadcrumbs">
            <ul>
              <li>
                <Link href="/" title="Home">
                  <svg className="w-5 h-5 mr-1 -mt-1">
                    <use xlinkHref="/icons.svg#home"></use>
                  </svg>
                  Home
                </Link>
              </li>
              {detail.genres && detail.genres.length > 0 ? (
                <li>
                  <Link
                    title={detail.genres[0].name}
                    href={`/novels/${detail.genres[0].uri}`}
                  >
                    {detail.genres[0].name}
                  </Link>
                </li>
              ) : null}
              <li>{detail.name}</li>
            </ul>
          </div>
          <div className={styles["novel-info"]}>
            <NovelCover
              className={styles["novel-info-cover"]}
              component="div"
              alt={detail.name}
              src={detail.img}
            />
            <div className={styles["nove-info-body"]}>
              <h1>{detail.name}</h1>
              <h2>
                <strong>
                  <svg>
                    <title>Chapters: </title>
                    <use xlinkHref="/icons.svg#chapter"></use>
                  </svg>
                  <span>{chapters.chapters.length} Chapters</span>
                </strong>
                <strong>
                  <svg>
                    <title>Author: </title>
                    <use xlinkHref="/icons.svg#person"></use>
                  </svg>
                  <span>{detail.author}</span>
                </strong>
                <strong>
                  <svg>
                    <title>Status: </title>
                    <use xlinkHref="/icons.svg#update"></use>
                  </svg>
                  <span>{detail.status}</span>
                </strong>
                {/* <strong>
                  <svg>
                    <use xlinkHref="/icons.svg#eye"></use>
                  </svg>
                  <span>0 Views</span>
                </strong> */}
              </h2>
              <div className={styles["btns"]}>
                <Link
                  href={`/novel/${
                    history?.isReading
                      ? history?.chapterUri
                      : chapters.chapters[0].uri
                  }`}
                  className={clsx(styles["button"], styles["button-reading"])}
                >
                  <strong>
                    {history?.isReading ? "Continue Reading" : "Start Reading"}
                  </strong>
                  {history?.isReading ? (
                    <small>{history.chapterName}</small>
                  ) : null}
                </Link>
                <button
                  className={styles["button"]}
                  onClick={handleTogleFavorite}
                >
                  <strong>
                    <svg>
                      <use
                        xlinkHref={`/icons.svg#${
                          history && history.isFavorite
                            ? "favorite"
                            : "unfavorite"
                        }`}
                      ></use>
                    </svg>
                    <span>
                      {history && history.isFavorite
                        ? "In Library"
                        : "Add to Library"}
                    </span>
                  </strong>
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
      <Tabs
        defaultValue={0}
        className={clsx(styles["novel-page"], "bg-paper", "py-3")}
      >
        <TabsList className={clsx("tabs", styles["novel-tabs"])}>
          <Tab value={0} className="tab">
            About
          </Tab>
          <Tab value={1} className="tab">
            Chapters
          </Tab>
        </TabsList>
        <TabPanel value={0}>
          <h2 className="sub-title">Genres</h2>
          <div className="tags">
            {detail.genres.map((item) => (
              <Link
                title={item.name}
                href={`/novels/${item.uri}`}
                className="tag"
                key={item.uri}
              >
                {item.name}
              </Link>
            ))}
          </div>

          <h2 className="sub-title">Synopsis</h2>
          <div
            className={styles["novel-text"]}
            dangerouslySetInnerHTML={{ __html: detail.desc }}
          />
        </TabPanel>
        <TabPanel value={1}>
          <h3 className="sub-title">{detail.name} Chapters</h3>
          <Tabs defaultValue={0}>
            <TabsList className={clsx("tabs", styles["novel-tabs"], styles["chapter-tabs"])}>
              {chapterLists.map((chapter, idx) => (
                <Tab value={idx} className="tab" key={chapter.title}>
                  {chapter.title}
                </Tab>
              ))}
            </TabsList>
            {chapterLists.map((chapter, idx) => (
              <TabPanel
                value={idx}
                component="ol"
                start={idx * 100 + 1}
                key={chapter.title}
                className={styles["chapter-list"]}
              >
                {chapter.list.map((item) => {
                  const dateFormNow = moment(item.create_time).fromNow(true);
                  return (
                    <li key={item.id}>
                      <Link href={`/novel/${item.uri}`} title={item.name}>
                        {/* <i>{idx * 100 + i + 1}</i> */}
                        <strong>{item.name}</strong>
                        <time
                          title={`Create at ${dateFormNow} ago`}
                          dateTime={item.create_time}
                        >
                          {dateFormNow}
                        </time>
                      </Link>
                    </li>
                  );
                })}
              </TabPanel>
            ))}
          </Tabs>
        </TabPanel>
      </Tabs>
    </main>
  );
};

export const getServerSideProps: GetServerSideProps<
  Docs,
  { slug: string }
> = async (context) => {
  if (!context.params) {
    return errorProps(context);
  }
  try {
    const { slug } = context.params;
    const [detail, chapters] = await Promise.all([
      get<Detail>(`/api/novel/${slug}`),
      get<ChapterListData>(`/api/novel/${slug}/chapters`),
    ]);

    if (!detail || !detail.data.id) {
      return errorProps(context);
    }

    return {
      props: {
        fallback: {
          [`/api/novel/${slug}`]: detail,
          [`/api/novel/${slug}/chapters`]: chapters,
        },
      },
    };
  } catch (e) {
    return errorProps(context, 500);
  }
};

export default Novel;
