import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  Box,
  Button,
  Divider,
  Drawer,
  IconButton,
  InputAdornment,
  List,
  ListItem,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  Popover,
  Stack,
  TextField,
  Typography,
} from '@mui/material';
import { CheckCircle, Close, KeyboardDoubleArrowRight, Search } from '@mui/icons-material';
import { useEffect, useMemo, useRef, useState, memo } from 'react';
import type { ControllerRenderProps, FieldError } from 'react-hook-form';
import { Controller, useFormContext } from 'react-hook-form';
import type { MouseEvent } from 'react';
import { useMobile } from '@blocklet/payment-react';

import Collapse from '../collapse';
import taxCodesRaw from './taxCodes.json';

export type TaxCodeType = 'general' | 'digital' | 'services' | 'physical';

type LocaleKey = 'en' | 'zh';

interface RawTaxCode {
  id: string;
  type: TaxCodeType;
  name: Record<LocaleKey, string>;
  description: Record<LocaleKey, string>;
  label: Record<LocaleKey, string>;
}

const TAX_CODE_TYPES: TaxCodeType[] = ['general', 'digital', 'services', 'physical'];

const TYPE_TRANSLATION_KEYS: Record<TaxCodeType, string> = {
  general: 'admin.taxRate.types.general',
  digital: 'admin.taxRate.types.digital',
  services: 'admin.taxRate.types.services',
  physical: 'admin.taxRate.types.physical',
};

const taxCodesById: Record<string, RawTaxCode> = taxCodesRaw as unknown as Record<string, RawTaxCode>;
const TAX_CODE_LIST: RawTaxCode[] = Object.values(taxCodesById);

const SORTED_TAX_CODES: RawTaxCode[] = [...TAX_CODE_LIST].sort((a, b) =>
  a.name.en.localeCompare(b.name.en, undefined, { sensitivity: 'base' })
);

const GROUPED_TAX_CODES: Record<TaxCodeType, RawTaxCode[]> = SORTED_TAX_CODES.reduce(
  (acc, code) => {
    if (!acc[code.type]) {
      acc[code.type] = [] as RawTaxCode[];
    }
    acc[code.type].push(code);
    return acc;
  },
  {
    general: [] as RawTaxCode[],
    digital: [] as RawTaxCode[],
    services: [] as RawTaxCode[],
    physical: [] as RawTaxCode[],
  }
);

const createDefaultExpanded = (): Record<TaxCodeType, boolean> => {
  const result = {} as Record<TaxCodeType, boolean>;
  TAX_CODE_TYPES.forEach((type, index) => {
    result[type] = index === 0;
  });
  return result;
};

interface TaxCodeSelectProps {
  name?: string;
  label?: string;
  placeholder?: string;
  required?: boolean;
  disabled?: boolean;
}

interface PickerProps {
  field: ControllerRenderProps<any, string>;
  error?: FieldError;
  disabled: boolean;
  label: string;
  placeholder: string;
  language: LocaleKey;
  translate: (key: string, params?: Record<string, any>) => string;
}

interface TaxCodeItemProps {
  code: RawTaxCode;
  isSelected: boolean;
  displayName: string;
  showIndicator: boolean;
  itemBorder: boolean;
  onSelect: (code: RawTaxCode) => void;
  onHover: (id: string | null) => void;
}

const TaxCodeItem = memo(
  ({ code, isSelected, displayName, showIndicator, itemBorder, onSelect, onHover }: TaxCodeItemProps) => (
    <ListItem
      disablePadding
      sx={
        itemBorder
          ? {
              '&:not(:last-of-type)': {
                borderBottom: '1px solid',
                borderColor: 'divider',
              },
              contain: 'layout style paint',
            }
          : { contain: 'layout style paint' }
      }>
      <ListItemButton
        selected={isSelected}
        onMouseEnter={() => onHover(code.id)}
        onMouseLeave={() => onHover(null)}
        onFocus={() => onHover(code.id)}
        onClick={() => onSelect(code)}>
        <ListItemText
          primary={
            <Typography variant="body2" sx={{ fontWeight: 500, color: 'text.primary' }}>
              {displayName}
            </Typography>
          }
          secondary={
            <Typography
              variant="caption"
              sx={{
                color: 'text.secondary',
              }}>
              {code.id}
            </Typography>
          }
        />
        {showIndicator && isSelected && (
          <ListItemIcon sx={{ minWidth: 0, color: 'primary.main' }}>
            <CheckCircle fontSize="small" />
          </ListItemIcon>
        )}
      </ListItemButton>
    </ListItem>
  )
);

TaxCodeItem.displayName = 'TaxCodeItem';

function TaxCodePicker({ field, error = undefined, disabled, label, placeholder, language, translate }: PickerProps) {
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [search, setSearch] = useState('');
  const [hoveredId, setHoveredId] = useState<string | null>(null);
  const [expandedSections, setExpandedSections] = useState<Record<TaxCodeType, boolean>>(createDefaultExpanded());
  const [pendingId, setPendingId] = useState<string>(field.value || '');
  const searchInputRef = useRef<HTMLInputElement>(null);
  const { isMobile } = useMobile();
  const sectionRefs = useRef<Record<TaxCodeType, HTMLDivElement | null>>({
    general: null,
    digital: null,
    services: null,
    physical: null,
  });

  const selected = field.value ? taxCodesById[field.value] : null;
  const previewId = hoveredId || pendingId || field.value || '';
  const preview = previewId ? taxCodesById[previewId] : undefined;

  const filteredByType = useMemo(() => {
    const term = search.trim().toLowerCase();
    if (!term) {
      return GROUPED_TAX_CODES;
    }

    const matches: Record<TaxCodeType, RawTaxCode[]> = {
      general: [],
      digital: [],
      services: [],
      physical: [],
    };

    SORTED_TAX_CODES.forEach((code) => {
      const match =
        code.id.toLowerCase().includes(term) ||
        code.name.en.toLowerCase().includes(term) ||
        code.name.zh.toLowerCase().includes(term) ||
        code.description.en.toLowerCase().includes(term) ||
        code.description.zh.toLowerCase().includes(term);

      if (match) {
        matches[code.type].push(code);
      }
    });

    return matches;
  }, [search]);

  const handleClose = () => {
    setAnchorEl(null);
    setDrawerOpen(false);
    setSearch('');
    setHoveredId(null);
    setExpandedSections(createDefaultExpanded());
    setPendingId(field.value || '');
  };

  const handleClear = (event: React.MouseEvent) => {
    event.stopPropagation();
    field.onChange('');
    setPendingId('');
    handleClose();
  };

  const handleSelect = (code: RawTaxCode) => {
    setPendingId(code.id);
    setHoveredId(null);
  };

  const handleConfirm = () => {
    if (!pendingId) return;
    field.onChange(pendingId);
    handleClose();
  };

  const displayValue = selected ? `${selected.name[language] || selected.name.en} (${selected.id})` : '';

  const hasResults = TAX_CODE_TYPES.some((type) => filteredByType[type].length > 0);
  const popoverOpen = Boolean(anchorEl);

  const toggleSection = (type: TaxCodeType) => {
    setExpandedSections((prev) => {
      if (prev[type]) {
        return { ...prev, [type]: false };
      }
      const next = createDefaultExpanded();
      Object.keys(next).forEach((key) => {
        next[key as TaxCodeType] = false;
      });
      next[type] = true;
      return next;
    });
    requestAnimationFrame(() => {
      const ref = sectionRefs.current[type];
      if (ref) {
        ref.scrollIntoView({ block: 'start', behavior: 'smooth' });
      }
    });
  };

  const onInputClick = (event: MouseEvent<HTMLElement>) => {
    if (disabled) return;
    if (isMobile) {
      setDrawerOpen(true);
    } else {
      setAnchorEl(event.currentTarget);
    }
  };

  const onPopoverClose = () => {
    handleClose();
  };

  useEffect(() => {
    if ((popoverOpen || drawerOpen) && searchInputRef.current) {
      searchInputRef.current.focus();
    }
    if (popoverOpen || drawerOpen) {
      setPendingId(field.value || '');
      setHoveredId(null);
    }
  }, [popoverOpen, drawerOpen, field.value]);

  useEffect(() => {
    if (search.trim()) {
      setExpandedSections({
        general: true,
        digital: true,
        services: true,
        physical: true,
      });
    } else {
      setExpandedSections(createDefaultExpanded());
    }
  }, [search]);

  const renderCategories = (options: {
    listPadding?: string | number;
    headerPadding?: string | number;
    itemBorder?: boolean;
    listProps?: Record<string, any>;
  }) =>
    TAX_CODE_TYPES.filter((type) => filteredByType[type].length > 0).map((type) => {
      const isExpanded = expandedSections[type];
      return (
        <Box
          key={type}
          ref={(el) => {
            sectionRefs.current[type] = el as HTMLDivElement;
          }}>
          <Collapse
            trigger={
              <Typography variant="body2" sx={{ fontWeight: 600, color: 'text.primary' }}>
                {translate(TYPE_TRANSLATION_KEYS[type])}
              </Typography>
            }
            expanded={isExpanded}
            onChange={() => toggleSection(type)}
            lazy
            timeout={200}
            style={{
              px: options.headerPadding ?? 1.5,
              py: 1,
              borderBottom: '1px solid',
              borderColor: 'divider',
              backgroundColor: 'background.paper',
            }}>
            <List dense disablePadding {...(options.listProps || {})} sx={{ contain: 'layout style' }}>
              {filteredByType[type].map((code) => {
                const isSelected = pendingId === code.id;
                const displayName = code.name[language] || code.name.en;
                const showIndicator = isSelected || hoveredId === code.id;
                return (
                  <TaxCodeItem
                    key={code.id}
                    code={code}
                    isSelected={isSelected}
                    displayName={displayName}
                    showIndicator={showIndicator}
                    itemBorder={options.itemBorder ?? false}
                    onSelect={handleSelect}
                    onHover={setHoveredId}
                  />
                );
              })}
            </List>
          </Collapse>
        </Box>
      );
    });

  const listContentDesktop = (
    <Box
      sx={{
        flex: 1,
        overflowY: 'auto',
        border: '1px solid',
        borderColor: 'divider',
        borderRadius: 1,
        bgcolor: 'background.paper',
        willChange: 'scroll-position',
        contain: 'layout style paint',
      }}>
      {hasResults ? (
        renderCategories({ headerPadding: 1.5, itemBorder: true })
      ) : (
        <Typography
          variant="body2"
          sx={{
            color: 'text.secondary',
            px: 2,
            py: 4,
          }}>
          {translate('admin.taxRate.noSuggestions')}
        </Typography>
      )}
    </Box>
  );

  const listContentMobile = (
    <Box
      sx={{
        flex: 1,
        overflowY: 'auto',
        px: 2,
        pb: 2,
        willChange: 'scroll-position',
        contain: 'layout style paint',
      }}>
      {hasResults ? (
        renderCategories({ headerPadding: 1.5, itemBorder: true })
      ) : (
        <Typography
          variant="body2"
          sx={{
            color: 'text.secondary',
            px: 2,
            py: 4,
          }}>
          {translate('admin.taxRate.noSuggestions')}
        </Typography>
      )}
    </Box>
  );

  const headerContent = (
    <>
      <TextField
        fullWidth
        inputRef={searchInputRef}
        value={search}
        onChange={(event) => setSearch(event.target.value)}
        placeholder={translate('admin.taxRate.searchPlaceholder')}
        slotProps={{
          input: {
            startAdornment: (
              <InputAdornment position="start">
                <Search fontSize="small" />
              </InputAdornment>
            ),
          },
        }}
        size="small"
      />
      {/* <Box
        sx={{
          border: '1px solid',
          borderColor: 'divider',
          borderRadius: 1,
          p: 2,
          bgcolor: 'background.default',
        }}>
        <Typography variant="overline" color="text.secondary">
          {translate('admin.taxRate.usePreset')}
        </Typography>
        <Typography variant="body2" sx={{ mt: 0.5 }}>
          {selected ? selected.name[language] || selected.name.en : translate('admin.taxRate.noPreset')}
        </Typography>
      </Box> */}
    </>
  );

  return (
    <>
      <TextField
        fullWidth
        value={displayValue}
        onClick={onInputClick}
        label={label}
        placeholder={placeholder}
        error={!!error}
        helperText={error?.message}
        disabled={disabled}
        slotProps={{
          input: {
            endAdornment: (
              <InputAdornment position="end">
                {field.value && !disabled && (
                  <IconButton size="small" onClick={handleClear} aria-label={translate('common.clear')}>
                    <Close fontSize="small" />
                  </IconButton>
                )}
                <KeyboardDoubleArrowRight fontSize="small" color="action" />
              </InputAdornment>
            ),
          },
          htmlInput: {
            readOnly: true,
          },
        }}
      />
      {!isMobile && (
        <Popover
          open={popoverOpen}
          anchorEl={anchorEl}
          onClose={onPopoverClose}
          anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
          transformOrigin={{ vertical: 'top', horizontal: 'left' }}
          slotProps={{
            paper: {
              sx: {
                width: { xs: '95vw', sm: 560, md: 720 },
                maxHeight: 560,
                display: 'flex',
                flexDirection: 'column',
                borderRadius: 2,
              },
            },
          }}>
          <Stack
            direction={{ xs: 'column', sm: 'row' }}
            spacing={0}
            sx={{ flex: 1, minHeight: { xs: 320, sm: 380 }, p: 3, pt: 2 }}>
            <Box sx={{ flex: 1.2, display: 'flex', flexDirection: 'column', gap: 2, pr: { sm: 3 } }}>
              <Box>
                <Typography variant="h6" sx={{ fontWeight: 600 }}>
                  {translate('admin.taxRate.taxCode')}
                </Typography>
                <Typography
                  variant="body2"
                  sx={{
                    color: 'text.secondary',
                  }}>
                  {translate('admin.taxRate.selectTaxCodeHint')}
                </Typography>
              </Box>
              {headerContent}
              <Divider />
              {listContentDesktop}
            </Box>

            <Divider orientation="vertical" flexItem sx={{ display: { xs: 'none', sm: 'block' } }} />

            <Box
              sx={{
                flex: 1,
                minWidth: 260,
                pl: { sm: 3 },
                pt: { xs: 3, sm: 0 },
                display: 'flex',
                flexDirection: 'column',
                gap: 2,
              }}>
              {preview ? (
                <>
                  <Typography variant="h6" sx={{ fontWeight: 600 }}>
                    {preview.name[language] || preview.name.en}
                  </Typography>
                  <Typography
                    variant="body2"
                    sx={{
                      color: 'text.secondary',
                    }}>
                    {preview.description[language] || preview.description.en}
                  </Typography>
                  <Typography
                    variant="caption"
                    sx={{
                      color: 'text.secondary',
                    }}>
                    {translate('admin.taxRate.taxCodeLabel', { code: preview.id })}
                  </Typography>
                </>
              ) : (
                <Typography
                  variant="body2"
                  sx={{
                    color: 'text.secondary',
                  }}>
                  {translate('admin.taxRate.previewPlaceholder')}
                </Typography>
              )}
            </Box>
          </Stack>
          <Divider />
          <Stack direction="row" spacing={1} sx={{ px: 3, py: 2, justifyContent: 'flex-end' }}>
            <Button variant="text" size="small" onClick={onPopoverClose}>
              {translate('common.cancel')}
            </Button>
            <Button
              variant="contained"
              size="small"
              onClick={handleConfirm}
              disabled={!pendingId || pendingId === field.value}>
              {translate('common.select')}
            </Button>
          </Stack>
        </Popover>
      )}
      {isMobile && (
        <Drawer
          anchor="bottom"
          open={drawerOpen}
          onClose={onPopoverClose}
          PaperProps={{
            sx: {
              borderTopLeftRadius: 16,
              borderTopRightRadius: 16,
            },
          }}>
          <Stack spacing={0} sx={{ height: '70vh', maxHeight: 'calc(100vh - 96px)' }}>
            <Box sx={{ px: 2, pt: 2, pb: 1, display: 'flex', flexDirection: 'column', gap: 2 }}>
              <Typography variant="h6" sx={{ fontWeight: 600 }}>
                {translate('admin.taxRate.taxCode')}
              </Typography>
              {headerContent}
            </Box>
            <Divider />
            {listContentMobile}
            <Divider />
            <Stack direction="row" spacing={1} sx={{ px: 2, py: 2, justifyContent: 'flex-end' }}>
              <Button variant="text" onClick={onPopoverClose}>
                {translate('common.cancel')}
              </Button>
              <Button variant="contained" onClick={handleConfirm} disabled={!pendingId || pendingId === field.value}>
                {translate('common.select')}
              </Button>
            </Stack>
          </Stack>
        </Drawer>
      )}
    </>
  );
}

export default function TaxCodeSelect({
  name = 'tax_code',
  label = '',
  placeholder = '',
  required = false,
  disabled = false,
}: TaxCodeSelectProps) {
  const { t, locale } = useLocaleContext();
  const { control } = useFormContext();
  const language: LocaleKey = locale.startsWith('zh') ? 'zh' : 'en';

  return (
    <Controller
      name={name}
      control={control}
      rules={{ required: required ? t('common.required') : false }}
      render={({ field, fieldState }) => (
        <TaxCodePicker
          field={field}
          error={fieldState.error}
          disabled={disabled}
          label={label ?? t('admin.taxRate.taxCode')}
          placeholder={placeholder || t('admin.taxRate.selectTaxCode')}
          language={language}
          translate={t}
        />
      )}
    />
  );
}
