/* eslint-disable @typescript-eslint/indent */
import { useMemo, useState, useEffect, ChangeEvent, useRef, KeyboardEvent } from 'react';
import { Box, MenuItem, Typography, TextField, Dialog, DialogContent, IconButton, Select, Slide } from '@mui/material';
import { useFormContext } from 'react-hook-form';
import { FlagEmoji, defaultCountries, parseCountry } from 'react-international-phone';
import type { SlideProps, SxProps } from '@mui/material';
import type { CountryIso2 } from 'react-international-phone';
import { useMobile } from '../hooks/mobile';

function Transition({ ref, ...props }: { ref: React.RefObject<unknown | null> } & SlideProps) {
  return <Slide direction="up" ref={ref} timeout={200} {...props} />;
}

export type CountrySelectProps = {
  value: CountryIso2;
  onChange: (value: CountryIso2) => void;
  name: string;
  sx?: SxProps;
  showDialCode?: boolean;
};

export default function CountrySelect({
  ref = undefined,
  value,
  onChange,
  name,
  sx = {},
  showDialCode = false,
}: CountrySelectProps & {
  ref?: React.RefObject<HTMLDivElement | null>;
}) {
  const { setValue } = useFormContext();
  const [open, setOpen] = useState(false);
  const [searchText, setSearchText] = useState('');
  const inputRef = useRef<HTMLInputElement>(null);
  const menuRef = useRef<HTMLDivElement>(null);
  const listRef = useRef<HTMLDivElement>(null);
  const [focusedIndex, setFocusedIndex] = useState(-1);
  const itemHeightRef = useRef<number>(40);
  const { isMobile } = useMobile();
  const measuredRef = useRef(false);

  // Handle window resize
  useEffect(() => {
    if (!open) return () => {};
    const handleResize = () => {
      measuredRef.current = false;
    };

    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  const scrollToTop = () => {
    if (listRef.current) {
      listRef.current.scrollTop = 0;
    }
  };

  const measureItemHeight = () => {
    if (!listRef.current || !open) return;

    const items = listRef.current.querySelectorAll('.MuiMenuItem-root');
    if (items.length > 0) {
      const firstItem = items[0] as HTMLElement;
      if (firstItem.offsetHeight > 0) {
        itemHeightRef.current = firstItem.offsetHeight;
      }
    }
  };

  const controlScrollPosition = (index: number) => {
    if (!listRef.current) return;

    // Always measure height when dropdown is open for accuracy
    if (open && !measuredRef.current) {
      measureItemHeight();
      measuredRef.current = true;
    }

    const listHeight = listRef.current.clientHeight;
    const targetPosition = index * itemHeightRef.current;

    if (index < 2) {
      listRef.current.scrollTop = 0;
    } else if (index > filteredCountries.length - 3) {
      listRef.current.scrollTop = listRef.current.scrollHeight - listHeight;
    } else {
      const scrollPosition = targetPosition - listHeight / 2 + itemHeightRef.current / 2;
      listRef.current.scrollTop = Math.max(0, scrollPosition);
    }
  };

  useEffect(() => {
    let timeout: NodeJS.Timeout | null = null;
    if (open) {
      timeout = setTimeout(() => {
        scrollToTop();
        if (!isMobile && inputRef.current) {
          inputRef.current.focus();
        }
      }, 100);
    } else {
      setSearchText('');
      setFocusedIndex(-1);
    }
    return () => {
      if (timeout) {
        clearTimeout(timeout);
      }
    };
  }, [open, isMobile]);

  const filteredCountries = useMemo(() => {
    if (!searchText) return defaultCountries;

    return defaultCountries.filter((c) => {
      const parsed = parseCountry(c);
      return (
        parsed.name.toLowerCase().includes(searchText.toLowerCase()) ||
        parsed.iso2.toLowerCase().includes(searchText.toLowerCase()) ||
        `+${parsed.dialCode}`.includes(searchText)
      );
    });
  }, [searchText]);

  useEffect(() => {
    scrollToTop();
    setFocusedIndex(-1);
  }, [searchText]);

  useEffect(() => {
    let timeout: NodeJS.Timeout | null = null;
    if (focusedIndex >= 0) {
      timeout = setTimeout(() => {
        controlScrollPosition(focusedIndex);
      }, 10);
    }
    return () => {
      if (timeout) {
        clearTimeout(timeout);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [focusedIndex, filteredCountries.length]);

  const countryDetail = useMemo(() => {
    const item = defaultCountries.find((v) => v[1] === value);
    return value && item ? parseCountry(item) : { name: '' };
  }, [value]);

  const handleCountryClick = (code: CountryIso2) => {
    onChange(code);
    setValue(name, code);
    setOpen(false);
  };

  const handleSearchChange = (e: ChangeEvent<HTMLInputElement>) => {
    e.stopPropagation();
    setSearchText(e.target.value);
  };

  const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
    e.stopPropagation();

    if (e.key === 'Escape') {
      setOpen(false);
      return;
    }

    const handleNavigation = (direction: 'next' | 'prev') => {
      e.preventDefault();
      setFocusedIndex((prev) => {
        if (direction === 'next') {
          if (prev === -1) return 0;
          return prev >= filteredCountries.length - 1 ? 0 : prev + 1;
        }
        if (prev === -1) return filteredCountries.length - 1;
        return prev <= 0 ? filteredCountries.length - 1 : prev - 1;
      });
    };

    if (e.key === 'Tab') {
      handleNavigation(e.shiftKey ? 'prev' : 'next');
      return;
    }

    if (e.key === 'ArrowDown') {
      handleNavigation('next');
      return;
    }

    if (e.key === 'ArrowUp') {
      handleNavigation('prev');
      return;
    }

    if (e.key === 'Enter' && focusedIndex >= 0 && focusedIndex < filteredCountries.length) {
      e.preventDefault();
      const country = parseCountry(filteredCountries[focusedIndex]);
      handleCountryClick(country.iso2);
    }
  };

  const countryListContent = (
    <>
      <Box
        sx={{
          position: 'sticky',
          top: 0,
          zIndex: 1,
          bgcolor: 'background.paper',
          p: 1,
        }}
        onClick={(e) => {
          e.stopPropagation();
        }}>
        <TextField
          inputRef={inputRef}
          autoFocus={!isMobile}
          fullWidth
          placeholder="Search country..."
          value={searchText}
          onChange={handleSearchChange}
          onKeyDown={handleKeyDown}
          onClick={(e) => e.stopPropagation()}
          size="small"
          variant="outlined"
        />
      </Box>
      <Box
        ref={listRef}
        sx={{
          flex: 1,
          overflowY: 'auto',
          overflowX: 'hidden',
          maxHeight: isMobile ? 'calc(60vh - 80px)' : 'calc(300px - 65px)',
          scrollBehavior: 'smooth',
        }}>
        {filteredCountries.length > 0 ? (
          filteredCountries.map((c: any, index) => {
            const parsed = parseCountry(c);
            const isFocused = index === focusedIndex;

            return (
              <MenuItem
                key={parsed.iso2}
                value={parsed.iso2}
                selected={parsed.iso2 === value}
                onClick={() => handleCountryClick(parsed.iso2)}
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  '&.Mui-selected': {
                    backgroundColor: 'primary.lighter',
                  },
                  '&:hover': {
                    backgroundColor: 'grey.100',
                  },
                  ...(isFocused
                    ? {
                        backgroundColor: 'grey.100',
                        outline: 'none',
                      }
                    : {}),
                }}>
                <FlagEmoji iso2={parsed.iso2} style={{ marginRight: '8px' }} />
                <Typography>{parsed.name}</Typography>
                {showDialCode && (
                  <Typography
                    sx={{
                      color: 'text.secondary',
                      ml: 1,
                    }}>
                    {`+${parsed.dialCode}`}
                  </Typography>
                )}
              </MenuItem>
            );
          })
        ) : (
          <MenuItem disabled>
            <Typography
              sx={{
                color: 'text.secondary',
              }}>
              No countries found
            </Typography>
          </MenuItem>
        )}
      </Box>
    </>
  );

  if (!isMobile) {
    return (
      <Select
        ref={ref}
        open={open}
        onOpen={() => setOpen(true)}
        onClose={() => setOpen(false)}
        MenuProps={{
          style: {
            maxHeight: '300px',
            top: '10px',
          },
          anchorOrigin: {
            vertical: 'bottom',
            horizontal: 'left',
          },
          transformOrigin: {
            vertical: 'top',
            horizontal: 'left',
          },
          PaperProps: {
            ref: menuRef,
            sx: {
              display: 'flex',
              '& .MuiList-root': {
                pt: 0,
                display: 'flex',
                flexDirection: 'column',
                overflowY: 'hidden',
              },
            },
          },
        }}
        sx={{
          width: '100%',
          minWidth: '60px',
          fieldset: {
            display: 'none',
          },
          '&.Mui-focused:has(div[aria-expanded="false"])': {
            fieldset: {
              display: 'block',
            },
          },
          '.MuiSelect-select': {
            padding: '8px',
            paddingRight: '24px !important',
          },
          svg: {
            right: 0,
          },
          '.MuiMenuItem-root': {
            justifyContent: 'flex-start',
          },
          ...sx,
        }}
        value={value}
        onChange={(e) => {
          onChange(e.target.value as CountryIso2);
          setValue(name, e.target.value);
        }}
        renderValue={(code) => (
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center',
              flexWrap: 'nowrap',
              gap: 0.5,
              cursor: 'pointer',
            }}>
            <FlagEmoji iso2={code} style={{ display: 'flex' }} />
            <Typography>{countryDetail?.name}</Typography>
          </Box>
        )}>
        {countryListContent}
      </Select>
    );
  }

  return (
    <Box ref={ref} sx={{ ...sx }}>
      <Box
        onClick={() => setOpen(true)}
        sx={{
          display: 'flex',
          alignItems: 'center',
          flexWrap: 'nowrap',
          gap: 0.5,
          cursor: 'pointer',
          padding: '8px',
          paddingRight: '24px',
          position: 'relative',
          border: 'none',
          '-webkit-tap-highlight-color': 'transparent',
          userSelect: 'none',
          background: 'none',

          '&:hover, &:focus, &:active': {
            backgroundColor: 'transparent',
            outline: 'none',
          },

          touchAction: 'manipulation',
        }}>
        <FlagEmoji iso2={value} style={{ display: 'flex' }} />
        <Typography>{countryDetail?.name}</Typography>
        <Box
          sx={{
            position: 'absolute',
            right: '8px',
            width: 0,
            height: 0,
            borderLeft: '5px solid transparent',
            borderRight: '5px solid transparent',
            borderTop: '5px solid currentColor',
          }}
        />
      </Box>
      <Dialog
        open={open}
        onClose={() => setOpen(false)}
        fullWidth
        maxWidth="xs"
        // @ts-expect-error
        TransitionComponent={Transition}
        PaperProps={{
          sx: {
            position: 'absolute',
            bottom: 0,
            m: 0,
            p: 0,
            borderBottomLeftRadius: 0,
            borderBottomRightRadius: 0,
            width: '100%',
          },
        }}>
        <Box sx={{ p: 2, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <Typography variant="h6">Select Country</Typography>
          <IconButton edge="end" onClick={() => setOpen(false)} sx={{ '-webkit-tap-highlight-color': 'transparent' }}>
            ✕
          </IconButton>
        </Box>
        <DialogContent sx={{ '&.MuiDialogContent-root': { p: 0 } }}>{countryListContent}</DialogContent>
      </Dialog>
    </Box>
  );
}
