import { TricksterCharacter } from "../lib/trickster"
import { useSessionContext } from "../context/SessionContext"

import 'handsontable/dist/handsontable.full.min.css';

import { registerAllModules } from 'handsontable/registry';
import { HotTable, HotTableClass } from '@handsontable/react';
import { forwardRef, useCallback, useEffect, useId, useMemo, useRef, useState} from "react";
import { InventoryTable } from "../lib/table";
import { DotLoader } from "react-spinners";
import {  useResizeObserver } from "@mantine/hooks";
import { Columns } from "../lib/columns";
import { OrderDetails, OrderSender } from "../lib/lifeto/order_manager";
import log from "loglevel";
import { charactersAtom, currentCharacterInventoryAtom, currentCharacterItemsAtom, LTOApi, selectedTargetInventoryAtom } from "../state/atoms";
import Select from 'react-select';
import { useAtom, useAtomValue } from "jotai";
import { autoUpdate, flip, FloatingFocusManager, FloatingPortal, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole } from "@floating-ui/react";
import Fuse from "fuse.js";

registerAllModules();
type Size = {
  width?: number
  height?: number
}



interface InventoryItemProps {
  children: React.ReactNode;
  active: boolean;
}

const InventoryItem = forwardRef<
  HTMLDivElement,
  InventoryItemProps & React.HTMLProps<HTMLDivElement>
>(({ children, active, ...rest }, ref) => {
  const id = useId();
  return (
    <div
      ref={ref}
      role="option"
      id={id}
      aria-selected={active}
      {...rest}
      style={{
        background: active ? "lightblue" : "none",
        padding: 4,
        cursor: "default",
        ...rest.style,
      }}
    >
      {children}
    </div>
  );
});

const InventoryTargetSelector = () => {
  const [open, setOpen] = useState(false);
  const [inputValue, setInputValue] = useState("");
  const [activeIndex, setActiveIndex] = useState<number | null>(null);

  const listRef = useRef<Array<HTMLElement | null>>([]);

  const { refs, floatingStyles, context } = useFloating<HTMLInputElement>({
    whileElementsMounted: autoUpdate,
    open,
    onOpenChange: setOpen,
    middleware: [
      flip({ padding: 10 }),
      size({
        apply({ rects, availableHeight, elements }) {
          Object.assign(elements.floating.style, {
            width: `${rects.reference.width}px`,
            maxHeight: `${availableHeight}px`,
          });
        },
        padding: 10,
      }),
    ],
  });

  const role = useRole(context, { role: "listbox" });
  const dismiss = useDismiss(context);
  const listNav = useListNavigation(context, {
    listRef,
    activeIndex,
    onNavigate: setActiveIndex,
    virtual: true,
    loop: true,
  });

  const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(
    [role, dismiss, listNav]
  );

  function onChange(event: React.ChangeEvent<HTMLInputElement>) {
    const value = event.target.value;
    setInputValue(value);
    setSelectedTargetInventory(undefined)

    if (value) {
      setOpen(true);
      setActiveIndex(0);
    } else {
      setOpen(false);
    }
  }
  const { data: subaccounts } = useAtomValue(charactersAtom)

  const [selectedTargetInventory, setSelectedTargetInventory] = useAtom(selectedTargetInventoryAtom)

  const searcher = useMemo(()=>{
    return new Fuse(subaccounts?.flatMap(x=>[
      x.bank,
      x.character,
    ])||[], {
        keys:["path","name"],
        findAllMatches: true,
        threshold: 0.8,
        useExtendedSearch: true,
      })
  }, [subaccounts])

  const items = searcher.search(inputValue || "!-", {limit: 10}).map(x=>x.item)
  return (
    <>
      <input
        className="border border-black-1 bg-gray-100 placeholder-gray-600"
        {...getReferenceProps({
          ref: refs.setReference,
          onChange,
          value: selectedTargetInventory !== undefined ? selectedTargetInventory.name : inputValue,
          placeholder: "Target Inventory",
          "aria-autocomplete": "list",
          onKeyDown(event) {
            if (
              event.key === "Enter" &&
                activeIndex != null &&
                items[activeIndex]
            ) {
              setSelectedTargetInventory(items[activeIndex])
              setInputValue(items[activeIndex].name);
              setActiveIndex(null);
              setOpen(false);
            }
          },
        })}
      />
      {open && (
        <FloatingPortal>
          <FloatingFocusManager
            context={context}
            initialFocus={-1}
            visuallyHiddenDismiss
          >
            <div
              {...getFloatingProps({
                ref: refs.setFloating,
                style: {
                  ...floatingStyles,
                  background: "#eee",
                  color: "black",
                  overflowY: "auto",
                },
              })}
            >
              {items.map((item, index) => (
                <InventoryItem
                  {...getItemProps({
                    key: item.path,
                    ref(node) {
                      listRef.current[index] = node;
                    },
                    onClick() {
                      setInputValue(item.name);
                      setSelectedTargetInventory(item);
                      setOpen(false);
                      refs.domReference.current?.focus();
                    },
                  })}
                  active={activeIndex === index}
                >
                  {item.name}
                </InventoryItem>
              ))}
            </div>
          </FloatingFocusManager>
        </FloatingPortal>
      )}
    </>
  );
}
export const Inventory = () => {
  const {activeTable, columns, tags, orders} = useSessionContext()

  const [ref, {height}] = useResizeObserver({})

  const {data:character, isLoading, isFetching } = useAtomValue(currentCharacterInventoryAtom)
//const sendOrders = useCallback(()=>{
//  if(!hotTableComponent.current?.hotInstance){
//    return
//  }
//  const hott = hotTableComponent.current?.hotInstance
//  const headers = hott.getColHeader()
//  const dat = hott.getData()
//  const idxNumber = headers.indexOf(Columns.MoveCount.displayName)
//  const idxTarget = headers.indexOf(Columns.Move.displayName)
//  const origin = activeTable
//  const pending:OrderDetails[] = [];
//  for(const row of dat) {
//    try{
//      const nm = Number(row[idxNumber].replace("x",""))
//      const target = (row[idxTarget] as string).replaceAll("-","").trim()
//      if(!isNaN(nm) && nm > 0 && target.length > 0){
//        const info:OrderDetails = {
//          item_uid: row[0].toString(),
//          count: nm,
//          origin_path: activeTable,
//          target_path: target,
//        }
//        pending.push(info)
//      }
//    }catch(e){
//    }
//  }
//  log.debug("OrderDetails", pending)
//  const chars = new Map<string,TricksterCharacter>()
//  const manager = new OrderSender(orders, chars)
//  for(const d of pending){
//    const order = manager.send(d)
//    //order.tick(api)
//  }
//}, [orders])

  const Loading = ()=>{
    return <div role="status" className="flex align-center justify-center">
      <div className="justify-center py-4">
        <DotLoader color="#dddddd"/>
      </div>
    </div>
  }

  const items = useAtomValue(currentCharacterItemsAtom)

  return <div ref={ref} className={``}>
    <div className="flex flex-row py-2 justify-end">
      <InventoryTargetSelector/>
      <div
        onClick={(e)=>{
         // sendOrders()
        }}
        className="
        hover:cursor-pointer
        border border-black-1
        bg-green-200
        px-2 py-1
        ">Move Selected</div>
    </div>
    {(isLoading || isFetching) ? <Loading/> : <>
      <div>
        total: {items.size}
      </div>
    </> }
  </div>
}
