import React, { MouseEventHandler, useState } from "react";
import { Button, Form, List, Popover, Switch } from "antd";
import { SwitchChangeEventHandler } from "antd/lib/switch";
import { FormInstance, Rule } from "antd/lib/form";

import { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";

import DragDropButton from "components/Button/DragDropButton";
import { Icon } from "components/Icon";
import { Input } from "components/Input";
import { Text } from "components/Typography";

import { DspLink } from "types/dsp";

import { dspLogosMetaData } from "constants/dsp-logos";

import { toTitleCase } from "utils/casing";
import { addingHttpsPrefix } from "utils/string";

import classnames from "classnames";
import "./SmartLinkSelection.scss";

interface SmartLinkSelectionItemProps {
  dragHandleProps?: DraggableProvidedDragHandleProps;
  dragDisabled?: boolean;
  form?: FormInstance;
  item: DspLink;
  index: number;
  removeItem: () => void;
  setItem: (link: DspLink) => void;
}

export const SmartLinkSelectionItem: React.FC<SmartLinkSelectionItemProps> = ({
  dragDisabled = false,
  dragHandleProps,
  form,
  item,
  index,
  removeItem,
  setItem,
}) => {
  const [isOptionMenuVisible, setIsOptionMenuVisible] =
    useState<boolean>(false);

  const [isVisibilityToggled, setIsVisibilityToggled] =
    useState<boolean>(false);
  const [isVisible, setIsVisible] = useState<boolean>(Boolean(item.url));

  const urlRule = React.useMemo<Rule>(
    () => ({
      type: "url",
      message: "Please enter a valid URL",
    }),
    []
  );
  const requiredRule = React.useMemo<Rule>(
    () => ({
      required: true,
      message: "Please enter a URL or hide this link",
    }),
    []
  );

  const rules = React.useMemo<Rule[]>(
    () => (isVisible ? [urlRule, requiredRule] : [urlRule]),
    [isVisible, urlRule, requiredRule]
  );

  const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (
    event
  ) => {
    const url = addingHttpsPrefix(event.currentTarget.value);
    const isCurrentlyVisible = isVisibilityToggled ? isVisible : Boolean(url);

    setItem({
      ...item,
      url,
      isVisible: isCurrentlyVisible,
    });
    setIsVisible(isCurrentlyVisible);
  };

  const handleSwitchVisibilityChange: SwitchChangeEventHandler = async (
    value
  ) => {
    setIsVisibilityToggled(true);

    setItem({
      ...item,
      isVisible: value,
    });
    setIsVisible(value);

    await form?.validateFields();
  };

  const handlePopoverVisibleChange = (visible: boolean) => {
    setIsOptionMenuVisible(visible);
  };

  const handleOpenInNewTab = () => {
    if (!item.url) {
      return;
    }

    window.open(item.url);
    setIsOptionMenuVisible(false);
  };

  const handleDeleteLink: MouseEventHandler<HTMLDivElement> = () => {
    removeItem();
    setIsOptionMenuVisible(false);
  };

  const createFormItemName = (name: string) => ["links", index, name];

  const MoreOptions = React.useMemo(
    () => (
      <React.Fragment>
        <List
          data-testid="smart-link-options"
          className="module-editor__acitons"
        >
          <List.Item
            className={classnames(
              item.url?.length === 0 && "smart-link-select--options-disabled"
            )}
            onClick={handleOpenInNewTab}
          >
            <Text
              className={classnames(
                item.url?.length === 0 && "smart-link-select--options-disabled",
                "smart-link-select--options-entry"
              )}
              preset="semibold14"
            >
              Open in New Tab
            </Text>
          </List.Item>
          <List.Item onClick={handleDeleteLink}>
            <Text preset="semibold14" className="text--red">
              Delete
            </Text>
          </List.Item>
        </List>
      </React.Fragment>
    ),
    [handleDeleteLink, handleOpenInNewTab]
  );

  return (
    <div className="smart-link-select--item">
      <img
        className="smart-link-select--item-logo"
        alt={toTitleCase(item.type)}
        src={dspLogosMetaData[item?.type].bigLogoUrl}
      />

      <Form.Item
        className="smart-link-select--item-input"
        name={createFormItemName("url")}
        rules={rules}
      >
        <Input
          onChange={handleInputChange}
          value={item.url}
          placeholder="Please enter link"
        />
      </Form.Item>

      <Form.Item
        className="smart-link-select--item-switch"
        name={createFormItemName("isVisible")}
        valuePropName="checked"
      >
        <Switch checked={isVisible} onChange={handleSwitchVisibilityChange} />
      </Form.Item>

      <Popover
        visible={isOptionMenuVisible}
        placement="bottomRight"
        overlayClassName="module-editor-overlay"
        arrowContent={null}
        trigger={["click"]}
        onVisibleChange={handlePopoverVisibleChange}
        content={MoreOptions}
      >
        <Button
          className="p--0 d--flex align__items--center height--24"
          type="link"
          onClick={() => setIsOptionMenuVisible(true)}
        >
          <Icon name="more" title="more" />
        </Button>
      </Popover>

      <DragDropButton
        className="prerelease--item-head-drag"
        dragType="vertical"
        dragHandleProps={dragHandleProps}
        disabled={dragDisabled}
        onClick={(event) => event.stopPropagation()}
        data-testid="drag-button"
      />

      <Form.Item name={createFormItemName("type")}>
        <Input type="hidden" value={item.type} />
      </Form.Item>

      <Form.Item name={createFormItemName("previewUrl")}>
        <Input type="hidden" value={item.previewUrl} />
      </Form.Item>
    </div>
  );
};

export const SmartLinkSelectionItemMemo = React.memo(SmartLinkSelectionItem);
