import React, {useEffect, useMemo, useRef, useState} from 'react';
import {Box, Button, CloseButton, Heading, Input, InputGroup, Spinner, Stack, Table, Text} from "@chakra-ui/react";
import {useAppStore} from "../appstore";
import {B2BQOMOrderListItem} from "../types/b2bqom";
import {UI_C} from "../constants/styling";
import {api} from "../api";
import {highlightSearchTerm} from "../utils/rendering";
import {toast} from "../components/ui/toaster";
import {Tooltip} from "../components/tooltip";

const DEBOUNCE_DELAY = 400; // ms
const MIN_SEARCH_LENGTH = 2;

export function SearchDialogContent() {
  const {
    searchTerm,
    searchResults,
    orderList,
    setSearchTerm,
    setSearchResults,
    clearSearchResults,
    searchTermOnSearchAction,
    showEmptyResultsMsg,
    addToOrderList
  } = useAppStore();
  const inputRef = useRef<HTMLInputElement | null>(null);
  const [searchInProgress, setSearchInProgress] = useState(false);

  const searchIdRef = useRef(0);
  const debounceTimerRef = useRef<number | null>(null);

  const search = async (term: string) => {
    if (!term || term.length < MIN_SEARCH_LENGTH) return;

    const searchId = ++searchIdRef.current; // bump counter
    setSearchInProgress(true);

    try {
      const results = await api.search(term);
      if (searchId === searchIdRef.current) {
        // Only apply if it's the latest search
        setSearchResults(term, results);
      }
    } catch(err) {
      toast({
        type: "error",
        title: err instanceof Error ? err.message : "Please try again",
      });
    } finally {
      if (searchId === searchIdRef.current) {
        setSearchInProgress(false);
      }
    }
  };

  // Debounced search on typing
  useEffect(() => {
    // Clear previous timer
    if (debounceTimerRef.current) {
      clearTimeout(debounceTimerRef.current);
    }

    // Don't search if less than min length
    if (searchTerm.length < MIN_SEARCH_LENGTH) {
      return;
    }

    // Set new timer
    debounceTimerRef.current = window.setTimeout(() => {
      search(searchTerm);
    }, DEBOUNCE_DELAY);

    // Cleanup on unmount or before next effect
    return () => {
      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }
    };
  }, [searchTerm]);

  const orderListBySku = useMemo(() => {
    return new Map(orderList.map(oli => [oli.sku, oli]));
  }, [orderList]);

  const orderListCandidatesMap: Map<string, B2BQOMOrderListItem> = useMemo(() => {
    return new Map(searchResults.map(sr => ([sr.sku, {...sr, quantity: orderListBySku.get(sr.sku)?.quantity || 0}])));
  }, [searchResults]);

  const addCandidateToList = (sku: string) => {
    const orderListCandidate = orderListCandidatesMap.get(sku);
    orderListCandidate && addToOrderList(orderListCandidate);
    inputRef?.current?.focus();
  }

  return (
    <Stack>
      <InputGroup endElement={
        <Stack direction="row" alignItems="center">
          {
            searchInProgress && <Spinner size="sm" />
          }
          <CloseButton size="sm" onClick={clearSearchResults}/>
        </Stack>
      }>
        <Input type="search"
               style={{outline: "none"}}
               colorPalette="blue"
               size="lg"
               placeholder="Search SKU or name (min 2 characters)"
               value={searchTerm}
               onChange={e => setSearchTerm(e.target.value)}
               autoFocus={true}
               ref={inputRef}
        />
      </InputGroup>
      {
        (searchResults.length !== 0 || showEmptyResultsMsg) &&
        <Stack direction='column'>
          <Heading>Search Results for <strong
            style={{backgroundColor: '#e6e6e6'}}>{searchTermOnSearchAction}</strong></Heading>
          {
            showEmptyResultsMsg
              ? <Text textStyle="md">Nothing found. Type another search term and press Enter.</Text>
              : <Box style={{maxHeight: '55vh', overflowY: 'auto', scrollPaddingTop: '40px'}}>
                <Table.Root>
                  <Table.Header style={{position: "sticky", top: 0, background: "white", zIndex: 1}}>
                    <Table.Row>
                      <Table.ColumnHeader w="150px" fontWeight="bold">SKU</Table.ColumnHeader>
                      <Table.ColumnHeader fontWeight="bold">Product</Table.ColumnHeader>
                      <Table.ColumnHeader w="80px" fontWeight="bold">In stock</Table.ColumnHeader>
                      <Table.ColumnHeader w="100px" fontWeight="bold">Price</Table.ColumnHeader>
                      <Table.ColumnHeader w="100px">&nbsp;</Table.ColumnHeader>
                    </Table.Row>
                  </Table.Header>
                  <Table.Body>
                    {Array.from(orderListCandidatesMap.values()).map((item) => (
                      <Table.Row key={item.id}>
                        <Table.Cell>
                          <Tooltip content={`${item.sku}`} hasArrow>
                            <Box maxW="150px" whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
                              {highlightSearchTerm(item.sku, searchTermOnSearchAction)}
                            </Box>
                          </Tooltip>
                        </Table.Cell>

                        <Table.Cell>
                          <Tooltip content={`${item.name}`} hasArrow>
                            <Box whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
                              {highlightSearchTerm(item.name, searchTermOnSearchAction)}
                            </Box>
                          </Tooltip>
                        </Table.Cell>
                        <Table.Cell>{item.stock_quantity}</Table.Cell>
                        <Table.Cell>{item.price}</Table.Cell>
                        <Table.Cell textAlign="center">
                          {
                            orderListBySku.has(item.sku)
                              ? <Button variant={UI_C.BTN_VARIANT} colorPalette={UI_C.COLOR_PALETTE} disabled>Added</Button>
                              : <Button
                                variant={UI_C.BTN_VARIANT}
                                colorPalette={UI_C.COLOR_PALETTE}
                                onClick={() => addCandidateToList(item.sku)}
                              >
                                Add
                              </Button>
                          }
                        </Table.Cell>
                      </Table.Row>
                    ))}
                  </Table.Body>
                </Table.Root>
              </Box>
          }
        </Stack>
      }
    </Stack>
  );
}