import React, { useEffect, useState } from "react";
import { Form } from "antd";
import { Rule } from "antd/lib/form";
import { Input } from "components/Input";

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

import { to } from "utils/to";

import { MusicArtist } from "models/talent/talent-profile-module.model";

import spotifyUri, { Artist } from "spotify-uri";
import spotifyApi from "services/api/spotify.api";

import classNames from "classnames";
import "./PreReleaseLinkArtist.scss";

interface PreReleaseLinkArtistProps {
  initialArtistValue?: MusicArtist;
  index: number;
  remove: (index: number) => void;
}

export const PreReleaseLinkArtist: React.FC<PreReleaseLinkArtistProps> = ({
  initialArtistValue = { url: "" },
  index,
  remove,
}) => {
  const [artist, setArtist] = useState<MusicArtist>();
  const [artistValue, setArtistValue] = useState(initialArtistValue.url || "");

  useEffect(() => {
    handleArtistChange();
  }, []);

  const clearArtist = () => {
    setArtist(undefined);
  };

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

  const handleArtistChange = async () => {
    const artist = await getSpotifyArtist();

    if (!artist) {
      return clearArtist();
    }

    const { images } = artist;
    const [firstImage] = images;

    setArtist({
      name: artist.name,
      url: firstImage.url,
    });
  };

  const handleArtistBlur: React.ChangeEventHandler = handleArtistChange;
  const handleArtistFocus: React.ChangeEventHandler = clearArtist;
  const handleArtistNameClick: React.MouseEventHandler = clearArtist;

  const trashButton = React.useMemo(
    () => <TrashIcon className="trash--red" onClick={() => remove(index)} />,
    [remove, index]
  );

  const artistImage = React.useMemo(
    () =>
      artist && (
        <img className="prerelease--link-artist-image" src={artist.url} />
      ),
    [artist]
  );

  const displayedTextElement = React.useMemo(
    () => (
      <div
        className="prerelease--link-artist-text-wrapper"
        onClick={handleArtistNameClick}
      >
        <p className="prerelease--link-artist-text">{artist?.name}</p>
      </div>
    ),
    [artist?.name]
  );

  const inputClassNames = classNames(
    Boolean(artist) && "prerelease--link-artist-input-hidden"
  );

  const getSpotifyArtist = async () => {
    const [parseError, parsedUrl] = await to(
      () => spotifyUri.parse(artistValue) as Artist
    );
    if (parseError) {
      return;
    }

    const { id } = parsedUrl as Artist;

    const [getArtistError, artist] = await to(spotifyApi.getArtistById(id));
    if (getArtistError || artist.kind) {
      return;
    }

    return artist;
  };

  //validator for rule
  const checkValid = async () => {
    //if the artist field is emtpy, resolve without error
    if (artistValue.length === 0) {
      return Promise.resolve();
    }

    //if the artist value does not include default format
    if (!artistValue.includes("https://open.spotify.com/artist/")) {
      return Promise.reject("Please enter a valid Spotify Artist URL");
    }

    //if the url looks good, call the handler
    const artist = await getSpotifyArtist();
    if (!artist) {
      return Promise.reject("Please enter a valid Spotify Artist URL");
    }

    //if there are no errors resolve the promise
    return Promise.resolve();
  };

  //create rule to check if url is valid
  const linkInputRules: Rule[] = [{ validator: checkValid }];

  return (
    <Form.Item
      className="prerelease--link-artist-item"
      name={[index, "url"]}
      rules={linkInputRules}
    >
      <Input
        className={inputClassNames}
        value={artist?.name || artistValue}
        placeholder="https://"
        addonBefore={artistImage}
        prefix={Boolean(artist) && displayedTextElement}
        suffix={trashButton}
        onBlur={handleArtistBlur}
        onFocus={handleArtistFocus}
        onChange={handleArtistValueChange}
      />
    </Form.Item>
  );
};
