import React, { useState, useCallback, useEffect } from "react";
import { FormInstance } from "antd/es/form/Form";

import { MultistageFormStage } from "components/MultistageForm";
import { Paragraph, Text } from "components/Typography";
import { Pill } from "components/Pill";
import { MultistageFormStageProps } from "components/MultistageForm/MultistageFormStage";

import { smartLinks } from "constants/social";

import { DspLink, DspResourceType, DspType } from "types/dsp";

import { SmartLinkSearchResult } from "../SmartLinkModal";
import { SmartLinkSelectionItems } from "./SmartLinkSelectionItems";
import { SmartLinkDropdown } from "./SmartLinkDropdownMenu";

import "./SmartLinkSelection.scss";

export const getHumanReadableTime = (seconds: number) => {
  const outputMinutes = Math.floor(seconds / 60);
  const outputSeconds = seconds % 60;

  const numberFormatOptions = {
    minimumIntegerDigits: 2,
    useGrouping: false,
  };
  const formattedMinutes = outputMinutes.toLocaleString(
    undefined,
    numberFormatOptions
  );
  const formattedSeconds = outputSeconds.toLocaleString(
    undefined,
    numberFormatOptions
  );

  return `${formattedMinutes}:${formattedSeconds}`;
};
export const formatResourceLength = (length: number, type: DspResourceType) => {
  // TODO: align server and talent enum value casing so we don't have to modify the case
  const isAlbum = type.toLowerCase() === DspResourceType.ALBUM.toLowerCase();
  return isAlbum
    ? `${length} track${length === 1 ? "" : "s"}`
    : getHumanReadableTime(length);
};

interface SmartLinkSelectionHeadProps {
  resource: SmartLinkSearchResult;
}

const SmartLinkSelectionHead: React.FC<SmartLinkSelectionHeadProps> = ({
  resource,
}) => {
  const {
    artistNames = [],
    imageUrl,
    length,
    name,
    releaseYear,
    type,
  } = resource;

  const resourceLength =
    length && type ? formatResourceLength(length, type) : "";

  return (
    <React.Fragment>
      <div className="smart-link-select--head">
        <img className="smart-link-select--head-artwork" src={imageUrl} />

        <div className="smart-link-select--metadata">
          <div>
            <Text className="smart-link-select--metadata-title">
              {name}
              <Pill className="smart-link-select--metadata-pill" text={type} />
            </Text>
          </div>

          <div>
            <Text className="smart-link-select--metadata-subtitle">
              {artistNames.join(", ")}
            </Text>

            {releaseYear && (
              <React.Fragment>
                <Text className="smart-link-select--metadata-subtitle">
                  {" "}
                  •{" "}
                </Text>
                <Text className="smart-link-select--metadata-subtitle">
                  {releaseYear}
                </Text>
              </React.Fragment>
            )}
          </div>

          <Text className="smart-link-select--metadata-duration">
            {resourceLength}
          </Text>
        </div>
      </div>
    </React.Fragment>
  );
};

interface SmartLinkSelectionProps extends MultistageFormStageProps {
  isCustomLink: boolean;
}

const defaultDspLinkTypes = [
  DspType.APPLE_MUSIC,
  DspType.SPOTIFY,
  DspType.YOUTUBE_MUSIC,
  DspType.DEEZER,
  DspType.TIDAL,
];

/**
 * Creates the DSP link structure with default links
 *
 * @param links The DSP links from which to create the structure
 * @returns The structured DSP links
 */
const buildDefaultDspLinks = (links: DspLink[] = []): DspLink[] => {
  const linkMap = links.reduce<Partial<Record<DspType, DspLink>>>(
    (map, link) => ({
      ...map,
      //add is visible support for legacy smart links
      [link.type]: {
        ...link,
        isVisible: link.isVisible ? link.isVisible : Boolean(link.url),
      },
    }),
    {}
  );

  const dspLinks = defaultDspLinkTypes.map((type) => {
    const maybeLink = linkMap[type];
    return maybeLink || { type, url: "", isVisible: false };
  });

  return dspLinks;
};

export const SmartLinkSelection: React.FC<SmartLinkSelectionProps> = ({
  accumulativeFormState: { links, searchResult },
  isCustomLink,
  ...props
}) => {
  const [form, setForm] = useState<FormInstance>();
  const [dspLinks, setDspLinks] = useState<DspLink[]>([]);

  const isMetadataAvailable = React.useMemo(
    () => !isCustomLink && searchResult,
    [isCustomLink, searchResult]
  );

  useEffect(() => {
    form?.setFieldsValue({ links: dspLinks });
  }, [dspLinks]);

  const initialValues = React.useMemo(() => {
    const defaultDspLinks = isCustomLink ? [] : buildDefaultDspLinks(links);
    const initialDspLinks = links || defaultDspLinks;
    setDspLinks(initialDspLinks);

    return {
      links: initialDspLinks,
    };
  }, []);

  const handleClickTag = useCallback(
    (key: string) => {
      const smartLinkItems = smartLinks.map((link) => link.items).flat();
      const link = smartLinkItems.find((item) => item.key === key);

      if (!link) {
        return;
      }

      const createDspLink = {
        type: link.key,
        url: "",
        isVisible: false,
      };

      setDspLinks((prevLinks) => [...prevLinks, createDspLink]);
    },
    [form, dspLinks]
  );

  const onFinish = async (values: any) => {
    if (!form) {
      return;
    }

    await form?.validateFields();
    return values;
  };

  return (
    <MultistageFormStage
      initialValues={initialValues}
      onFinish={onFinish}
      setForm={setForm}
      validateTrigger="onSubmit"
      {...props}
    >
      <div className="smart-link-select--container">
        <Paragraph className="smart-link-select--title" preset="semibold18">
          Select Services
        </Paragraph>
        {isMetadataAvailable && (
          <SmartLinkSelectionHead resource={searchResult} />
        )}
      </div>

      <SmartLinkSelectionItems
        form={form}
        dspLinks={dspLinks}
        setDspLinks={setDspLinks}
      />

      <div className="smart-link-select--link-menu">
        <SmartLinkDropdown
          inModal={true}
          links={dspLinks}
          menuItems={smartLinks}
          onClickMenu={handleClickTag}
        />
      </div>
    </MultistageFormStage>
  );
};
