'use client';

import { useEffect, useRef, useState } from 'react';
import Image from 'next/image';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlus, faImage, faPlay, faStop } from '@fortawesome/free-solid-svg-icons';
import { Checkbox } from '@/components/ui/checkbox';
import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog';
import { fetchApi } from '@/lib/utils/client';
import { useStudioContext } from '@/app/studio/context';
import { useAlertConfigContext } from '../context';
import type { AlertConfigItem } from '@/types/response/donation/alertConfig';
import { PER_PAGE_OPTIONS } from '@/constants/donation';

type Props = {
	items: AlertConfigItem[];
	loading: boolean;
	saving: boolean;
	checkedIDs: Set<number>;
	setCheckedIDs: React.Dispatch<React.SetStateAction<Set<number>>>;
	page: number;
	setPage: React.Dispatch<React.SetStateAction<number>>;
	perPage: number;
	setPerPage: React.Dispatch<React.SetStateAction<number>>;
	onNew: () => void;
	onEdit: (item: AlertConfigItem) => void;
	onBatchDelete: () => void;
};

export default function AlertListPanel({
	items,
	loading,
	saving,
	checkedIDs,
	setCheckedIDs,
	page,
	setPage,
	perPage,
	setPerPage,
	onNew,
	onEdit,
	onBatchDelete
}: Props) {
	const { channelID } = useStudioContext();
	const { setItems } = useAlertConfigContext();
	const [playingAudio, setPlayingAudio] = useState<number|null>(null);
	const [previewImageUrl, setPreviewImageUrl] = useState<string|null>(null);
	const [thumbErrors, setThumbErrors] = useState<Set<number>>(new Set());
	const [togglingIDs, setTogglingIDs] = useState<Set<number>>(new Set());
	const audioRef = useRef<HTMLAudioElement|null>(null);

	// ── 활성/비활성 토글 ─────────────────────────────
	const handleToggleActive = async (item: AlertConfigItem) => {
		if (!channelID || togglingIDs.has(item.id)) {
			return;
		}

		const next = !item.isActive;

		// 1) in-flight guard (race 방지)
		setTogglingIDs(prev => {
			const s = new Set(prev);
			s.add(item.id);
			return s;
		});

		// 2) optimistic update
		setItems(prev => prev.map(x => x.id === item.id ? { ...x, isActive: next } : x));

		try {
			const res = await fetchApi<{ id: number; isActive: boolean }>(
				`/api/studio/donation/alert/config/${item.id}/active`,
				{
					method: 'PATCH',
					body: { channelID, isActive: next },
					silent: true
				}
			);

			if (!res.success) {
				// 롤백
				setItems(prev => prev.map(x => x.id === item.id ? { ...x, isActive: item.isActive } : x));
				alert(res.message || '활성 상태 변경에 실패했습니다.');
			} else if (res.data && res.data.isActive !== next) {
				// 서버가 다른 값 반환 시 ground truth 반영
				setItems(prev => prev.map(x => x.id === item.id ? { ...x, isActive: res.data!.isActive } : x));
			}
		} catch (err) {
			// 네트워크/예외 → 롤백
			setItems(prev => prev.map(x => x.id === item.id ? { ...x, isActive: item.isActive } : x));
			alert(err instanceof Error ? err.message : '활성 상태 변경에 실패했습니다.');
		} finally {
			setTogglingIDs(prev => {
				const s = new Set(prev);
				s.delete(item.id);
				return s;
			});
		}
	};

	// ── 페이징 ───────────────────────────────────────
	const totalPages = Math.max(1, Math.ceil(items.length / perPage));
	const pagedItems = items.slice((page - 1) * perPage, page * perPage);

	const handlePerPageChange = (value: number) => {
		setPerPage(value);
		setPage(1);
	};

	// ── 전체선택 ─────────────────────────────────────
	const visibleIDs = pagedItems.map(i => i.id);
	const checkedCount = visibleIDs.filter(id => checkedIDs.has(id)).length;
	const allChecked = pagedItems.length > 0 && checkedCount === visibleIDs.length;
	const isIndeterminate = checkedCount > 0 && checkedCount < visibleIDs.length;

	const handleSelectAll = () => {
		setCheckedIDs(prev => {
			const next = new Set(prev);
			if (allChecked) {
				visibleIDs.forEach(id => next.delete(id));
			} else {
				visibleIDs.forEach(id => next.add(id));
			}
			return next;
		});
	};

	const handleToggleCheck = (id: number) => {
		setCheckedIDs(prev => {
			const next = new Set(prev);
			if (next.has(id)) {
				next.delete(id);
			} else {
				next.add(id);
			}
			return next;
		});
	};

	// ── 사운드 재생/정지 ─────────────────────────────
	const handlePlaySound = (itemId: number, soundUrl: string) => {
		// 이미 재생 중이면 정지
		if (playingAudio === itemId && audioRef.current) {
			audioRef.current.pause();
			audioRef.current = null;
			setPlayingAudio(null);
			return;
		}

		// 기존 재생 정지
		if (audioRef.current) {
			audioRef.current.pause();
			audioRef.current = null;
		}

		const audio = new Audio(soundUrl);
		audioRef.current = audio;
		setPlayingAudio(itemId);

		audio.play().catch(() => {});
		audio.addEventListener('ended', () => {
			setPlayingAudio(null);
			audioRef.current = null;
		});
	};

	// unmount 시 오디오 정리
	useEffect(() => {
		return () => {
			if (audioRef.current) {
				audioRef.current.pause();
				audioRef.current = null;
			}
		};
	}, []);

	return (
		<div className="alert-config__list-panel">
			<div className="alert-config__toolbar">
				<div className="alert-config__toolbar-left">
					<span className="alert-config__count">총 {items.length}개</span>
					{checkedIDs.size > 0 && (
						<span className="alert-config__count">({checkedIDs.size}개 선택)</span>
					)}
				</div>
				<div className="alert-config__toolbar-right">
					<select
						value={perPage}
						onChange={e => handlePerPageChange(Number(e.target.value))}
						className="alert-config__per-page"
						title="보여질 개수"
					>
						{PER_PAGE_OPTIONS.map(n => (
							<option key={n} value={n}>{n}개씩</option>
						))}
					</select>
					<button type="button" className="alert-config__btn" onClick={onNew}>
						<FontAwesomeIcon icon={faPlus} />
						추가
					</button>
					<button
						type="button"
						className="alert-config__btn alert-config__btn--danger"
						onClick={onBatchDelete}
						disabled={checkedIDs.size === 0 || saving}
					>
						삭제
					</button>
				</div>
			</div>

			<div className="alert-config__table-wrap">
				{loading ? (
					<div className="alert-config__empty">준비 중...</div>
				) : items.length === 0 ? (
					<div className="alert-config__empty">등록된 알림 설정이 없습니다.</div>
				) : (
					<table className="alert-config__table">
						<thead>
							<tr>
								<th className="alert-config__th--check">
									<Checkbox
										checked={allChecked} indeterminate={isIndeterminate}
										onCheckedChange={handleSelectAll}
										aria-label="전체선택"
									/>
								</th>
								<th>조건</th>
								<th>금액</th>
								<th>제목</th>
								<th>보낼 내용</th>
								<th>노출(초)</th>
								<th>활성</th>
								<th>미디어</th>
								<th>비고</th>
							</tr>
						</thead>
						<tbody>
							{pagedItems.map(item => {
								const isChecked = checkedIDs.has(item.id);
								const hasImage = item.enableImage && item.imageUrl;
								const hasSound = item.enableSound && item.soundUrl;
								return (
									<tr
										key={item.id}
										className={isChecked ? 'alert-config__row--checked' : ''}
									>
										<td className="alert-config__td--check">
											<Checkbox
												checked={isChecked}
												onCheckedChange={() => handleToggleCheck(item.id)}
												aria-label={`${item.id} 선택`}
											/>
										</td>
										<td>
											<span className={`alert-config__match-badge alert-config__match-badge--${item.matchType === 1 ? 'exact' : 'min'}`}>
												{item.matchType === 1 ? '정확히' : '이상'}
											</span>
										</td>
										<td>{item.amount.toLocaleString()}원</td>
										<td>{item.title || <span className="text-muted-foreground">미입력</span>}</td>
										<td className="alert-config__td--message">{item.message}</td>
										<td>{item.displayDurationSec}초</td>
										<td>
											<button
												type="button"
												role="switch"
												aria-checked={item.isActive}
												aria-busy={togglingIDs.has(item.id)}
												aria-label={`${item.title || `#${item.id}`} 활성 상태 ${item.isActive ? '끄기' : '켜기'}`}
												className={`alert-config__active-toggle${item.isActive ? ' alert-config__active-toggle--on' : ''}${togglingIDs.has(item.id) ? ' alert-config__active-toggle--busy' : ''}`}
												onClick={() => handleToggleActive(item)}
												disabled={togglingIDs.has(item.id) || saving}
												title={item.isActive ? '비활성화' : '활성화'}
											>
												<span className="alert-config__active-toggle-knob" aria-hidden="true" />
											</button>
										</td>
										<td className="alert-config__td--media">
											<div>
												{hasImage && (
													thumbErrors.has(item.id) ? (
														<button
															type="button"
															className="alert-config__media-btn alert-config__media-btn--image"
															title="이미지 보기"
															onClick={() => setPreviewImageUrl(item.imageUrl!)}
														>
															<FontAwesomeIcon icon={faImage} />
														</button>
													) : (
														<button
															type="button"
															className="alert-config__media-thumb"
															title="이미지 크게 보기"
															onClick={() => setPreviewImageUrl(item.imageUrl!)}
														>
															<Image
																src={item.imageUrl!}
																alt="알림 이미지"
																width={96}
																height={96}
																sizes="96px"
																quality={90}
																className="alert-config__media-thumb-img"
																loading="lazy"
																onError={() => setThumbErrors(prev => new Set(prev).add(item.id))}
															/>
														</button>
													)
												)}
												{hasSound && (
													<button
														type="button"
														className={`alert-config__media-btn alert-config__media-btn--sound${playingAudio === item.id ? ' alert-config__media-btn--playing' : ''}`}
														title={playingAudio === item.id ? '사운드 정지' : '사운드 재생'}
														onClick={() => handlePlaySound(item.id, item.soundUrl!)}
													>
														<FontAwesomeIcon icon={playingAudio === item.id ? faStop : faPlay} />
													</button>
												)}
												{!hasImage && !hasSound && (
													<span className="text-muted-foreground">-</span>
												)}
											</div>
										</td>
										<td>
											<button
												type="button"
												className="alert-config__btn alert-config__btn--sm"
												onClick={() => onEdit(item)}
												disabled={isChecked}
											>
												수정
											</button>
										</td>
									</tr>
								);
							})}
						</tbody>
					</table>
				)}
			</div>

			{totalPages > 1 && (
				<div className="alert-config__pagination">
					<button
						type="button"
						className="alert-config__page-btn"
						disabled={page <= 1}
						onClick={() => setPage(p => p - 1)}
					>
						◀
					</button>
					{Array.from({ length: totalPages }, (_, i) => i + 1).map(p => (
						<button
							key={p}
							type="button"
							className={`alert-config__page-btn${p === page ? ' alert-config__page-btn--active' : ''}`}
							onClick={() => setPage(p)}
						>
							{p}
						</button>
					))}
					<button
						type="button"
						className="alert-config__page-btn"
						disabled={page >= totalPages}
						onClick={() => setPage(p => p + 1)}
					>
						▶
					</button>
				</div>
			)}
		{/* 이미지 확대 모달 */}
		<Dialog open={!!previewImageUrl} onOpenChange={open => { if (!open) { setPreviewImageUrl(null); } }}>
			<DialogContent className="alert-config__media-dialog">
				<DialogTitle className="sr-only">이미지 미리보기</DialogTitle>
				{previewImageUrl && (
					<img
						src={previewImageUrl}
						alt="알림 이미지"
						className="alert-config__media-dialog-img"
					/>
				)}
			</DialogContent>
		</Dialog>
		</div>
	);
}