'use client';

import './style.scss';
import { useState, useEffect, useCallback, useMemo } from 'react';
import { fetchApi, getDateTime } from '@/lib/utils/client';
import useAuth from '@/hooks/useAuth';
import { useConfigContext } from '@/contexts/configProvider';
import type { AttendanceListResponse, AttendanceItem, AttendanceCalendarResponse, CalendarDay, AttendanceCheckInResponse } from '@/types/response/attendance';
import type { RankBonusEntry } from '@/types/config';
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { Stamp, Users, CircleHelp } from 'lucide-react';
import Loading from '@/app/component/Loading';
import Pagination from '@/app/component/Pagination';

export default function AttendancePage()
{
	const { loginCheck } = useAuth();
	const config = useConfigContext();

	const rankBonuses = useMemo<RankBonusEntry[]>(() => {
		if (!config.attendance?.useRankBonus || !config.attendance?.rankBonusConfig) {
			return [];
		}
		try {
			return JSON.parse(config.attendance.rankBonusConfig);
		} catch {
			return [];
		}
	}, [config.attendance?.useRankBonus, config.attendance?.rankBonusConfig]);

	// Calendar
	const now = new Date();
	const [calYear, setCalYear] = useState(now.getFullYear());
	const [calMonth, setCalMonth] = useState(now.getMonth() + 1);
	const [calDays, setCalDays] = useState<CalendarDay[]>([]);
	const [calLoading, setCalLoading] = useState(false);

	// Check-in
	const [greeting, setGreeting] = useState('');
	const [checkInLoading, setCheckInLoading] = useState(false);

	// List (선택 날짜 연동)
	const todayStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
	const [selectedDate, setSelectedDate] = useState(todayStr);
	const [listLoading, setListLoading] = useState(true);
	const [listPage, setListPage] = useState(1);
	const [listData, setListData] = useState<AttendanceListResponse>({ total: 0, list: [] });
	const [sortBy, setSortBy] = useState<'time'|'count'|'streak'>('time');

	// selectedDate를 오늘 기준 offset (0~7)로 환산, 범위 밖이면 ''
	const dayOffset = useMemo(() => {
		const sel = new Date(selectedDate + 'T00:00:00');
		const today = new Date(todayStr + 'T00:00:00');
		const diff = Math.round((today.getTime() - sel.getTime()) / (1000 * 60 * 60 * 24));
		return diff >= 0 && diff <= 7 ? String(diff) : '';
	}, [selectedDate, todayStr]);

	// 오늘 이미 출석했는지 (개인 출석 여부)
	const attendedToday = useMemo(() => {
		return calDays.some((cd) => {
			if (!cd.attendedAt) {
				return false;
			}
			const d = new Date(cd.attendedAt);
			const y = d.getFullYear();
			const m = String(d.getMonth() + 1).padStart(2, '0');
			const day = String(d.getDate()).padStart(2, '0');
			return `${y}-${m}-${day}` === todayStr;
		});
	}, [calDays, todayStr]);

	const handleOffsetChange = (offsetStr: string) => {
		const offset = parseInt(offsetStr, 10);
		const target = new Date(todayStr + 'T00:00:00');
		target.setDate(target.getDate() - offset);
		const y = target.getFullYear();
		const m = String(target.getMonth() + 1).padStart(2, '0');
		const d = String(target.getDate()).padStart(2, '0');
		setSelectedDate(`${y}-${m}-${d}`);
		setListPage(1);
	};

	// 캘린더 데이터 로드
	const loadCalendar = useCallback(() => {
		setCalLoading(true);

		fetchApi<AttendanceCalendarResponse>(`/api/attendance/calendar?year=${calYear}&month=${calMonth}`, { silent: true }).then((res) => {
			setCalDays(res.data?.days ?? []);
		}).catch(() => {
			setCalDays([]);
		}).finally(() => {
			setCalLoading(false);
		});

	}, [calYear, calMonth]);

	useEffect(() => {
		loadCalendar();
	}, [loadCalendar]);

	// 리스트 로드 (선택 날짜 기준)
	const loadList = useCallback(() => {
		setListLoading(true);

		fetchApi<AttendanceListResponse>(`/api/attendance/list?page=${listPage}&perPage=20&date=${selectedDate}&sortBy=${sortBy}`, { silent: true }).then((res) => {
			setListData(res.data ?? { total: 0, list: [] });
		}).catch(() => {
			setListData({ total: 0, list: [] });
		}).finally(() => {
			setListLoading(false);
		});

	}, [listPage, selectedDate, sortBy]);

	useEffect(() => {
		loadList();
	}, [loadList]);

	// 출석 체크
	const handleCheckIn = () => {
		if (!loginCheck()) {
			return;
		}

		setCheckInLoading(true);

		fetchApi<AttendanceCheckInResponse>('/api/attendance/check-in', {
			method: 'POST',
			body: { greeting: greeting.trim() || '' }
		}).then((res) => {
			const data = res.data!;
			let msg = `출석 완료! 순위: ${data.rank}등 | 연속: ${data.consecutiveDays}일 | 경험치: +${data.expRewarded} | 토큰: +${data.pointRewarded}P`;
			if (data.rankBonusExp > 0 || data.rankBonusPoint > 0) {
				msg += ` (순위 보상: +${data.rankBonusExp}EXP, +${data.rankBonusPoint}P)`;
			}
			alert(msg);
			setGreeting('');
			setSelectedDate(todayStr);

			if (listPage === 1) {
				loadList();
			} else {
				setListPage(1);
			}

			loadCalendar();
		}).catch((err) => {
			alert(err.message);
		}).finally(() => {
			setCheckInLoading(false);
		});
	};

	// 오늘 자정 기준 (미래 날짜 비교용)
	const todayMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate());

	// 날짜 클릭 → 하단 리스트 전환 (미래 날짜는 무시)
	const handleDateClick = (dateStr: string) => {
		const clicked = new Date(dateStr + 'T00:00:00');
		if (clicked > todayMidnight) {
			return;
		}
		setSelectedDate(dateStr);
		setListPage(1);
	};

	// 캘린더 렌더링
	const renderCalendar = () =>
	{
		const firstDay = new Date(calYear, calMonth - 1, 1).getDay();
		const daysInMonth = new Date(calYear, calMonth, 0).getDate();
		const weekdays = ['일', '월', '화', '수', '목', '금', '토'];

		const cells: React.ReactNode[] = [];

		// 빈 칸
		for (let i = 0; i < firstDay; i++) {
			cells.push(<div key={`empty-${i}`} className="attendance__calendar-cell attendance__calendar-cell--empty" />);
		}

		// 날짜
		for (let d = 1; d <= daysInMonth; d++) {
			const dateStr = `${calYear}-${String(calMonth).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
			const dayData = calDays.find(cd => cd.date?.startsWith(dateStr));
			const attended = dayData?.attendedAt != null;
			const isToday = calYear === now.getFullYear() && calMonth === now.getMonth() + 1 && d === now.getDate();
			const isSelected = selectedDate === dateStr;
			const totalCount = dayData?.totalCount ?? 0;
			const isFuture = new Date(calYear, calMonth - 1, d) > todayMidnight;

			const classNames = [
				'attendance__calendar-cell',
				attended ? 'attendance__calendar-cell--attended' : '',
				isToday ? 'attendance__calendar-cell--today' : '',
				isSelected ? 'attendance__calendar-cell--selected' : '',
				isFuture ? 'attendance__calendar-cell--future' : ''
			].filter(Boolean).join(' ');

			cells.push(
				<div key={d} className={classNames} onClick={() => handleDateClick(dateStr)}>
					<span className="attendance__calendar-day">{d}</span>
					{(attended || totalCount > 0) && (
						<span className="attendance__calendar-bottom">
							<span className="attendance__calendar-stamp">
								{attended && <Stamp size={16} />}
							</span>
							<span className="attendance__calendar-count">
								{totalCount > 0 && (
									<>
										<Users size={14} />
										{totalCount}
									</>
								)}
							</span>
						</span>
					)}
				</div>
			);
		}

		const isCurrentMonth = calYear === now.getFullYear() && calMonth === now.getMonth() + 1;

		return (
			<div className="attendance__calendar">
				<div className="attendance__calendar-nav">
					<button type="button" onClick={() => {
						if (calMonth === 1) {
							setCalYear(calYear - 1);
							setCalMonth(12);
						} else {
							setCalMonth(calMonth - 1);
						}
					}}>&lt;</button>
					<span>{calYear}년 {calMonth}월</span>
					<button type="button" disabled={isCurrentMonth} onClick={() => {
						if (calMonth === 12) {
							setCalYear(calYear + 1);
							setCalMonth(1);
						} else {
							setCalMonth(calMonth + 1);
						}
					}}>&gt;</button>
				</div>
				<div className="attendance__calendar-grid">
					{weekdays.map(w => (
						<div key={w} className="attendance__calendar-weekday">{w}</div>
					))}
					{cells}
				</div>
			</div>
		);
	};

	return (
		<div id="attendancePage">
			<div>
				<br/>
			</div>
			<div className="attendance__title-row">
				<h1>출석부</h1>
				<Dialog>
					<DialogTrigger asChild>
						<button type="button" className="attendance__help-btn" title='출석부 이용안내'>
							<CircleHelp size={20} />
						</button>
					</DialogTrigger>
					<DialogContent>
						<DialogHeader>
							<DialogTitle>출석부 안내</DialogTitle>
						</DialogHeader>
						<DialogDescription asChild>
							<div className="attendance__guide">
								<section className="attendance__guide-section">
									<h3>기본 보상</h3>
									<p>매일 출석 시 경험치 <strong>{config.attendance?.baseExp ?? 0}</strong>, 토큰 <strong>{config.attendance?.basePoint ?? 0}P</strong>가 지급됩니다.</p>
								</section>

								{config.attendance?.useStreakBonus && (
									<section className="attendance__guide-section">
										<h3>연속 출석 보상</h3>
										<p>연속 출석 시 1일당 추가 경험치 <strong>+{config.attendance.streakBonusPerDay}</strong>, 토큰 <strong>+{config.attendance.streakBonusPointPerDay}P</strong>가 지급됩니다.</p>
										{config.attendance.streakBonusMaxDays > 0 && (
											<p>최대 <strong>{config.attendance.streakBonusMaxDays}일</strong>까지 적용됩니다.</p>
										)}
									</section>
								)}

								{config.attendance?.useRankBonus && rankBonuses.length > 0 && (
									<section className="attendance__guide-section">
										<h3>순위 보상</h3>
										<p>출석 순위에 따라 추가 보상이 지급됩니다.</p>
										<table className="attendance__guide-table" aria-label="순위별 추가 보상">
											<thead>
												<tr>
													<th scope="col">순위</th>
													<th scope="col">추가 경험치</th>
													<th scope="col">추가 토큰</th>
												</tr>
											</thead>
											<tbody>
												{rankBonuses.map((entry) => (
													<tr key={entry.rank}>
														<th scope="row">{entry.rank}등</th>
														<td>+{entry.exp}</td>
														<td>+{entry.point}P</td>
													</tr>
												))}
											</tbody>
										</table>
									</section>
								)}
							</div>
						</DialogDescription>
					</DialogContent>
				</Dialog>
			</div>

			{/* 캘린더 */}
			<section className="attendance__section">
				{calLoading && <Loading type={2} />}
				{!calLoading && renderCalendar()}
			</section>

			{/* 출석 입력 (오늘 미출석 시만 노출) */}
			{!attendedToday && (
				<section className="attendance__form">
					<input
						type="text"
						className="attendance__form-input"
						placeholder="출석 인사를 입력하세요 (선택)"
						maxLength={200}
						value={greeting}
						onChange={(e) => setGreeting(e.target.value)}
						onKeyDown={(e) => {
							if (e.key === 'Enter') {
								handleCheckIn();
							}
						}}
						disabled={checkInLoading}
					/>
					<button
						type="button"
						className="attendance__form-btn"
						onClick={handleCheckIn}
						disabled={checkInLoading}
					>
						{checkInLoading ? '처리중...' : '출석하기'}
					</button>
				</section>
			)}

			{/* 리스트 */}
			<section className="attendance__section">
				<div className="attendance__list-toolbar">
					<div className="attendance__list-toolbar-left">
						<span className="attendance__list-toolbar-total">총 {listData.total}명</span>
					</div>
					<div className="attendance__list-toolbar-right">
						<select
							title='기간 선택'
							className="attendance__list-toolbar-select"
							value={dayOffset}
							onChange={(e) => handleOffsetChange(e.target.value)}
						>
							<option value="" disabled>기간 선택</option>
							<option value="0">오늘</option>
							<option value="1">1일전</option>
							<option value="2">2일전</option>
							<option value="3">3일전</option>
							<option value="4">4일전</option>
							<option value="5">5일전</option>
							<option value="6">6일전</option>
							<option value="7">7일전</option>
						</select>
						<select
							title='정렬'
							className="attendance__list-toolbar-select"
							value={sortBy}
							onChange={(e) => {
								setSortBy(e.target.value as 'time'|'count'|'streak');
								setListPage(1);
							}}
						>
							<option value="time">시간순</option>
							<option value="count">출석순</option>
							<option value="streak">개근순</option>
						</select>
					</div>
				</div>

				{listLoading && <Loading type={2} />}

				<div className="attendance__list">
					{/* 헤더 */}
					<div className="attendance__list-header">
						<span>순위</span>
						<span>별명</span>
						<span>출석 인사</span>
						<span>출석 일시</span>
						<span>토큰</span>
						<span>경험치</span>
						<span>개근(일)</span>
					</div>

					{/* 데이터 */}
					{listData.list.length > 0 ? (
						listData.list.map((item: AttendanceItem) => (
							<div key={item.rank} className="attendance__list-row">

								{/* PC */}
								<div className="attendance__list-row-pc">
									<span className="attendance__list-rank">{item.rank}</span>
									<span className="attendance__list-member">
										<Avatar className="h-6 w-6">
											{item.memberThumb ? (
												<AvatarImage src={item.memberThumb} alt={item.memberName?.trim() || item.memberSID} />
											) : null}
											<AvatarFallback>{(item.memberName?.trim() || item.memberSID)?.[0] ?? '?'}</AvatarFallback>
										</Avatar>
										<span>{item.memberName?.trim() || item.memberSID}</span>
									</span>
									<span className="attendance__list-greeting">{item.greeting || '-'}</span>
									<span>{getDateTime(item.createdAt)}</span>
									<span className="attendance__list-point">+{item.pointRewarded}P</span>
									<span className="attendance__list-exp">+{item.expRewarded}</span>
									<span className="attendance__list-streak">{item.consecutiveDays}일</span>
								</div>

								{/* Mobile */}
								<div className="attendance__list-row-mobile">
									<div className="attendance__list-row-mobile-top">
										<span className="attendance__list-rank">{item.rank}</span>
										<Avatar className="h-5 w-5">
											{item.memberThumb ? (
												<AvatarImage src={item.memberThumb} alt={item.memberName?.trim() || item.memberSID} />
											) : null}
											<AvatarFallback>{(item.memberName?.trim() || item.memberSID)?.[0] ?? '?'}</AvatarFallback>
										</Avatar>
										<span className="attendance__list-member-name">{item.memberName?.trim() || item.memberSID}</span>
										<span className="attendance__list-streak">{item.consecutiveDays}일</span>
									</div>
									<div className="attendance__list-row-mobile-bottom">
										<span className="attendance__list-greeting">{item.greeting || '-'}</span>
										<span className="attendance__list-meta">
											<span className="attendance__list-point">+{item.pointRewarded}P</span>
											<span className="attendance__list-exp">+{item.expRewarded} EXP</span>
											<span>{getDateTime(item.createdAt)}</span>
										</span>
									</div>
								</div>
							</div>
						))
					) : (
						<p className="attendance__empty">출석한 회원이 없습니다.</p>
					)}
				</div>

				{listData.total > 0 && (
					<Pagination total={listData.total} page={listPage} perPage={20} onChange={setListPage} />
				)}
			</section>
		</div>
	);
}