import {
  DataCaptureMethod,
  InlineMessage,
  MultiSelect,
} from "@komi-app/components";
import { Checkbox, Card, Col, Row, Button, Typography } from "antd";
import DragDropButton from "components/Button/DragDropButton";
import DragDropContext from "components/DragDropContext";
import { Icon } from "components/Icon";
import PortalComponent from "components/PortalComponent/PortalComponent";
import React, { useEffect, useState } from "react";
import "../DataCaptureCreationModal.scss";
import StepLayout from "./StepLayout";
import {
  additionalContactMethodLocation,
  countryDropdownOption,
  DataCaptureFormField,
  DCAFormStepsProps,
  locationDropdownOptions,
} from "./schemas";

import {
  DataCaptureField,
  DataCaptureLocationLevel,
} from "@komi-app/shared-types";

export interface DcaContactMethodsStepProps {
  values: DCAFormStepsProps;
  patchValues: (patch: Partial<DCAFormStepsProps>) => void;
  Preview: React.ReactNode;
  onPrevious: () => void;
  onSubmit: () => void;
}

const DcaContactMethodsStep = ({
  values,
  patchValues,
  Preview,
  onPrevious,
  onSubmit,
}: DcaContactMethodsStepProps) => {
  //Set country as default
  const [locationLevel, setLocationLevel] = useState<{
    label: string;
    value: DataCaptureLocationLevel;
  }>(countryDropdownOption);

  const onDropContactMethods = (methods: DataCaptureMethod[]) => {
    methods.forEach((element, index) => {
      element.orderIndex = index;
    });
    patchValues({ contactMethods: methods });
  };

  const onContactMethodVisibleChanged = (index: number) => {
    const updated = values.contactMethods.map((obj) => Object.assign({}, obj));
    updated[index].isVisible = !updated[index].isVisible;
    patchValues({ contactMethods: updated });
  };

  // Additional
  const onAdditionalContactMethodRequiredChanged = (index: number) => {
    const updated = values.additionalContactMethods.map((obj) =>
      Object.assign({}, obj),
    );
    updated[index].isRequired = !updated[index].isRequired;
    patchValues({ additionalContactMethods: updated });
  };

  const onAdditionalContactMethodVisibleChanged = (index: number) => {
    const updated = values.additionalContactMethods.map((obj) =>
      Object.assign({}, obj),
    );
    updated[index].isVisible = !updated[index].isVisible;
    patchValues({ additionalContactMethods: updated });
  };

  const onDropAdditionalContactMethods = (methods: DataCaptureFormField[]) => {
    patchValues({ additionalContactMethods: methods });
  };

  /**
   * Default definition of function outside FF.
   * These need to be defined when FF is off.
   * @param changeData
   * @param index
   */
  let onLocationLevelSelectionChange = (
    changeData: { label: string; value: DataCaptureLocationLevel },
    index: number,
  ) => {};
  let getLocationDropdown = (
    linkIndex: number,
    item: DataCaptureFormField,
  ) => {};
  onLocationLevelSelectionChange = (
    changeData: { label: string; value: DataCaptureLocationLevel },
    index: number,
  ) => {
    const updated = values.additionalContactMethods.map((obj) =>
      Object.assign({}, obj),
    );
    updated[index].location_level = changeData.value;
    updated[index].placeholder =
      `Select your ${changeData.label.toLowerCase()}`;
    setLocationLevel(changeData);
    patchValues({ additionalContactMethods: updated });
  };

  getLocationDropdown = (linkIndex: number, item: DataCaptureFormField) => {
    const dataWarningMessage =
      locationLevel.value === DataCaptureLocationLevel.CITY
        ? "By choosing to collect city data you'll also be collecting country and state / province as additional data points."
        : locationLevel.value === DataCaptureLocationLevel.POSTAL_CODE
          ? "By choosing to collect ZIP / Postal code you’ll also be collecting country, state / province and city as additional data points."
          : null;

    return (
      <div className="location-selection__wrapper">
        <Typography.Text className="location-selection__title">
          Which level of data do you want to collect?
        </Typography.Text>
        <Row className="location-selection__dropdown">
          <MultiSelect
            className="location-selection"
            isMultiselection={false}
            selectedOptions={[locationLevel]}
            options={locationDropdownOptions}
            onOptionClick={(changeData: any) => {
              onLocationLevelSelectionChange(changeData, linkIndex);
            }}
          />
        </Row>
        {dataWarningMessage && (
          <InlineMessage
            className="m__t--16"
            type="info"
            message={dataWarningMessage}
          />
        )}
      </div>
    );
  };

  useEffect(() => {
    const locationField = values.additionalContactMethods.find(
      (field) => field.type === DataCaptureField.LOCATION,
    );

    /**
     * If new location search field is present, just set selected value as value on
     * the dropdown location dropdown.
     */
    if (locationField) {
      const selectedOption = locationDropdownOptions.find(
        (option) => option.value === locationField.location_level,
      );
      if (selectedOption) setLocationLevel(selectedOption);
    } else {
      /**
       * If FF is ON and no 'new location search field' is found,
       * it means this is an older Country based form JSON
       * 1. We need to replace the older Country field to
       *    newer location dropdown.
       */

      const additionalContactMethods = values.additionalContactMethods;
      const newLocationField = additionalContactMethods.findIndex(
        (field) => field.type === DataCaptureField.COUNTRY,
      );

      if (newLocationField > -1) {
        //Replace the older field with the new field at the same location
        additionalContactMethods[newLocationField] =
          additionalContactMethodLocation;
        patchValues({ additionalContactMethods: additionalContactMethods });
      }
    }
  }, []);

  return (
    <StepLayout
      Preview={Preview}
      Controls={
        <>
          <Button
            className="ant-btn-sm ant-btn-uppercase"
            onClick={onPrevious}
            data-testid={"previous-button"}
          >
            Previous
          </Button>
          <Button
            className="ant-btn-sm ant-btn-uppercase"
            type="primary"
            onClick={onSubmit}
            data-testid={"next-button"}
          >
            Submit
          </Button>
        </>
      }
      Form={
        <>
          <Card
            className="signup-methods-card"
            data-testid="signup-methods-card"
          >
            <span className="title">Signup Methods</span>
            <DragDropContext
              droppableId="methods-drop"
              listClassName="method-list"
              itemIdPrefix="method"
              direction="vertical"
              list={values.contactMethods}
              onDropEndCallback={onDropContactMethods}
            >
              {(dragProvided, snapshot, item, linkIndex) => (
                <PortalComponent
                  key={linkIndex}
                  innerRef={dragProvided.innerRef}
                  namespaceClass="method-list"
                  provided={dragProvided}
                  snapshot={snapshot}
                  single={false}
                >
                  <Row
                    data-testid={item.title}
                    className="additional-contact-method-row"
                    align="middle"
                  >
                    <Col className="label" span={20}>
                      {item.title}
                    </Col>
                    <Col span={2}>
                      <div
                        className="visible-toggle"
                        onClick={() => onContactMethodVisibleChanged(linkIndex)}
                      >
                        <Icon
                          name={item.isVisible ? "open-eye" : "closed-eye"}
                        />
                      </div>
                    </Col>
                    <Col span={2}>
                      <DragDropButton
                        // className="p__x--0 p__y--0 d--none"
                        dragType="vertical"
                        dragHandleProps={dragProvided.dragHandleProps}
                      />
                    </Col>
                  </Row>
                </PortalComponent>
              )}
            </DragDropContext>
          </Card>

          <Card className="contact-data-card" data-testid="contact-data-card">
            <span className="title">Additional contact data to collect</span>
            <DragDropContext
              droppableId="methods-drop"
              listClassName="method-list"
              itemIdPrefix="method"
              direction="vertical"
              list={values.additionalContactMethods}
              onDropEndCallback={onDropAdditionalContactMethods}
            >
              {(dragProvided, snapshot, item, linkIndex) => (
                <PortalComponent
                  key={linkIndex}
                  innerRef={dragProvided.innerRef}
                  namespaceClass="method-list"
                  provided={dragProvided}
                  snapshot={snapshot}
                  single={false}
                >
                  <Row
                    data-testid={item.name}
                    className="additional-contact-method-row"
                    align="middle"
                  >
                    <Col className="label" span={15}>
                      {item.label}
                    </Col>
                    <Col span={5}>
                      <Checkbox
                        // label="Required"
                        checked={item.isRequired}
                        onChange={() =>
                          onAdditionalContactMethodRequiredChanged(linkIndex)
                        }
                      >
                        Required
                      </Checkbox>
                    </Col>
                    <Col span={2}>
                      {item.isVisible ? (
                        <div
                          className="visible-toggle"
                          onClick={() =>
                            onAdditionalContactMethodVisibleChanged(linkIndex)
                          }
                        >
                          <Icon name="open-eye" />
                        </div>
                      ) : (
                        <div
                          className="visible-toggle"
                          onClick={() =>
                            onAdditionalContactMethodVisibleChanged(linkIndex)
                          }
                        >
                          <Icon name="closed-eye" />
                        </div>
                      )}
                    </Col>
                    <Col span={2}>
                      <DragDropButton
                        dragType="vertical"
                        dragHandleProps={dragProvided.dragHandleProps}
                      />
                    </Col>
                    {item.type === DataCaptureField.LOCATION && (
                      <>{getLocationDropdown(linkIndex, item)}</>
                    )}
                  </Row>
                </PortalComponent>
              )}
            </DragDropContext>
          </Card>
        </>
      }
    />
  );
};

export default DcaContactMethodsStep;
