import React, { useState, useEffect, useCallback } from "react"
import chunk from "lodash/chunk"
import groupBy from "lodash/groupBy"
import compact from "lodash/compact"

import Container from "@/components/container"
import cls from "classnames"
import PracticeList from "./practice-list"
import PracticeTagSelect from "./practice-tag-select"
import MobilePracticeTagSelect from "./mobile-practice-select"
import { Icon } from ".."
import t from "@/constants/wording"
import { STORAGE_KEY } from "@/constants/common"

import * as styles from "./index.module.scss"
import * as queryString from "querystring"

const pageSize = 12
type IProps = {
  list: PracticeType[]
}

const PracticeBody: React.FC<IProps> = ({ list }) => {
  const [listData, setListData] = useState<PracticeType[]>([])
  const [pagesListData, setPagesListData] = useState<Array<PracticeType[]>>([
    [],
  ])
  const [curPage, setCurPage] = useState(0)
  const [isLoadMore, setIsLoadMore] = useState(false)

  const setInitialPageData = (listData: PracticeType[], pageNum = 0) => {
    const pagesListData = chunk(listData, pageSize) as Array<PracticeType[]>
    setPagesListData(pagesListData)
    setListData(pagesListData[pageNum] as PracticeType[])
    setIsLoadMore(listData.length > pageSize)
  }

  const tagsGroup = groupBy(
    list.reduce((acc: string[], item) => {
      return [...acc, ...compact(item.tags)]
    }, [])
  )
  const tagsAndCount = Object.keys(tagsGroup).reduce(
    (final, key) => {
      final[key] = tagsGroup[key].length
      return final
    },
    { [t("all")]: list.length }
  )

  const tagsJointChar = ","
  const [checkedTags, setCheckedTags] = useState([""])

  function queryUrl() {
    const { tag } = queryString.parse(
      typeof window !== "undefined"
        ? window.location.search.replace("?", "")
        : ""
    ) as { [key: string]: string }
    const tagsStr = tag || t("all")
    sessionStorage.setItem(STORAGE_KEY.PRACTICE, tagsStr)
    const tagsArr = tagsStr.split(tagsJointChar)
    submitCheck(tagsArr)
  }

  useEffect(() => {
    queryUrl()
  }, [])

  const loadMore = useCallback(
    (i: number) => {
      setCurPage(i)
      const newListData = [...listData, ...pagesListData[i]]
      setListData(newListData)
      setIsLoadMore(i < pagesListData.length - 1)
    },
    [pagesListData, curPage]
  )
  const selectTag = useCallback(
    (tag: string) => {
      if (checkedTags.includes(tag) && checkedTags.length === 1) {
        return
      }
      setCurPage(0)
      const filteredList = list
        .filter(item => item.tags.includes(tag))
        .sort((a, b) => a.order - b.order)
      setInitialPageData(filteredList)
      setCheckedTags([tag])
    },
    [checkedTags]
  )

  const filterTag = (tags: string[]) => {
    setCurPage(0)
    if (tags.includes(t("all"))) {
      return setInitialPageData(list)
    }
    const filteredList = list
      .filter(item => item.tags.some(i => tags.includes(i)))
      .sort((a, b) => a.order - b.order)
    setInitialPageData(filteredList)
  }

  const check = useCallback(
    (tag: string, isChecked: boolean) => {
      let newCheckedTags = []
      if (isChecked && tag === t("all")) {
        newCheckedTags = [t("all")]
      } else {
        newCheckedTags = isChecked
          ? [...checkedTags.filter(i => i !== t("all")), tag]
          : checkedTags.filter(item => tag !== item)
      }

      setCheckedTags(newCheckedTags)
      sessionStorage.setItem(
        STORAGE_KEY.PRACTICE,
        newCheckedTags.join(tagsJointChar)
      )

      window.history.replaceState(
        null,
        "",
        "?tag=" + newCheckedTags.join(tagsJointChar)
      )

      return newCheckedTags
    },
    [checkedTags]
  )

  const checkHandle = useCallback(
    (tag: string, isChecked: boolean) => {
      filterTag(check(tag, isChecked))
    },
    [checkedTags]
  )

  const submitCheck = useCallback((tags: string[]) => {
    setCheckedTags([...tags])
    filterTag([...tags])
  }, [])

  return (
    <section id="practice">
      <Container>
        <div className={cls(styles.container, "columns is-variable is-4")}>
          <div
            className={cls(
              styles.filterContainer,
              "column is-3-widescreen is-4-tablet py-0"
            )}
          >
            <PracticeTagSelect
              tagsAndCount={tagsAndCount}
              checkedTags={checkedTags}
              checkHandle={checkHandle}
            />
          </div>

          <div className={cls(styles.listContainer, "column py-0")}>
            <div className={cls(styles.mobileFilterContainer)}>
              <MobilePracticeTagSelect
                tagsAndCount={tagsAndCount}
                checkedTags={checkedTags}
                submitCheck={submitCheck}
              />
            </div>
            <PracticeList list={listData} select={selectTag} />
            <div className={styles.paginationContainer}>
              {isLoadMore && (
                <div className={styles.moreButton}>
                  <button
                    className="button is-medium is-ghost is-primary"
                    onClick={() => loadMore(curPage + 1)}
                  >
                    <span>{t("expand to show more data")}</span>
                    <span className="icon">
                      <Icon name="chevron-right" />
                    </span>
                  </button>
                </div>
              )}
            </div>
          </div>
        </div>
      </Container>
    </section>
  )
}

export default PracticeBody
