import React, { Fragment, useState, useEffect } from "react";
import { Combobox, Transition } from "@headlessui/react";
import { EnsureArray } from "@headlessui/react/dist/types";
import { Icon, TalentCheckbox, Typography } from "@komi-app/components";
import { useLocation } from "react-router-dom";
import classNames from "classnames";
import {
  FieldValues,
  Path,
  useController,
  UseControllerProps,
} from "react-hook-form";
import "./CampaignFormCombobox.scss";

type CampaignFormComboboxOption = { label: string; value: string };

// TODO Use variables or move combobox to @komi-app/components
// This is full of CampaignForm-specific logic
export function CampaignFormCombobox<
  TFieldValues extends FieldValues = FieldValues,
  TName extends Path<TFieldValues> = Path<TFieldValues>
>({
  controllerProps,
  label,
  options,
  onChangeHandler,
}: {
  controllerProps: UseControllerProps<TFieldValues, TName>;
  label: string;
  options: CampaignFormComboboxOption[];
  onChangeHandler?: () => void;
}) {
  const {
    field: { onChange, onBlur, value },
    fieldState: { error },
  } = useController(controllerProps);

  const location = useLocation();
  const searchParams = new URLSearchParams(location.search);
  const preselectedSegmentId = searchParams.get("segmentId");

  const [query, setQuery] = useState("");

  useEffect(() => {
    if (preselectedSegmentId && !value.length) onChange([preselectedSegmentId]);
  }, [preselectedSegmentId]);

  const filteredOptions =
    query === ""
      ? options
      : options.filter((option) =>
          option.label
            .toLowerCase()
            .replace(/\s+/g, "")
            .includes(query.toLowerCase().replace(/\s+/g, ""))
        );

  const handleChange = (e: EnsureArray<TFieldValues>) => {
    onChange(e);
    if (onChangeHandler) {
      onChangeHandler();
    }
  };

  return (
    <div style={{ flex: 1 }}>
      <div style={{ paddingBottom: "2px" }} data-testid="combobox-label">
        {label}
      </div>
      <Combobox
        as={Fragment}
        value={value}
        onChange={(e) => handleChange(e)}
        multiple
      >
        {({ open }) => (
          <div
            data-testid="combobox"
            className={classNames("combobox", {
              "combobox--error": error,
              "combobox--open": open,
            })}
          >
            <div className="combobox__input-container">
              <Combobox.Button
                className="combobox__overlay"
                data-testid="combobox-button"
              >
                <Icon name="search" height={24} width={24} />
                <Icon
                  name="arrow/down"
                  height={24}
                  width={24}
                  style={{ transform: open ? "rotate(180deg)" : undefined }}
                />
              </Combobox.Button>

              <Combobox.Input<string[]>
                as={Fragment}
                className="combobox__input"
                data-testid="combobox-input"
                displayValue={(value) =>
                  open
                    ? ""
                    : options
                        .filter((o) => value.includes(o.value))
                        .map((o) => o.label)
                        .join(", ")
                }
                onChange={(event) => setQuery(event.target.value)}
              >
                <input placeholder="Select segment" />
              </Combobox.Input>
            </div>
            <Transition
              as={Fragment}
              afterLeave={() => {
                setQuery("");
                onBlur();
              }}
            >
              <Combobox.Options
                className="combobox__options"
                data-testid="combobox-options"
              >
                {filteredOptions.length === 0 && query !== "" ? (
                  <div className="combobox__option">No segments found</div>
                ) : (
                  filteredOptions.map((option) => (
                    <Combobox.Option
                      data-testid="combobox-option"
                      key={option.value}
                      className={({ active }) =>
                        `combobox__option  ${
                          active ? "combobox__option--active" : ""
                        }`
                      }
                      value={option.value}
                    >
                      {({ selected }) => (
                        <>
                          <div className="combobox__option-checkbox">
                            <TalentCheckbox
                              checked={selected}
                              value={selected}
                            />
                          </div>
                          <span>{option.label}</span>
                        </>
                      )}
                    </Combobox.Option>
                  ))
                )}
              </Combobox.Options>
            </Transition>
          </div>
        )}
      </Combobox>

      <div style={{ paddingTop: "4px" }}>
        <Typography.Body
          level={2}
          color="feedback-error"
          data-testid="combobox-error"
        >
          {error?.message}
        </Typography.Body>
      </div>
    </div>
  );
}
