import { Fragment, useCallback, useMemo } from "react";
import { Chip } from "components/Chip";
import { Img } from "components/Img";
import { Button } from "components/Inputs/Button";
import { RecorderChip } from "components/RecorderChip";
import { ToolTip } from "components/ToolTip";
import { GetLibraryItemScansQuery } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { getAssetFilename, getAssetURL, ImageQuality } from "helpers/img";
import { isInteger } from "helpers/numbers";
import {
  filterHasAttributes,
  getStatusDescription,
  isDefined,
  isDefinedAndNotEmpty,
} from "helpers/others";
import { useSmartLanguage } from "hooks/useSmartLanguage";

/*
 *                                        ╭─────────────╮
 * ───────────────────────────────────────╯  COMPONENT  ╰───────────────────────────────────────────
 */

interface Props {
  openLightBox: (images: string[], index?: number) => void;
  scanSet: NonNullable<
    NonNullable<
      NonNullable<
        NonNullable<
          NonNullable<
            GetLibraryItemScansQuery["libraryItems"]
          >["data"][number]["attributes"]
        >["contents"]
      >["data"][number]["attributes"]
    >["scan_set"]
  >;
  id: string;
  title: string;
  languages: AppStaticProps["languages"];
  langui: AppStaticProps["langui"];
  content: NonNullable<
    NonNullable<
      NonNullable<
        NonNullable<
          GetLibraryItemScansQuery["libraryItems"]
        >["data"][number]["attributes"]
      >["contents"]
    >["data"][number]["attributes"]
  >["content"];
}

// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─

export const ScanSet = ({
  openLightBox,
  scanSet,
  id,
  title,
  languages,
  langui,
  content,
}: Props): JSX.Element => {
  const [selectedScan, LanguageSwitcher, languageSwitcherProps] =
    useSmartLanguage({
      items: scanSet,
      languages: languages,
      languageExtractor: useCallback(
        (item: NonNullable<Props["scanSet"][number]>) =>
          item.language?.data?.attributes?.code,
        []
      ),
      transform: useCallback((item: NonNullable<Props["scanSet"][number]>) => {
        item.pages?.data.sort((a, b) => {
          if (
            a.attributes &&
            b.attributes &&
            isDefinedAndNotEmpty(a.attributes.url) &&
            isDefinedAndNotEmpty(b.attributes.url)
          ) {
            let aName = getAssetFilename(a.attributes.url);
            let bName = getAssetFilename(b.attributes.url);

            /*
             * If the number is a succession of 0s, make the number
             * incrementally smaller than 0 (i.e: 00 becomes -1)
             */
            if (aName.replaceAll("0", "").length === 0) {
              aName = (1 - aName.length).toString(10);
            }
            if (bName.replaceAll("0", "").length === 0) {
              bName = (1 - bName.length).toString(10);
            }

            if (isInteger(aName) && isInteger(bName)) {
              return parseInt(aName, 10) - parseInt(bName, 10);
            }
            return a.attributes.url.localeCompare(b.attributes.url);
          }
          return 0;
        });
        return item;
      }, []),
    });

  const pages = useMemo(
    () => filterHasAttributes(selectedScan?.pages?.data, ["attributes"]),
    [selectedScan]
  );

  return (
    <>
      {selectedScan && isDefined(pages) && (
        <div>
          <div
            className="flex flex-row flex-wrap place-items-center
          gap-6 pt-10 text-base first-of-type:pt-0"
          >
            <h2 id={id} className="text-2xl">
              {title}
            </h2>

            <Chip
              text={
                selectedScan.language?.data?.attributes?.code ===
                selectedScan.source_language?.data?.attributes?.code
                  ? langui.scan ?? "Scan"
                  : langui.scanlation ?? "Scanlation"
              }
            />
          </div>

          <div className="flex flex-row flex-wrap place-items-center gap-4 pb-6">
            {content?.data?.attributes &&
              isDefinedAndNotEmpty(content.data.attributes.slug) && (
                <Button
                  href={`/contents/${content.data.attributes.slug}`}
                  text={langui.open_content}
                />
              )}

            {languageSwitcherProps.locales.size > 1 && (
              <LanguageSwitcher {...languageSwitcherProps} />
            )}

            <div className="grid place-content-center place-items-center">
              <p className="font-headers font-bold">{langui.status}:</p>
              <ToolTip
                content={getStatusDescription(selectedScan.status, langui)}
                maxWidth={"20rem"}
              >
                <Chip text={selectedScan.status} />
              </ToolTip>
            </div>

            {selectedScan.scanners && selectedScan.scanners.data.length > 0 && (
              <div>
                <p className="font-headers font-bold">{langui.scanners}:</p>
                <div className="grid place-content-center place-items-center gap-2">
                  {filterHasAttributes(selectedScan.scanners.data, [
                    "id",
                    "attributes",
                  ] as const).map((scanner) => (
                    <Fragment key={scanner.id}>
                      <RecorderChip
                        langui={langui}
                        recorder={scanner.attributes}
                      />
                    </Fragment>
                  ))}
                </div>
              </div>
            )}

            {selectedScan.cleaners && selectedScan.cleaners.data.length > 0 && (
              <div>
                <p className="font-headers font-bold">{langui.cleaners}:</p>
                <div className="grid place-content-center place-items-center gap-2">
                  {filterHasAttributes(selectedScan.cleaners.data, [
                    "id",
                    "attributes",
                  ] as const).map((cleaner) => (
                    <Fragment key={cleaner.id}>
                      <RecorderChip
                        langui={langui}
                        recorder={cleaner.attributes}
                      />
                    </Fragment>
                  ))}
                </div>
              </div>
            )}

            {selectedScan.typesetters &&
              selectedScan.typesetters.data.length > 0 && (
                <div>
                  <p className="font-headers font-bold">
                    {langui.typesetters}:
                  </p>
                  <div className="grid place-content-center place-items-center gap-2">
                    {filterHasAttributes(selectedScan.typesetters.data, [
                      "id",
                      "attributes",
                    ] as const).map((typesetter) => (
                      <Fragment key={typesetter.id}>
                        <RecorderChip
                          langui={langui}
                          recorder={typesetter.attributes}
                        />
                      </Fragment>
                    ))}
                  </div>
                </div>
              )}

            {isDefinedAndNotEmpty(selectedScan.notes) && (
              <ToolTip content={selectedScan.notes}>
                <Chip text={langui.notes ?? "Notes"} />
              </ToolTip>
            )}
          </div>

          <div
            className="grid items-end gap-8 border-b-[3px] border-dotted pb-12 last-of-type:border-0
             desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] mobile:grid-cols-2"
          >
            {pages.map((page, index) => (
              <div
                key={page.id}
                className="cursor-pointer transition-transform
                drop-shadow-shade-lg hover:scale-[1.02]"
                onClick={() => {
                  const images = pages.map((image) =>
                    getAssetURL(image.attributes.url, ImageQuality.Large)
                  );
                  openLightBox(images, index);
                }}
              >
                <Img src={page.attributes} quality={ImageQuality.Small} />
              </div>
            ))}
          </div>
        </div>
      )}
    </>
  );
};