import React, { useState, useEffect, useCallback, useRef } from 'react';
import { Autocomplete, TextField, CircularProgress, Box, SxProps, Theme, IconButton, Typography, Divider } from '@mui/material';
import { Star, StarBorder } from '@mui/icons-material';
import upbitApiService, { UpbitMarket, UpbitTicker } from '../services/upbitApi';
import { toggleFavorite, getAllFavorites } from '../services/cryptoFavoriteApi';

interface CryptoNameComboBoxProps {
  value: string;
  onChange: (symbol: string, cryptoInfo?: UpbitMarket) => void;
  disabled?: boolean;
  label?: string;
  placeholder?: string;
  helperText?: string;
  size?: 'small' | 'medium';
  sx?: SxProps<Theme>;
}

type SortKey = 'favorite' | 'korean_name' | 'trade_price' | 'signed_change_rate' | 'acc_trade_price_24h';
type SortOrder = 'asc' | 'desc';

const HEADER_ROW_HEIGHT = 30;

const formatPrice = (price?: number): string => {
  if (price == null) return '-';
  if (price >= 1000) return price.toLocaleString();
  if (price >= 1) return price.toLocaleString(undefined, { maximumFractionDigits: 4 });
  return price.toLocaleString(undefined, { maximumFractionDigits: 8 });
};

const formatChangeRate = (rate?: number): string => {
  if (rate == null) return '-';
  const percent = rate * 100;
  const sign = percent > 0 ? '+' : '';
  return `${sign}${percent.toFixed(2)}%`;
};

const formatTradeValue = (value?: number): string => {
  if (value == null) return '-';
  if (value >= 1_0000_0000_0000) return `${(value / 1_0000_0000_0000).toFixed(2)}조`;
  if (value >= 1_0000_0000) return `${(value / 1_0000_0000).toFixed(1)}억`;
  if (value >= 1_0000) return `${(value / 1_0000).toFixed(1)}만`;
  return value.toLocaleString();
};

const compareNumber = (a?: number, b?: number): number => {
  const av = a ?? Number.NEGATIVE_INFINITY;
  const bv = b ?? Number.NEGATIVE_INFINITY;
  return av - bv;
};

const compareString = (a?: string, b?: string): number => (a ?? '').localeCompare(b ?? '', 'ko');


const CryptoNameComboBox: React.FC<CryptoNameComboBoxProps> = ({
  value,
  onChange,
  disabled = false,
  label = '암호화폐명',
  placeholder = '암호화폐명을 입력하거나 선택하세요',
  helperText,
  size = 'medium',
  sx,
}) => {
  const [cryptos, setCryptos] = useState<UpbitMarket[]>([]);
  const [loading, setLoading] = useState(false);
  const [inputValue, setInputValue] = useState('');
  const [selectedCrypto, setSelectedCrypto] = useState<UpbitMarket | null>(null);
  const [isOpen, setIsOpen] = useState(false);
  const [isUserTyping, setIsUserTyping] = useState(false);
  const [favorites, setFavorites] = useState<Record<string, boolean>>({});
  const [tickerMap, setTickerMap] = useState<Record<string, UpbitTicker>>({});
  const [sortKey, setSortKey] = useState<SortKey>('favorite');
  const [sortOrder, setSortOrder] = useState<SortOrder>('desc');
  const [dropdownWidth, setDropdownWidth] = useState<number>(520);
  const inputRef = useRef<HTMLInputElement>(null);
  const comboRootRef = useRef<HTMLDivElement>(null);

  const fetchTickers = useCallback(async (markets: string[]) => {
    if (markets.length === 0) return;
    const chunkSize = 80;
    const chunks: string[][] = [];
    for (let i = 0; i < markets.length; i += chunkSize) {
      chunks.push(markets.slice(i, i + chunkSize));
    }

    try {
      const results = await Promise.all(chunks.map((chunk) => upbitApiService.getCurrentPrice(chunk)));
      const next: Record<string, UpbitTicker> = {};
      results.flat().forEach((ticker) => {
        if (ticker?.market) next[ticker.market] = ticker;
      });
      setTickerMap(next);
    } catch (error) {
      console.error('티커 로드 실패:', error);
    }
  }, []);

  // 컴포넌트 마운트 시 암호화폐 목록 로드
  useEffect(() => {
    const loadAllCryptos = async () => {
      try {
        setLoading(true);
        const activeCryptos = await upbitApiService.getActiveCryptos();
        const convertedCryptos = activeCryptos.map(crypto => ({
          market: crypto.symbol,
          korean_name: crypto.koreanName,
          english_name: crypto.englishName
        }));
        setCryptos(convertedCryptos);
        await fetchTickers(convertedCryptos.map((c) => c.market));
        
        // 즐겨찾기 목록 한 번에 로드
        try {
          const favList = await getAllFavorites();
          const favMap: Record<string, boolean> = {};
          favList.forEach(fav => {
            favMap[fav.symbol] = true;
          });
          setFavorites(favMap);
        } catch (error) {
          console.error('즐겨찾기 목록 로드 실패:', error);
          setFavorites({});
        }
      } catch (error) {
        console.error('암호화폐 목록 로드 실패:', error);
        const defaultCryptos = [
          { market: 'KRW-BTC', korean_name: '비트코인', english_name: 'Bitcoin' },
          { market: 'KRW-ETH', korean_name: '이더리움', english_name: 'Ethereum' },
          { market: 'KRW-XRP', korean_name: '리플', english_name: 'Ripple' },
          { market: 'KRW-ADA', korean_name: '에이다', english_name: 'Cardano' },
          { market: 'KRW-SOL', korean_name: '솔라나', english_name: 'Solana' },
        ];
        setCryptos(defaultCryptos);
      } finally {
        setLoading(false);
      }
    };

    loadAllCryptos();
  }, [fetchTickers]);

  useEffect(() => {
    if (!isOpen || cryptos.length === 0) return;
    void fetchTickers(cryptos.map((c) => c.market));
  }, [isOpen, cryptos, fetchTickers]);

  // 부모에서 종목이 바뀌면(알림·FAB 등) 검색 중 플래그 해제 → 아래 동기화 effect가 한글명 반영
  useEffect(() => {
    setIsUserTyping(false);
  }, [value]);

  // 외부 value 변경 시 선택 상태 동기화
  useEffect(() => {
    // 사용자가 타이핑 중이거나 드롭다운이 열려있을 때는 동기화하지 않음
    if (isUserTyping || isOpen) {
      return;
    }
    
    if (value && cryptos.length > 0) {
      const crypto = cryptos.find(c => c.market === value);
      if (crypto && crypto !== selectedCrypto) {
        setSelectedCrypto(crypto);
        setInputValue(crypto.korean_name);
      }
    } else if (!value) {
      setSelectedCrypto(null);
      setInputValue('');
    }
  }, [value, cryptos, selectedCrypto, isUserTyping, isOpen]);

  // 필터링된 종목 목록
  // - 드롭다운이 열릴 때 (isOpen=true) 사용자가 타이핑 중일 때만 필터링
  // - 목록을 펼칠 때는 모든 종목 표시
  // - 즐겨찾기를 먼저 표시하도록 정렬
  const getFilteredOptions = useCallback(() => {
    let filteredList: UpbitMarket[];
    
    // 사용자가 타이핑 중일 때만 필터링
    if (isUserTyping && inputValue) {
      const lowerCaseInput = inputValue.toLowerCase();
      filteredList = cryptos.filter(crypto => {
        if (!crypto || !crypto.korean_name || !crypto.english_name || !crypto.market) return false;
        return crypto.korean_name.toLowerCase().includes(lowerCaseInput) ||
               crypto.english_name.toLowerCase().includes(lowerCaseInput) ||
               crypto.market.toLowerCase().includes(lowerCaseInput);
      });
    } else {
      // 목록을 펼칠 때는 모든 종목 표시
      filteredList = cryptos;
    }
    
    return [...filteredList].sort((a, b) => {
      const tA = tickerMap[a.market];
      const tB = tickerMap[b.market];
      let cmp = 0;

      if (sortKey === 'favorite') {
        cmp = Number(!!favorites[a.market]) - Number(!!favorites[b.market]);
      } else if (sortKey === 'korean_name') {
        cmp = compareString(a.korean_name, b.korean_name);
      } else if (sortKey === 'trade_price') {
        cmp = compareNumber(tA?.trade_price, tB?.trade_price);
      } else if (sortKey === 'signed_change_rate') {
        cmp = compareNumber(tA?.signed_change_rate, tB?.signed_change_rate);
      } else if (sortKey === 'acc_trade_price_24h') {
        cmp = compareNumber(tA?.acc_trade_price_24h, tB?.acc_trade_price_24h);
      }

      if (cmp === 0) {
        cmp = compareString(a.korean_name, b.korean_name);
      }
      return sortOrder === 'asc' ? cmp : -cmp;
    });
  }, [cryptos, inputValue, isUserTyping, favorites, tickerMap, sortKey, sortOrder]);

  const handleSort = useCallback((key: SortKey) => {
    if (sortKey === key) {
      setSortOrder((prev) => (prev === 'asc' ? 'desc' : 'asc'));
      return;
    }
    setSortKey(key);
    setSortOrder(key === 'korean_name' ? 'asc' : 'desc');
  }, [sortKey]);

  // 드롭다운 열림/닫힘 핸들러
  const handleOpen = () => {
    const inputWidth = comboRootRef.current?.clientWidth ?? 0;
    // 입력란 좌측 기준으로 붙이고, 너무 좁지 않게 최소 폭 보장
    setDropdownWidth(Math.max(520, inputWidth));
    setIsOpen(true);
    setIsUserTyping(false); // 목록을 펼칠 때는 필터링 비활성화
  };

  const handleClose = () => {
    setIsOpen(false);
    setIsUserTyping(false);
    // 닫힐 때 입력값이 비어있거나 매칭되는 종목이 없으면 선택된 종목으로 복원
    if (selectedCrypto && !inputValue) {
      setInputValue(selectedCrypto.korean_name);
    } else if (!selectedCrypto && !inputValue) {
      // 선택된 종목도 없고 입력값도 없으면 그대로 유지
      setInputValue('');
    }
  };

  // 종목 선택 핸들러 — 목록에서 고를 때만 부모 onChange(차트 갱신). Clear는 검색칸만 비움.
  const handleChange = (event: React.SyntheticEvent, newValue: UpbitMarket | null) => {
    if (newValue) {
      setSelectedCrypto(newValue);
      setIsUserTyping(false);
      setInputValue(newValue.korean_name);
      onChange(newValue.market, newValue);
      return;
    }
    // Clear(X): 실제 선택·부모 symbol·차트는 유지, 입력만 비워 다음 종목 검색 가능
    const keep =
      (value && cryptos.length > 0 ? cryptos.find((c) => c.market === value) : null) ?? selectedCrypto;
    if (keep) {
      setSelectedCrypto(keep);
      setInputValue('');
      setIsUserTyping(true);
    } else {
      setSelectedCrypto(null);
      setInputValue('');
      setIsUserTyping(false);
    }
  };

  // 입력 변경 핸들러
  const handleInputChange = (event: React.SyntheticEvent, newInputValue: string, reason: string) => {
    setInputValue(newInputValue);
    
    // 사용자가 키보드로 직접 입력하거나 clear할 때 필터링 활성화
    if (reason === 'input' || reason === 'clear') {
      setIsUserTyping(true);
    } else if (reason === 'reset') {
      // 선택이 완료되었을 때만 타이핑 상태 해제
      setIsUserTyping(false);
    }
  };

  // 키 입력 핸들러 - 엔터키 처리
  const handleKeyDown = (event: React.KeyboardEvent) => {
    if (event.key === 'Enter' && isUserTyping) {
      const filteredOptions = getFilteredOptions();
      // 필터링된 결과가 하나이면 해당 종목 선택
      if (filteredOptions.length === 1) {
        const crypto = filteredOptions[0];
        setSelectedCrypto(crypto);
        setInputValue(crypto.korean_name);
        setIsUserTyping(false);
        setIsOpen(false);
        onChange(crypto.market, crypto);
      } else if (filteredOptions.length > 1) {
        // 필터링된 결과 중 정확히 일치하는 종목이 있으면 선택
        const exactMatch = filteredOptions.find(c => 
          c.korean_name.toLowerCase() === inputValue.toLowerCase() ||
          c.english_name.toLowerCase() === inputValue.toLowerCase() ||
          c.market.toLowerCase() === inputValue.toLowerCase()
        );
        if (exactMatch) {
          setSelectedCrypto(exactMatch);
          setInputValue(exactMatch.korean_name);
          setIsUserTyping(false);
          setIsOpen(false);
          onChange(exactMatch.market, exactMatch);
        }
      }
    }
  };

  // 즐겨찾기 토글 핸들러
  const handleToggleFavorite = async (e: React.MouseEvent, option: UpbitMarket) => {
    e.stopPropagation();
    e.preventDefault();
    try {
      const result = await toggleFavorite({
        symbol: option.market,
        koreanName: option.korean_name,
        englishName: option.english_name,
      });
      setFavorites(prev => ({ ...prev, [option.market]: result }));
    } catch (error) {
      console.error('즐겨찾기 토글 실패:', error);
    }
  };

  return (
    <Box ref={comboRootRef}>
    <Autocomplete
      options={getFilteredOptions()}
      getOptionLabel={(option) => option.korean_name}
      isOptionEqualToValue={(option, val) => option.market === val.market}
      loading={loading}
      disabled={disabled}
      value={selectedCrypto}
      open={isOpen}
      onOpen={handleOpen}
      onClose={handleClose}
      onChange={handleChange}
      inputValue={inputValue}
      onInputChange={handleInputChange}
      filterOptions={(options) => options} // 커스텀 필터링 사용
      size={size}
      freeSolo={false} // 목록에서만 선택 가능
      clearOnBlur={false} // 포커스를 잃어도 입력값 유지
      selectOnFocus={false} // 포커스 시 자동 선택 안함
      handleHomeEndKeys={false}
      disableClearable={false} // X 버튼 표시
      sx={sx}
      renderInput={(params) => (
        <TextField
          {...params}
          inputRef={inputRef}
          label={label || undefined}
          placeholder={placeholder}
          helperText={helperText || undefined}
          fullWidth
          size={size}
          onKeyDown={handleKeyDown}
          InputProps={{
            ...params.InputProps,
            endAdornment: (
              <React.Fragment>
                {loading ? <CircularProgress color="inherit" size={20} /> : null}
                {params.InputProps.endAdornment}
              </React.Fragment>
            ),
          }}
        />
      )}
      renderOption={(props, option, state) => {
        const isFav = favorites[option.market] || false;
        const ticker = tickerMap[option.market];
        const options = getFilteredOptions();
        const currentIndex = state.index;
        const isFirstRow = currentIndex === 0;
        
        // 현재 항목이 즐겨찾기이고, 다음 항목이 일반 항목인지 확인
        const nextOption = options[currentIndex + 1];
        const isLastFavorite = isFav && nextOption && !favorites[nextOption.market];
        
        return (
          <React.Fragment key={option.market}>
            {isFirstRow && (
              <Box
                sx={{
                  position: 'sticky',
                  top: 0,
                  zIndex: 1,
                  display: 'grid',
                  gridTemplateColumns: '28px minmax(120px, 1.2fr) minmax(92px, 0.9fr) minmax(82px, 0.8fr) minmax(82px, 0.8fr)',
                  alignItems: 'center',
                  px: 1.5,
                  height: HEADER_ROW_HEIGHT,
                  bgcolor: 'background.paper',
                  borderBottom: '1px solid',
                  borderColor: 'divider',
                }}
              >
                <Typography
                  variant="caption"
                  sx={{ textAlign: 'center', cursor: 'pointer', userSelect: 'none' }}
                  onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
                  onClick={(e) => { e.preventDefault(); e.stopPropagation(); handleSort('favorite'); }}
                >
                  즐겨
                </Typography>
                <Typography
                  variant="caption"
                  sx={{ cursor: 'pointer', userSelect: 'none' }}
                  onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
                  onClick={(e) => { e.preventDefault(); e.stopPropagation(); handleSort('korean_name'); }}
                >
                  한글명 {sortKey === 'korean_name' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
                </Typography>
                <Typography
                  variant="caption"
                  sx={{ textAlign: 'right', cursor: 'pointer', userSelect: 'none' }}
                  onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
                  onClick={(e) => { e.preventDefault(); e.stopPropagation(); handleSort('trade_price'); }}
                >
                  현재가 {sortKey === 'trade_price' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
                </Typography>
                <Typography
                  variant="caption"
                  sx={{ textAlign: 'right', cursor: 'pointer', userSelect: 'none' }}
                  onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
                  onClick={(e) => { e.preventDefault(); e.stopPropagation(); handleSort('signed_change_rate'); }}
                >
                  전일대비 {sortKey === 'signed_change_rate' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
                </Typography>
                <Typography
                  variant="caption"
                  sx={{ textAlign: 'right', cursor: 'pointer', userSelect: 'none' }}
                  onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
                  onClick={(e) => { e.preventDefault(); e.stopPropagation(); handleSort('acc_trade_price_24h'); }}
                >
                  거래대금 {sortKey === 'acc_trade_price_24h' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
                </Typography>
              </Box>
            )}
            <Box 
              component="li" 
              {...props} 
              sx={{
                display: 'grid !important',
                gridTemplateColumns: '28px minmax(120px, 1.2fr) minmax(92px, 0.9fr) minmax(82px, 0.8fr) minmax(82px, 0.8fr) !important',
                alignItems: 'center !important',
                gap: 1,
                padding: '8px 12px !important',
              }}
            >
              <IconButton
                size="small"
                onClick={(e) => handleToggleFavorite(e, option)}
                sx={{ 
                  color: isFav ? '#fbbf24' : 'action.disabled',
                  padding: '2px',
                }}
              >
                {isFav ? <Star fontSize="small" /> : <StarBorder fontSize="small" />}
              </IconButton>

              {/* 한글명 */}
              <Box sx={{ minWidth: 0, display: 'flex', flexDirection: 'column' }}>
                <Typography sx={{ fontWeight: 'bold', fontSize: '14px' }}>
                  {option.korean_name}
                </Typography>
                <Typography sx={{ fontSize: '12px', color: 'text.secondary' }}>
                  {option.market.replace('KRW-', '')}
                </Typography>
              </Box>

              {/* 현재가 */}
              <Typography sx={{ textAlign: 'right', fontWeight: 600, fontSize: '13px' }}>
                {formatPrice(ticker?.trade_price)}
              </Typography>

              {/* 전일대비 */}
              <Typography
                sx={{
                  textAlign: 'right',
                  fontWeight: 600,
                  fontSize: '13px',
                  color:
                    (ticker?.signed_change_rate ?? 0) > 0
                      ? 'error.main'
                      : (ticker?.signed_change_rate ?? 0) < 0
                        ? 'info.main'
                        : 'text.secondary',
                }}
              >
                {formatChangeRate(ticker?.signed_change_rate)}
              </Typography>

              {/* 거래대금 */}
              <Typography sx={{ textAlign: 'right', fontSize: '12px', color: 'text.secondary' }}>
                {formatTradeValue(ticker?.acc_trade_price_24h)}
              </Typography>
            </Box>
            
            {/* 즐겨찾기와 일반 종목 사이 divider */}
            {isLastFavorite && (
              <Divider sx={{ my: 0.5 }} />
            )}
          </React.Fragment>
        );
      }}
      ListboxProps={{
        sx: {
          width: '100%',
          maxHeight: '70vh',
          pt: 0,
        },
      }}
      componentsProps={{
        popper: {
          style: {
            width: `${dropdownWidth}px`,
          },
          placement: 'bottom-start',
        },
        paper: {
          sx: {
            maxHeight: '72vh',
          },
        },
      }}
    />
    </Box>
  );
  
};

export default CryptoNameComboBox;
