'use client';

import { useCallback, useEffect, useState } from 'react';
import Link from 'next/link';
import { useRouter, useSearchParams } from 'next/navigation';
import { Gamepad2, Package, Ticket } from 'lucide-react';
import { fetchApi } from '@/lib/utils/client';
import Loading from '@/app/component/Loading';
import Pagination from '@/app/component/Pagination';
import type {
	ProductListResponse,
	ProductListRow,
	ProductType,
	SortKey,
	GameOption,
	GameListResponse
} from '@/types/store';
import { SORT_OPTIONS } from '@/types/store';

const PER_PAGE = 20;

const TYPE_BADGE_CLASS: Record<ProductType, string> = {
	1: 'bg-sky-100 text-sky-800 dark:bg-sky-900/40 dark:text-sky-300',
	2: 'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300'
};

const TYPE_LABEL: Record<ProductType, string> = { 1: '실물', 2: '쿠폰' };

function TypeBadge({ type }: { type: ProductType })
{
	const Icon = type === 2 ? Ticket : Package;

	return (
		<span
			title={TYPE_LABEL[type]}
			aria-label={TYPE_LABEL[type]}
			className={`inline-flex items-center justify-center p-1 rounded ${TYPE_BADGE_CLASS[type]}`}
		>
			<Icon className="size-3" />
		</span>
	);
}

function formatPrice(n: number): string
{
	return n.toLocaleString('ko-KR');
}

export default function StorePage()
{
	const router = useRouter();
	const search = useSearchParams();

	const initialKeyword = search.get('keyword') ?? '';
	const initialType = search.get('type') ?? '';
	const initialGameID = search.get('gameID') ?? '';
	const initialSort = (search.get('sort') as SortKey|null) ?? 'latest';
	const initialPage = (() => {
		const raw = parseInt(search.get('page') ?? '1', 10);
		return Number.isNaN(raw) || raw < 1 ? 1 : raw;
	})();

	const [products, setProducts] = useState<ProductListRow[]>([]);
	const [games, setGames] = useState<GameOption[]>([]);
	const [total, setTotal] = useState(0);
	const [loading, setLoading] = useState(true);

	const [keyword, setKeyword] = useState(initialKeyword);
	const [submittedKeyword, setSubmittedKeyword] = useState(initialKeyword);
	const [typeFilter, setTypeFilter] = useState<string>(initialType);
	const [gameIDFilter, setGameIDFilter] = useState<string>(initialGameID);
	const [sort, setSort] = useState<SortKey>(initialSort);
	const [page, setPage] = useState<number>(initialPage);

	// 게임 목록은 mount 시 1회만 fetch
	useEffect(() => {
		(async () => {
			const res = await fetchApi<GameListResponse>('/api/store/games', { silent: true });

			if (res.success && res.data) {
				setGames(res.data.list);
			}
		})();
	}, []);

	const load = useCallback(async () => {
		setLoading(true);

		const params = new URLSearchParams();
		params.set('page', String(page));
		params.set('perPage', String(PER_PAGE));
		params.set('sort', sort);

		if (submittedKeyword) {
			params.set('keyword', submittedKeyword);
		}

		if (typeFilter) {
			params.set('type', typeFilter);
		}

		if (gameIDFilter) {
			params.set('gameID', gameIDFilter);
		}

		const res = await fetchApi<ProductListResponse>(`/api/store/products?${params.toString()}`, { silent: true });

		if (res.success && res.data) {
			setProducts(res.data.list);
			setTotal(res.data.total);
		}
		else {
			setProducts([]);
			setTotal(0);
		}

		setLoading(false);
	}, [submittedKeyword, typeFilter, gameIDFilter, sort, page]);

	// 필터/정렬/게임/검색 키워드 변경 시 1페이지로 리셋
	useEffect(() => {
		setPage(1);
	}, [sort, typeFilter, gameIDFilter, submittedKeyword]);

	// page 변경 또는 의존 필터/검색 변경 시 자동 재조회
	useEffect(() => {
		load();
	}, [sort, typeFilter, gameIDFilter, submittedKeyword, page]); // eslint-disable-line react-hooks/exhaustive-deps

	const syncUrl = useCallback((nextPage: number, kw: string = submittedKeyword) => {
		const params = new URLSearchParams();

		if (kw) {
			params.set('keyword', kw);
		}

		if (typeFilter) {
			params.set('type', typeFilter);
		}

		if (gameIDFilter) {
			params.set('gameID', gameIDFilter);
		}

		if (sort !== 'latest') {
			params.set('sort', sort);
		}

		if (nextPage > 1) {
			params.set('page', String(nextPage));
		}

		router.replace(`/store${params.toString() ? `?${params.toString()}` : ''}`);
	}, [submittedKeyword, typeFilter, gameIDFilter, sort, router]);

	const handleSearch = (e: React.FormEvent) => {
		e.preventDefault();
		const trimmed = keyword.trim();
		setSubmittedKeyword(trimmed);
		setPage(1);
		syncUrl(1, trimmed);
	};

	const handlePageChange = (next: number) => {
		setPage(next);
		syncUrl(next);
		if (typeof window !== 'undefined') {
			window.scrollTo({ top: 0, behavior: 'smooth' });
		}
	};

	return (
		<div className="mx-auto px-2 sm:px-4 py-6">
			<h1 className="text-2xl font-bold mb-4">
				상점{' '}
				<span className="text-red-600 dark:text-red-400 text-xl font-extrabold">
					({total.toLocaleString()}개)
				</span>
			</h1>

			<form onSubmit={handleSearch} className="mb-6 space-y-2 sm:space-y-0 sm:flex sm:flex-wrap sm:items-center sm:gap-2">
				<div className="grid grid-cols-3 gap-2 sm:contents">
					<select
						title="sort"
						value={sort}
						onChange={(e) => { setSort(e.target.value as SortKey); }}
						className="w-full sm:w-auto border rounded px-3 py-2 text-sm bg-white dark:bg-neutral-900"
					>
						{SORT_OPTIONS.map(o => (
							<option key={o.value} value={o.value}>{o.label}</option>
						))}
					</select>

					<select
						title="gameID"
						value={gameIDFilter}
						onChange={(e) => { setGameIDFilter(e.target.value); }}
						className="w-full sm:w-auto border rounded px-3 py-2 text-sm bg-white dark:bg-neutral-900"
					>
						<option value="">전체 게임</option>
						{games.map(g => (
							<option key={g.id} value={g.id}>{g.korName}</option>
						))}
					</select>

					<select
						title="type"
						value={typeFilter}
						onChange={(e) => { setTypeFilter(e.target.value); }}
						className="w-full sm:w-auto border rounded px-3 py-2 text-sm bg-white dark:bg-neutral-900"
					>
						<option value="">전체 유형</option>
						<option value="1">실물</option>
						<option value="2">쿠폰</option>
					</select>
				</div>

				<input
					type="search"
					value={keyword}
					onChange={(e) => { setKeyword(e.target.value); }}
					placeholder="상품명 또는 게임 검색"
					className="w-full sm:flex-1 border rounded px-3 py-2 text-sm bg-white dark:bg-neutral-900"
					maxLength={100}
				/>

				<button type="submit" className="w-full sm:w-auto bg-blue-600 text-white px-4 py-2 rounded text-sm hover:bg-blue-700">
					검색
				</button>
			</form>

			{loading ? (
				<Loading />
			) : products.length === 0 ? (
				<div className="text-center py-20 text-neutral-500">판매 중인 상품이 없습니다.</div>
			) : (
				<>
					<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
						{products.map((p) => (
							<Link
								key={p.id}
								href={`/store/${p.id}`}
								className="group block rounded-lg border border-neutral-200 dark:border-neutral-800 overflow-hidden hover:shadow-lg transition-shadow bg-white dark:bg-neutral-900"
							>
								<div className="aspect-square bg-neutral-100 dark:bg-neutral-800 overflow-hidden flex items-center justify-center relative">
									{p.thumbnail ? (
										// eslint-disable-next-line @next/next/no-img-element
										<img
											src={p.thumbnail}
											alt={p.name}
											className="w-full h-full max-w-[calc(100%/1.6)] object-scale-down group-hover:scale-105 transition-transform duration-300"
										/>
									) : (
										<span className="text-neutral-400 text-xs">이미지 없음</span>
									)}

									{p.stock === 0 && (
										<div className="absolute inset-0 bg-black/50 flex items-center justify-center">
											<span className="text-white text-sm font-bold tracking-widest">SOLD OUT</span>
										</div>
									)}
								</div>

								<div className="p-3">
									<div className="flex items-center gap-1.5 mb-1.5">
										<TypeBadge type={p.type} />
										<Gamepad2 className="size-3.5 shrink-0 text-purple-600 dark:text-purple-400" />
										<span className="text-xs font-semibold truncate text-purple-600 dark:text-purple-400" title={p.gameName}>
											{p.gameName}
										</span>
									</div>

									<div className="text-sm font-semibold mb-1.5 line-clamp-2 min-h-[1.6rem]" title={p.name}>
										{p.name}
									</div>

									{p.discountType !== 0 && p.salePrice !== p.price ? (
										<>
											<div className="text-lg font-extrabold text-red-600 dark:text-red-400">
												{formatPrice(p.salePrice)}P
											</div>
											<div className="flex items-baseline gap-1.5 text-xs">
												<span className="line-through text-yellow-600 dark:text-yellow-400">{formatPrice(p.price)}P</span>
												<span className="font-semibold text-green-600 dark:text-green-400">
													{p.discountType === 1 ? `-${p.discountValue}%` : `-${formatPrice(p.discountValue)}P`}
												</span>
											</div>
										</>
									) : (
										<div className="text-lg font-extrabold text-red-600 dark:text-red-400">
											{formatPrice(p.price)}P
										</div>
									)}
								</div>
							</Link>
						))}
					</div>

					<hr className="my-4 border-neutral-200 dark:border-neutral-800" />

					<Pagination total={total} page={page} perPage={PER_PAGE} onChange={handlePageChange} />
				</>
			)}
		</div>
	);
}
