/* eslint-disable @typescript-eslint/indent */
import { useMemo, useState, useEffect, ChangeEvent, useRef, KeyboardEvent } from 'react';
import {
  Box,
  MenuItem,
  Typography,
  TextField,
  Dialog,
  DialogContent,
  IconButton,
  Select,
  Slide,
  Stack,
} from '@mui/material';
import { Clear as ClearIcon } from '@mui/icons-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 useFormContextSafe() {
  try {
    return useFormContext();
  } catch {
    return null;
  }
}

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;
  label?: string;
  allowClear?: boolean;
  bordered?: boolean;
  disabled?: boolean;
};

export default function CountrySelect({
  ref = undefined,
  value,
  onChange,
  name = '',
  sx = {},
  showDialCode = false,
  label = '',
  bordered = false,
  allowClear = false,
  disabled = false,
}: CountrySelectProps & {
  ref?: React.RefObject<HTMLDivElement | null>;
}) {
  const formContext = useFormContextSafe();
  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);
    if (formContext && name) {
      formContext.setValue(name, code);
    }
    setOpen(false);
  };

  const handleClear = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    onChange('' as CountryIso2);
    if (formContext && name) {
      formContext.setValue(name, '');
    }
  };

  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={label || 'Search country...'}
          value={searchText}
          onChange={handleSearchChange}
          onKeyDown={handleKeyDown}
          onClick={(e) => e.stopPropagation()}
          size="small"
          variant="outlined"
          disabled={disabled}
        />
      </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',
                width: '100%',
              },
            },
          },
        }}
        sx={{
          width: '100%',
          minWidth: '60px',
          fieldset: {
            display: 'none',
          },
          '&.Mui-focused:has(div[aria-expanded="false"])': {
            fieldset: {
              display: 'block',
            },
          },
          '.MuiSelect-select': {
            padding: '8px',
            paddingRight: allowClear && value ? '48px !important' : '24px !important',
          },
          svg: {
            right: 0,
          },
          '.MuiMenuItem-root': {
            justifyContent: 'flex-start',
          },
          ...sx,
        }}
        value={value}
        onChange={(e) => {
          onChange(e.target.value as CountryIso2);
          if (formContext && name) {
            formContext.setValue(name, e.target.value);
          }
        }}
        disabled={disabled}
        renderValue={(code) => (
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center',
              flexWrap: 'nowrap',
              gap: 0.5,
              cursor: 'pointer',
              width: '100%',
            }}>
            {code ? (
              <Stack
                direction="row"
                sx={{
                  alignItems: 'center',
                  gap: 0.5,
                  justifyContent: 'space-between',
                  width: '100%',
                }}>
                <Stack
                  direction="row"
                  sx={{
                    alignItems: 'center',
                    gap: 0.5,
                  }}>
                  <FlagEmoji iso2={code} style={{ display: 'flex' }} />
                  <Typography sx={{ flex: 1 }}>{countryDetail?.name}</Typography>
                </Stack>

                {allowClear && value && (
                  <Box
                    onClick={handleClear}
                    onMouseDown={(event) => {
                      event.stopPropagation();
                      event.preventDefault();
                    }}
                    onTouchStart={(event) => {
                      event.stopPropagation();
                    }}
                    sx={{
                      display: 'flex',
                      alignItems: 'center',
                      cursor: 'pointer',
                      p: 0,
                      borderRadius: '50%',
                      border: 'none',
                      background: 'transparent',
                      zIndex: 2,
                      marginRight: '-28px',
                      '&:hover': {
                        backgroundColor: 'action.hover',
                      },
                    }}>
                    <ClearIcon fontSize="small" />
                  </Box>
                )}
              </Stack>
            ) : (
              <Typography sx={{ color: 'text.secondary', flex: 1 }}>{label || 'Select country...'}</Typography>
            )}
          </Box>
        )}>
        {countryListContent}
      </Select>
    );
  }

  return (
    <Box ref={ref} sx={{ ...sx }}>
      <Box
        onClick={() => {
          if (disabled) return;
          setOpen(true);
        }}
        sx={{
          display: 'flex',
          alignItems: 'center',
          flexWrap: 'nowrap',
          gap: 0.5,
          cursor: 'pointer',
          padding: '8px',
          paddingRight: '24px',
          position: 'relative',
          ...(!bordered
            ? {
                border: 'none',
              }
            : {}),

          '-webkit-tap-highlight-color': 'transparent',
          userSelect: 'none',
          background: 'none',

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

          ...(disabled
            ? {
                backgroundColor: 'grey.100',
                cursor: 'not-allowed',
                color: 'text.disabled',
                '&:hover, &:focus, &:active': {
                  backgroundColor: 'grey.100',
                  color: 'text.disabled',
                },
              }
            : {}),

          touchAction: 'manipulation',
        }}>
        {value ? (
          <>
            <FlagEmoji iso2={value} style={{ display: 'flex' }} />
            <Typography sx={{ flex: 1 }}>{countryDetail?.name}</Typography>
            {allowClear && (
              <Box
                component="button"
                type="button"
                onClick={handleClear}
                onMouseDown={(event) => {
                  event.stopPropagation();
                  event.preventDefault();
                }}
                onTouchStart={(event) => {
                  event.stopPropagation();
                }}
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  cursor: 'pointer',
                  p: 0.5,
                  mr: 1,
                  borderRadius: '50%',

                  border: 'none',
                  background: 'transparent',
                  '&:hover': {
                    backgroundColor: 'action.hover',
                  },
                }}>
                <ClearIcon fontSize="small" />
              </Box>
            )}
          </>
        ) : (
          <Typography sx={{ color: 'text.secondary', flex: 1 }}>{label || 'Select country...'}</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"
        slotProps={{
          paper: {
            sx: {
              position: 'absolute',
              bottom: 0,
              m: 0,
              p: 0,
              borderBottomLeftRadius: 0,
              borderBottomRightRadius: 0,
              width: '100%',
            },
          },
        }}
        slots={{
          transition: Transition,
        }}>
        <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>
  );
}
