import React, { useCallback, useState } from "react";
import { Col, Form, Row, Tooltip } from "antd";

import { MediaUpload } from "redux/Common/types";
import { useTypedSelector } from "redux/rootReducer";

import { SmartLinkArtistField } from "../SmartLinkArtistField";

import { MultistageFormStage, warnAndThrow } from "components/MultistageForm";
import { Paragraph } from "components/Typography";
import { Icon } from "components/Icon";
import { Input } from "components/Input";
import CoverUpload from "components/CoverUpload";
import { MultistageFormStageProps } from "components/MultistageForm/MultistageFormStage";

import { ReactComponent as TrashIcon } from "icons/trash.svg";
import { ReactComponent as LinkIcon } from "icons/link.svg";

import "../SmartLinks.scss";
import "./SmartLinkCustomization.scss";
import {
  MusicItem,
  TalentModuleMixItem,
} from "models/talent/talent-profile-module.model";
import { Rule } from "antd/lib/form";
import { profileUrl } from "utils/url";
import { selectUserData } from "redux/User/selector";
import copyToClipboard from "copy-to-clipboard";

export const buildArtists = (artistNames: string[] = [""]) =>
  artistNames.map((name) => ({ name }));
export const buildUrlPath = (songName: string) =>
  songName
    .replace(/[^a-zA-Z0-9 ]/g, "")
    .replace(/ /g, "-")
    .toLowerCase();

const isMusicItem = (item: TalentModuleMixItem): item is MusicItem => {
  return (
    item.hasOwnProperty("links") && !item.hasOwnProperty("activeLatestPodcast")
  );
};

export const SmartLinkCustomization: React.FC<MultistageFormStageProps> = ({
  accumulativeFormState: { searchResult = {}, urlSlug: initialUrlSlug },
  ...props
}) => {
  const user = useTypedSelector(selectUserData);

  /**
   * Gets the URL slugs for music items, excluding for the current music item
   */
  const otherMusicModuleSlugs = useTypedSelector((state) => {
    const allModules = state.userState.talentProfileModules || [];
    const allItems = allModules.flatMap((module) => module.items);
    const musicItems = allItems.filter(isMusicItem);
    const otherMusicItems = musicItems.filter(
      (item) => item.urlSlug !== initialUrlSlug
    );

    return otherMusicItems.map(
      (item) => item.urlSlug || buildUrlPath(item.metadata.name)
    );
  });

  const linkPrefix = React.useMemo(
    () => `${profileUrl}/music/`,
    [user?.username, user?.firstName, user?.lastName]
  );

  const [photo, setPhoto] = useState<MediaUpload>({
    url: searchResult.imageUrl,
  });
  const [urlSlug, setUrlSlug] = useState("");
  const [isCopyTooltipVisible, setIsCopyTooltipVisible] = useState(false);

  const initialValues = React.useMemo(() => {
    const { artistNames, ...values } = searchResult;
    const artists = buildArtists(artistNames);

    const defaultSlug = searchResult.name
      ? buildUrlPath(searchResult.name)
      : "";
    const slug = initialUrlSlug || defaultSlug;
    setUrlSlug(slug);

    return {
      ...values,
      urlSlug: slug,
      artists,
    };
  }, []);

  const handleUploadSuccess = (photo: MediaUpload) => {
    setPhoto(photo);
  };

  const removePhoto = () => {
    setPhoto({});
  };

  const handleUrlPathChange: React.ChangeEventHandler<HTMLInputElement> = (
    event
  ) => {
    setUrlSlug(event.target.value);
  };

  const handleLinkClick = () => {
    //Doesn't work on http: navigator.clipboard.writeText(`${linkPrefix}${urlSlug}`);
    navigator.clipboard.writeText(`${linkPrefix}${urlSlug}`);

    setIsCopyTooltipVisible(true);
    setTimeout(() => setIsCopyTooltipVisible(false), 2000);
  };

  const handleFinish = (values: any) => {
    if (!photo.url) {
      warnAndThrow("No image selected");
    }

    const imageUrl = photo.url;

    return {
      ...values,
      imageUrl,
    };
  };

  const validateSlug = useCallback(
    async (_, value: string) => {
      if (otherMusicModuleSlugs.includes(value)) {
        throw new Error("URL slug is taken by an existing music resource");
      }
    },
    [otherMusicModuleSlugs]
  );
  const titleRules = [{ required: true, message: "Title is required" }];
  const urlSlugRules: Rule[] = [
    { required: true, message: "URL slug is required" },
    {
      pattern: new RegExp(/^[a-zA-Z0-9-]+$/),
      message: "URL slug can only contain numbers, letters and dashes",
    },
    {
      message: "URL slug is taken by an existing music resource",
      validator: validateSlug,
    },
  ];

  return (
    <MultistageFormStage
      initialValues={initialValues}
      onFinish={handleFinish}
      validateTrigger="onSubmit"
      {...props}
    >
      <Paragraph className="smart-link--title" preset="semibold18">
        Customize Link
      </Paragraph>

      <div className="smart-link--customize-artwork">
        <CoverUpload
          photo={photo}
          onUploadSuccess={handleUploadSuccess}
          onRemove={removePhoto}
          data-testid="smart-link--customize-cover-upload"
        />
      </div>

      <Form.Item
        label="Title"
        labelAlign="left"
        colon={false}
        requiredMark="optional"
        name="name"
        rules={titleRules}
      >
        <Input placeholder="e.g. Love at First Sight" />
      </Form.Item>

      <Form.List name="artists">
        {(fields, { add, remove }) => (
          <div className="smart-link--artists">
            <Paragraph className="smart-link--artists-label">
              Artist(s)
            </Paragraph>

            {fields.map(({ key, ...props }, index) => {
              const removeButton =
                index > 0 ? (
                  <TrashIcon
                    title="remove-artist"
                    className="trash--red"
                    onClick={() => remove(index)}
                  />
                ) : null;

              return (
                <SmartLinkArtistField
                  key={key}
                  index={index}
                  removeButton={removeButton}
                  {...props}
                />
              );
            })}

            <Row className="smart-link--artists-add" gutter={8} align="middle">
              {/* This cannot be simplified to `onClick={add}`, or it will post unwanted parameters */}
              <Col onClick={() => add()} className="height--32">
                <Icon name="add-blue" />
              </Col>

              <Col onClick={() => add()}>
                <Paragraph className="text--blue m__b--0" preset="semibold18">
                  Add artist
                </Paragraph>
              </Col>
            </Row>
          </div>
        )}
      </Form.List>

      <Form.Item
        label="Custom URL"
        labelAlign="left"
        name="urlSlug"
        requiredMark="optional"
        colon={false}
        className="smart-link--url"
        rules={urlSlugRules}
      >
        <Input
          addonBefore={linkPrefix}
          className="smart-link--url-input"
          value={urlSlug}
          suffix={
            <Tooltip
              visible={isCopyTooltipVisible}
              placement="top"
              title="Copied!"
            >
              <LinkIcon
                className="smart-link--url-copy"
                onClick={handleLinkClick}
                title="copy-url"
              />
            </Tooltip>
          }
          placeholder="e.g. love-at-first-sight"
          onChange={handleUrlPathChange}
        />
      </Form.Item>
    </MultistageFormStage>
  );
};
