import {
  JSX,
  Component,
  For,
  useContext,
  startTransition,
  Show,
  splitProps,
} from "solid-js";
import { produce, unwrap } from "solid-js/store";
import { autoAnimate } from "~/directives/autoAnimate";
import { sortable } from "~/directives/sortable";
import {
  Position,
  POSITION_TYPE_AGILE,
  POSITION_TYPE_QUANTITY,
  StoreContext,
  UiStoreContext,
} from "~/stores";
import AddIcon from "~icons/carbon/add-filled";
import DeleteIcon from "~icons/carbon/trash-can";
import DragVerticalIcon from "~icons/carbon/drag-vertical";
import PositionSettingsIcon from "~icons/carbon/settings-adjust";
import { Checkbox, NumberInput, TextArea, TextInput } from "../Form";
import { MarkdownHelpLabel } from "../Markdown";
import {
  createOptionalNumberInputHandler,
  createNativeInputValue,
  resetInput,
} from "~/util";

export const PositionsSettings: Component = () => {
  const [state, setState] = useContext(StoreContext)!;
  const [uiState, setUiState] = useContext(UiStoreContext)!;

  autoAnimate;
  sortable;

  const AddPositionButton: Component<{ idx?: number }> = (props) => (
    <button
      onClick={() => {
        const id = Math.random();
        setState(
          "positions",
          produce((positions: Position[]) => {
            const newPosition: Position = {
              id,
              enabled: true,
              type: state.defaultPositionType,
              name: "",
              quantity: 1,
            };
            if (props.idx != null) {
              positions.splice(props.idx, 0, newPosition);
            } else {
              positions.push(newPosition);
            }
          })
        );
        setUiState("selectedPosition", id);
      }}
      class="btn btn-xs btn-circle btn-outline btn-accent"
    >
      <AddIcon />
    </button>
  );

  return (
    <>
      <div
        class="grid grid-cols-1 gap-4"
        use:sortable={{
          handle: ".handle",
          dragClass: "sortable-drag-card",
          ghostClass: "sortable-ghost-card",
          filter: ".drag-disabled",
          forceFallback: true,
          onEnd: (evt) => {
            const oldIndex = evt.oldIndex;
            const newIndex = evt.newIndex;
            if (oldIndex == null || newIndex == null) {
              return;
            }

            setState(
              "positions",
              produce((positions: any[]) => {
                let item = positions[oldIndex];
                positions.splice(oldIndex, 1);
                positions.splice(newIndex, 0, unwrap(item));
              })
            );
          },
        }}
      >
        <For each={state.positions}>
          {(position, idx) => {
            let nameInputRef: HTMLInputElement = undefined!;
            let positionNumberInputRef: HTMLInputElement = undefined!;
            let onEnterKeyClose: JSX.EventHandler<
              HTMLInputElement,
              KeyboardEvent
            > = (e) => {
              if (e.code !== "Enter") {
                return;
              }

              setUiState("selectedPosition", undefined);
            };

            const AgileDropdown: Component<
              { selected: number } & JSX.HTMLAttributes<HTMLSelectElement>
            > = (p) => {
              const [props, rest] = splitProps(p, ["selected", "class"]);
              return (
                <select
                  class={
                    "flex-1 w-0 pl-1 pr-0 select indent-0 select-xs select-bordered rounded-none " +
                    props.class
                  }
                  {...rest}
                >
                  <For each={[0, 1, 2, 3, 5, 8, 13]}>
                    {(v) => (
                      <option selected={v === props.selected}>{v}</option>
                    )}
                  </For>
                </select>
              );
            };

            let quantityInputEl: HTMLInputElement = undefined!;
            const quantityValue = createNativeInputValue(
              () => quantityInputEl,
              () => position.quantity
            );

            return (
              <div class="indicator w-full">
                <div class="indicator-item indicator-middle indicator-end flex items-center">
                  <div
                    title="Drag here"
                    class="rounded-sm bg-white p-1 py-3 shadow-sm border -ml-2 text-sm transition-transform cursor-pointer handle"
                  >
                    <DragVerticalIcon />
                  </div>
                </div>
                <div
                  data-idx={idx()}
                  class="relative z-10 bg-white w-full mr-4 card rounded-lg card-bordered card-compact shadow-sm"
                >
                  <div class="card-body !p-2">
                    <div class="card-actions items-center justify-between gap-4 flex-nowrap">
                      <div
                        classList={{
                          "flex gap-2 overflow-hidden": true,
                          "line-through": !position.enabled,
                        }}
                      >
                        <div
                          class="font-bold cursor-pointer"
                          onClick={async () => {
                            await startTransition(function () {
                              setUiState("selectedPosition", position.id);
                            });
                            if (positionNumberInputRef) {
                              positionNumberInputRef.focus();
                            }
                          }}
                        >
                          {position.number || idx() + 1}
                        </div>
                        <div
                          class="min-w-[50px] min-h-[1rem] cursor-pointer text-ellipsis overflow-hidden whitespace-nowrap"
                          onClick={async () => {
                            await startTransition(function () {
                              setUiState("selectedPosition", position.id);
                            });
                            if (nameInputRef) {
                              nameInputRef.focus();
                            }
                          }}
                        >
                          {position.name}
                        </div>
                      </div>
                      <div class="flex gap-3">
                        <AddPositionButton idx={idx()} />
                        <button
                          classList={{
                            "btn btn-xs btn-circle": true,
                            "btn-outline":
                              uiState.selectedPosition !== position.id,
                            "btn-active":
                              uiState.selectedPosition === position.id,
                          }}
                          onClick={() =>
                            setUiState(
                              "selectedPosition",
                              uiState.selectedPosition !== position.id
                                ? position.id
                                : undefined
                            )
                          }
                        >
                          <PositionSettingsIcon />
                        </button>
                        <button
                          onClick={() => {
                            setState(
                              "positions",
                              produce((positions: Position[]) =>
                                positions.splice(idx(), 1)
                              )
                            );
                          }}
                          class="btn btn-xs btn-circle btn-outline btn-error"
                        >
                          <DeleteIcon />
                        </button>
                      </div>
                    </div>
                    <div class="grid grid-cols-2 gap-1">
                      <div class="shrink form-control">
                        <div use:autoAnimate class="input-group input-group-xs">
                          <select
                            class="select select-xs select-bordered border-r-0"
                            onChange={(e) =>
                              setState(
                                "positions",
                                idx(),
                                "type",
                                e.currentTarget.value as any
                              )
                            }
                          >
                            <For
                              each={[
                                [POSITION_TYPE_QUANTITY, "Menge"],
                                [POSITION_TYPE_AGILE, "Agile"],
                              ]}
                            >
                              {([type, label]) => (
                                <option
                                  value={type}
                                  selected={position.type === type}
                                >
                                  {label}
                                </option>
                              )}
                            </For>
                          </select>
                          <Show when={position.type === POSITION_TYPE_QUANTITY}>
                            <div class="flex-1">
                              <input
                                ref={quantityInputEl}
                                class="w-full input input-bordered input-xs"
                                value={quantityValue()}
                                placeholder="Menge"
                                required
                                name="Menge"
                                onInput={createOptionalNumberInputHandler(
                                  (v) => {
                                    v != null &&
                                      setState(
                                        "positions",
                                        idx(),
                                        "quantity",
                                        v
                                      );
                                  }
                                )}
                                onBlur={resetInput(0)}
                              />
                            </div>
                          </Show>
                          <Show when={position.type === POSITION_TYPE_AGILE}>
                            <AgileDropdown
                              title="Story Points Minimum"
                              class="border-r-0"
                              onChange={(e) =>
                                setState(
                                  "positions",
                                  idx(),
                                  "agilePointsMin",
                                  parseInt(e.currentTarget.value)
                                )
                              }
                              selected={position.agilePointsMin || 0}
                            />
                            <AgileDropdown
                              title="Story Points Maximum"
                              onChange={(e) =>
                                setState(
                                  "positions",
                                  idx(),
                                  "agilePointsMax",
                                  parseInt(e.currentTarget.value)
                                )
                              }
                              selected={position.agilePointsMax || 0}
                            />
                          </Show>
                        </div>
                      </div>
                      <NumberInput
                        size="xs"
                        value={position.itemPrice}
                        label="Einzelpreis"
                        placeholder={
                          state.defaultItemPrice
                            ? state.defaultItemPrice + ""
                            : undefined
                        }
                        onInput={(v) =>
                          setState("positions", idx(), "itemPrice", v)
                        }
                      />
                      <div
                        use:autoAnimate
                        class="col-span-2 grid grid-cols-2 gap-1"
                      >
                        <Show when={uiState.selectedPosition === position.id}>
                          <div class="col-span-2">
                            <TextInput
                              ref={nameInputRef}
                              value={position.name}
                              label="Name"
                              required
                              onKeyDown={onEnterKeyClose}
                              onInput={(e) => {
                                setState(
                                  "positions",
                                  idx(),
                                  "name",
                                  e.currentTarget.value
                                );
                              }}
                            />
                          </div>
                          <div class="col-span-2">
                            <TextInput
                              ref={positionNumberInputRef}
                              value={position.number}
                              label="Position"
                              onKeyDown={onEnterKeyClose}
                              onInput={(e) => {
                                setState(
                                  "positions",
                                  idx(),
                                  "number",
                                  e.currentTarget.value
                                );
                              }}
                            />
                          </div>
                          <div class="col-span-2">
                            <NumberInput
                              label="Aktionspreis"
                              suffix="CHF"
                              value={position.fixedDiscountPrice}
                              onInput={(v) =>
                                setState(
                                  "positions",
                                  idx(),
                                  "fixedDiscountPrice",
                                  v
                                )
                              }
                            />
                          </div>
                          <div class="col-span-2">
                            <TextArea
                              label="Beschreibung"
                              labelSuffixJsx={<MarkdownHelpLabel />}
                              value={position.description}
                              onInput={(evt) =>
                                setState(
                                  "positions",
                                  idx(),
                                  "description",
                                  evt.currentTarget.value
                                )
                              }
                            />
                          </div>
                          <div class="col-span-2">
                            <Checkbox
                              checked={position.enabled}
                              onChange={(e) =>
                                setState(
                                  "positions",
                                  idx(),
                                  "enabled",
                                  e.currentTarget.checked
                                )
                              }
                            >
                              Position ist aktiv
                            </Checkbox>
                          </div>
                        </Show>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            );
          }}
        </For>
      </div>
      <div class={"p-3 flex justify-center drag-disabled"}>
        <AddPositionButton />
      </div>
    </>
  );
};
