import { KeyboardEvent, SyntheticEvent, useEffect, useMemo, useState } from 'react';

import KeyboardReturnIcon from '@mui/icons-material/KeyboardReturn';
import { Autocomplete, Divider, InputAdornment, TextField, useTheme } from '@mui/material';
import { AutocompleteRenderOptionState } from '@mui/material/Autocomplete';
import Box from '@mui/material/Box';
import Tooltip from '@mui/material/Tooltip';
import Typography from '@mui/material/Typography';
import { debounce } from '@mui/material/utils';
import { makeStyles } from 'tss-react/mui';

import dayjs, { extend } from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';

import { darkBlue, darkThemeText, gray } from '../../themes/common';
import { SearchHost } from '../../types/common';
import styles from './hostSearch.module.scss';

extend(relativeTime);
const goToInventoryOption: SearchHost = {
  hostname: '',
  ipaddress: '-1',
  firstreporttimestamp: '',
  lastreporttimestamp: '',
  hostkey: '',
  macs: '',
  os: ''
};

const useStyles = makeStyles()(() => ({
  root: {
    width: 370,
    fontSize: '16px',
    borderRadius: '4px',
    minWidth: 200,
    '& .MuiAutocomplete-input': {
      padding: '10px 0 10px 35px !important',
      border: 0,
      borderRadius: '4px',
      fontSize: '16px',
      margin: 0,
      boxShadow: 'none'
    },
    '& .MuiOutlinedInput-root': {
      padding: '0 !important'
    },
    '& .MuiInputBase-input::placeholder': {
      fontWeight: 500,
      fontSize: '16px',
      opacity: 1
    },
    '& .MuiOutlinedInput-notchedOutline': {
      border: '0px solid transparent',
      borderRadius: '4px'
    }
  }
}));

export const HostSearch = () => {
  const [inputValue, setInputValue] = useState('');
  const [value, setValue] = useState<SearchHost | null>(null);
  const theme = useTheme();
  const isDark = theme.palette.mode === 'dark';
  const [options, setOptions] = useState<readonly SearchHost[]>([]);
  const { classes } = useStyles();
  const fetchHosts = useMemo(
    () =>
      debounce((request: { q: string }, callback: (results?: readonly SearchHost[]) => void) => {
        const qParams = new URLSearchParams({
          query: request.q
        });
        const hostSearchUrl = `${window.location.origin}/host/searchHost`;
        fetch(hostSearchUrl + `?${qParams.toString()}`).then(async response => {
          callback(await response.json());
        });
      }, 400),
    []
  );
  const onOptionSelect = (host: SearchHost | null) => {
    if (host && host.hostkey) {
      const hostPageUrl = `${window.location.origin}/hosts/`;
      window.location.href = hostPageUrl + host.hostkey;
    }
  };
  useEffect(() => {
    let active = true;

    if (inputValue === '') {
      setOptions(value ? [value] : []);
      return undefined;
    }
    if (inputValue.length < 3) {
      return;
    }
    fetchHosts({ q: inputValue }, (results?: readonly SearchHost[]) => {
      if (active) {
        let newOptions: readonly SearchHost[] = [];

        if (value) {
          newOptions = [value];
        }

        if (results) {
          newOptions = [...newOptions, ...results, goToInventoryOption];
        }

        setOptions(newOptions);
      }
    });
    return () => {
      active = false;
    };
  }, [fetchHosts, value, inputValue]);
  const tooltipFontSize = {
    fontSize: '14px',
    fontWeight: 500
  };
  const highlightSearch = (option: string, search: string) => {
    const i = option.toLowerCase().indexOf(search.toLowerCase());
    if (i === -1) return option;
    const beforeMatch = option.slice(0, i);
    const match = option.slice(i, i + search.length);
    const afterMatch = option.slice(i + search.length);
    return (
      <>
        {beforeMatch}
        <b>{match}</b>
        {afterMatch}
      </>
    );
  };
  const openInventoryReport = (newValue: string) => {
    sessionStorage.removeItem('inventory_sql');
    window.location.href = `/reports/inventory?searchQuery=${newValue}`;
  };
  const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
    if (event.key === 'Enter') {
      const target = event.target as HTMLInputElement;
      openInventoryReport(target.value);
    }
  };
  return (
    <Autocomplete
      classes={{
        root: classes.root
      }}
      onInputChange={(event, newInputValue) => {
        setInputValue(newInputValue);
      }}
      onChange={(event: SyntheticEvent, newValue: SearchHost | null) => {
        setOptions(newValue ? [newValue, ...options] : options);
        setValue(newValue);
        onOptionSelect(newValue);
      }}
      getOptionLabel={(option: SearchHost) => (inputValue === 'SHA=' ? option.hostkey : option.hostname)}
      filterOptions={x => x}
      open={inputValue.length >= 3}
      options={options}
      value={value}
      fullWidth
      autoComplete
      disablePortal
      includeInputInList
      filterSelectedOptions
      renderInput={params => (
        <TextField
          {...params}
          placeholder="Find host"
          onKeyDown={handleKeyDown}
          slotProps={{
            ...params.slotProps,
            input: {
              ...params.slotProps.input,
              startAdornment: (
                <InputAdornment
                  position="start"
                  sx={{
                    height: 0,
                    margin: 0,
                    color: theme.palette.mode === 'dark' ? darkThemeText : darkBlue[600]
                  }}
                >
                  <div className={styles.hostSearchIcon} />
                </InputAdornment>
              ),
              endAdornment: <></>
            }
          }}
        />
      )}
      renderOption={(props, option: SearchHost, state: AutocompleteRenderOptionState) => {
        const { key, ...optionProps } = props;
        if (option.ipaddress === goToInventoryOption.ipaddress) {
          return (
            <>
              <Divider component="li" />
              <li
                {...optionProps}
                className={`${optionProps.className} ${styles.lastOption} ${styles.sp2} ${styles.sp1}`}
                key={key}
                onClick={() => openInventoryReport(state.inputValue)}
              >
                <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
                  <Box sx={{ display: 'flex', alignItems: 'center' }}>
                    <i style={{ fontSize: '16px' }} className="bi bi-search" />
                    <Typography sx={{ marginLeft: '8px' }}>Open in inventory report</Typography>
                  </Box>
                  <Box className={styles[`enterIcon${isDark ? 'Dark' : ''}`]}>
                    <KeyboardReturnIcon fontSize="small" />
                  </Box>
                </Box>
              </li>
            </>
          );
        }
        return (
          <Tooltip
            arrow
            placement="right-end"
            title={
              <Box className={styles.hostTooltip} sx={{ pointerEvents: 'auto' }}>
                <Typography sx={{ fontSize: '18px', fontWeight: 700 }}>{option.hostname}</Typography>
                <Typography title={option.hostkey} sx={tooltipFontSize}>
                  CFEngine ID: {option.hostkey.slice(0, 10)}...
                </Typography>
                <Typography sx={tooltipFontSize}>OS: {option.os}</Typography>
                <Typography sx={tooltipFontSize}>First report: {dayjs(option.firstreporttimestamp).format('YYYY-MM-DD HH:mmZ')}</Typography>
                <Typography sx={tooltipFontSize}>Last report: {dayjs(option.lastreporttimestamp).format('YYYY-MM-DD HH:mmZ')}</Typography>
                <Typography sx={tooltipFontSize}>IP(s): {option.ipaddress}</Typography>
                <Typography sx={tooltipFontSize}>MACs: {option.macs}</Typography>
              </Box>
            }
          >
            <li {...optionProps} key={key}>
              <Box sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', width: '100%' }}>
                <Typography sx={{ maxWidth: '180px', fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }} variant="body1">
                  {highlightSearch(inputValue.startsWith('SHA=') ? option.hostkey.slice(0, 10) : option.hostname, inputValue)}
                </Typography>
                <Typography
                  variant="body2"
                  sx={{
                    color: gray[500],
                    fontWeight: 500
                  }}
                >
                  Active {dayjs().to(dayjs(option.lastreporttimestamp))}
                </Typography>
              </Box>
            </li>
          </Tooltip>
        );
      }}
    />
  );
};
