'use client';

import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
import { useCryptoContext } from '@/contexts/cryptoProvider';
import useTickers from '@/hooks/useTickers';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCaretUp, faCaretDown } from '@fortawesome/free-solid-svg-icons';
import { formatPrice, formatChangeRate, getChangeClass } from '@/lib/utils/crypto';
import type { TickerRestData } from '@/types/crypto';
import './sidebar.scss';

const QUOTE_TABS = ['KRW', 'BTC', 'USDT'] as const;

type SortKey = 'name' | 'price' | 'change' | 'volume';
type SortDir = 'asc' | 'desc';
type NameMode = 'kor' | 'eng';

type Props = {
	initialTickers?: TickerRestData[];
};

export default function CryptoSidebar({ initialTickers }: Props) {
	const { selectedMarket, setSelectedMarket, quoteMarket, setQuoteMarket, setTickers: setContextTickers, setTickerMeta: setContextMeta } = useCryptoContext();
	const { tickers, meta } = useTickers(quoteMarket, quoteMarket === 'KRW' ? initialTickers : undefined);
	const [search, setSearch] = useState('');
	const [sortKey, setSortKey] = useState<SortKey | null>(null);
	const [sortDir, setSortDir] = useState<SortDir>('desc');
	const [nameMode, setNameMode] = useState<NameMode>('kor');
	const prevPricesRef = useRef<Map<string, number>>(new Map());

	const handleSort = useCallback((key: SortKey) => {
		if (key === 'name' && sortKey === 'name') {
			setNameMode((prev) => prev === 'kor' ? 'eng' : 'kor');
		} else if (sortKey === key) {
			setSortDir((prev) => prev === 'desc' ? 'asc' : 'desc');
		} else {
			setSortKey(key);
			setSortDir(key === 'name' ? 'asc' : 'desc');
		}
	}, [sortKey]);

	// tickers를 context에 공유
	useEffect(() => {
		setContextTickers(tickers);
	}, [tickers, setContextTickers]);

	useEffect(() => {
		setContextMeta(meta);
	}, [meta, setContextMeta]);

	const sortedTickers = useMemo(() => {
		const arr = Array.from(tickers.values());
		const keyword = search.toLowerCase().trim();

		const filtered = keyword
			? arr.filter((t) => {
				const m = meta.get(t.market);
				return t.symbol.toLowerCase().includes(keyword) ||
					t.market.toLowerCase().includes(keyword) ||
					(m?.korName && m.korName.includes(keyword));
			})
			: arr;

		if (!sortKey) {
			return filtered.sort((a, b) => b.accTradePrice24h - a.accTradePrice24h);
		}

		const dir = sortDir === 'asc' ? 1 : -1;
		return filtered.sort((a, b) => {
			if (sortKey === 'name') {
				const aName = nameMode === 'kor' ? (meta.get(a.market)?.korName ?? a.symbol) : a.symbol;
				const bName = nameMode === 'kor' ? (meta.get(b.market)?.korName ?? b.symbol) : b.symbol;
				return dir * aName.localeCompare(bName, nameMode === 'kor' ? 'ko' : 'en');
			}
			if (sortKey === 'price') {
				return dir * (a.tradePrice - b.tradePrice);
			}
			if (sortKey === 'change') {
				return dir * (a.signedChangeRate - b.signedChangeRate);
			}
			return dir * (a.accTradePrice24h - b.accTradePrice24h);
		});
	}, [tickers, search, meta, sortKey, sortDir, nameMode]);

	// 시세 변동 보더 플래시 애니메이션
	useEffect(() => {
		for (const [market, ticker] of tickers) {
			const prev = prevPricesRef.current.get(market);
			if (prev !== undefined && prev !== ticker.tradePrice) {
				const direction = ticker.tradePrice > prev ? 'up' : 'down';
				const el = document.querySelector(`[data-market="${market}"]`) as HTMLElement | null;
				if (el) {
					el.classList.remove('flash-up', 'flash-down');
					void el.offsetWidth; // force reflow
					el.classList.add(`flash-${direction}`);
				}
			}
			prevPricesRef.current.set(market, ticker.tradePrice);
		}
	}, [tickers]);

	return (
		<div className='crypto-sidebar'>
			<div className='sidebar-tabs'>
				{QUOTE_TABS.map((tab) => (
					<button
						key={tab}
						type='button'
						className={`tab ${quoteMarket === tab ? 'active' : ''}`}
						onClick={() => setQuoteMarket(tab)}
					>
						{tab}
					</button>
				))}
			</div>
			<div className='sidebar-search'>
				<input
					type='text'
					placeholder='코인 검색...'
					value={search}
					onChange={(e) => setSearch(e.target.value)}
				/>
			</div>
			<div className='sidebar-sort'>
				<button
					type='button'
					className={sortKey === 'name' ? 'active' : ''}
					onClick={() => handleSort('name')}
				>
					{nameMode === 'kor' ? '한글명' : '영문명'}
				</button>
				<button
					type='button'
					className={sortKey === 'price' ? 'active' : ''}
					onClick={() => handleSort('price')}
				>
					현재가
					<FontAwesomeIcon icon={sortKey === 'price' && sortDir === 'asc' ? faCaretUp : faCaretDown} />
				</button>
				<button
					type='button'
					className={sortKey === 'change' ? 'active' : ''}
					onClick={() => handleSort('change')}
				>
					전일대비
					<FontAwesomeIcon icon={sortKey === 'change' && sortDir === 'asc' ? faCaretUp : faCaretDown} />
				</button>
				<button
					type='button'
					className={sortKey === 'volume' ? 'active' : ''}
					onClick={() => handleSort('volume')}
				>
					거래대금
					<FontAwesomeIcon icon={sortKey === 'volume' && sortDir === 'asc' ? faCaretUp : faCaretDown} />
				</button>
			</div>
			<div className='sidebar-list'>
				{sortedTickers.map((ticker) => {
					const tickerMeta = meta.get(ticker.market);
					return (
						<button
							key={ticker.market}
							type='button'
							className={`sidebar-item ${selectedMarket === ticker.market ? 'active' : ''}`}
							data-market={ticker.market}
							onClick={() => setSelectedMarket(ticker.market)}
						>
							<div className='item-info'>
								<span className='item-name'>{nameMode === 'kor' ? (tickerMeta?.korName ?? ticker.symbol) : ticker.symbol}</span>
								<span className='item-symbol'>{nameMode === 'kor' ? ticker.symbol : (tickerMeta?.korName ?? '')}</span>
							</div>
							<div className='item-price'>
								<span className={`price ${getChangeClass(ticker.change)}`}>
									{formatPrice(ticker.tradePrice)}
								</span>
								<span className={`change ${getChangeClass(ticker.change)}`}>
									{formatChangeRate(ticker.signedChangeRate)}
								</span>
							</div>
						</button>
					);
				})}
				{sortedTickers.length === 0 && (
					<div className='sidebar-empty'>검색 결과가 없습니다.</div>
				)}
			</div>
		</div>
	);
}