"use client";

import React, { useEffect, useRef, useState } from "react";

/* ------------------------------------------------------------------ */
/* Types                                                               */
/* ------------------------------------------------------------------ */

interface DateRangePickerProps {
	from: string; // YYYY-MM-DD
	to: string; // YYYY-MM-DD
	onChange: (from: string, to: string) => void;
}

/* ------------------------------------------------------------------ */
/* Helpers                                                             */
/* ------------------------------------------------------------------ */

function daysInMonth(year: number, month: number): number {
	return new Date(year, month + 1, 0).getDate();
}

function firstDayOfMonth(year: number, month: number): number {
	return new Date(year, month, 1).getDay(); // 0=Sun
}

function fmt(d: Date): string {
	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}`;
}

function fmtDisplay(dateStr: string): string {
	if (!dateStr) return "";
	const [y, m, d] = dateStr.split("-");
	return `${y}.${m}.${d}`;
}

function isSame(a: string, b: string): boolean {
	return a === b;
}

function isBetween(date: string, from: string, to: string): boolean {
	return date >= from && date <= to;
}

const WEEKDAYS = ["일", "월", "화", "수", "목", "금", "토"];
const MONTH_NAMES = [
	"1월",
	"2월",
	"3월",
	"4월",
	"5월",
	"6월",
	"7월",
	"8월",
	"9월",
	"10월",
	"11월",
	"12월",
];

/* ------------------------------------------------------------------ */
/* Component                                                           */
/* ------------------------------------------------------------------ */

export function DateRangePicker({ from, to, onChange }: DateRangePickerProps) {
	const [open, setOpen] = useState(false);
	const [selecting, setSelecting] = useState<"from" | "to" | null>(null);
	const [tempFrom, setTempFrom] = useState(from);
	const [tempTo, setTempTo] = useState(to);
	const [viewYear, setViewYear] = useState(() => new Date().getFullYear());
	const [viewMonth, setViewMonth] = useState(() => new Date().getMonth());
	const containerRef = useRef<HTMLDivElement>(null);

	// Close on outside click
	useEffect(() => {
		function handleClick(e: MouseEvent) {
			if (
				containerRef.current &&
				!containerRef.current.contains(e.target as Node)
			) {
				setOpen(false);
			}
		}
		if (open) document.addEventListener("mousedown", handleClick);
		return () => document.removeEventListener("mousedown", handleClick);
	}, [open]);

	const handleOpen = () => {
		setTempFrom(from);
		setTempTo(to);
		setSelecting("from");
		const d = from ? new Date(from) : new Date();
		setViewYear(d.getFullYear());
		setViewMonth(d.getMonth());
		setOpen(true);
	};

	const handleDayClick = (dateStr: string) => {
		if (selecting === "from") {
			setTempFrom(dateStr);
			setTempTo(dateStr); // 같은 날짜 = 당일
			setSelecting("to");
		} else {
			// to 선택
			if (dateStr < tempFrom) {
				// 시작일보다 이전 선택 → 시작일로 교체
				setTempFrom(dateStr);
				setTempTo(dateStr);
				setSelecting("to");
			} else {
				setTempTo(dateStr);
				onChange(tempFrom, dateStr);
				setOpen(false);
				setSelecting(null);
			}
		}
	};

	const prevMonth = () => {
		if (viewMonth === 0) {
			setViewYear(viewYear - 1);
			setViewMonth(11);
		} else setViewMonth(viewMonth - 1);
	};

	const nextMonth = () => {
		if (viewMonth === 11) {
			setViewYear(viewYear + 1);
			setViewMonth(0);
		} else setViewMonth(viewMonth + 1);
	};

	// Quick select presets
	const today = fmt(new Date());
	const presets = [
		{ label: "오늘", from: today, to: today },
		{
			label: "이번주",
			from: fmt(
				new Date(
					new Date().setDate(new Date().getDate() - new Date().getDay()),
				),
			),
			to: today,
		},
		{
			label: "이번달",
			from: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-01`,
			to: today,
		},
	];

	// Display text
	const displayText =
		from && to
			? isSame(from, to)
				? fmtDisplay(from)
				: `${fmtDisplay(from)} ~ ${fmtDisplay(to)}`
			: "기간 선택";

	// Build calendar grid
	const totalDays = daysInMonth(viewYear, viewMonth);
	const startDay = firstDayOfMonth(viewYear, viewMonth);
	const cells: (string | null)[] = [];
	for (let i = 0; i < startDay; i++) cells.push(null);
	for (let d = 1; d <= totalDays; d++) {
		const dateStr = `${viewYear}-${String(viewMonth + 1).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
		cells.push(dateStr);
	}

	return (
		<div ref={containerRef} className="relative">
			{/* Trigger Button */}
			<div>
				<label className="text-[10px] font-semibold text-gray-400 mb-1 block">
					기간
				</label>
				<button
					onClick={handleOpen}
					className="w-full px-3 py-2.5 border border-gray-200 rounded-lg text-sm text-left focus:outline-none focus:border-cyan-400 focus:ring-2 focus:ring-cyan-100 bg-white flex items-center justify-between gap-2"
				>
					<span
						className={from ? "text-gray-900 font-medium" : "text-gray-400"}
					>
						{displayText}
					</span>
					<svg
						className="w-4 h-4 text-gray-400 shrink-0"
						fill="none"
						stroke="currentColor"
						strokeWidth={2}
						viewBox="0 0 24 24"
					>
						<path
							strokeLinecap="round"
							strokeLinejoin="round"
							d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5"
						/>
					</svg>
				</button>
			</div>

			{/* Calendar Popup */}
			{open && (
				<div className="absolute left-0 top-full mt-2 z-50 bg-white rounded-2xl shadow-xl border border-gray-200 p-4 w-[320px]">
					{/* Header hint */}
					<p className="text-[10px] text-center text-gray-400 mb-2">
						{selecting === "from"
							? "시작일을 선택하세요"
							: "종료일을 선택하세요 (같은 날 = 당일)"}
					</p>

					{/* Quick Presets */}
					<div className="flex gap-1.5 mb-3">
						{presets.map((p) => (
							<button
								key={p.label}
								onClick={() => {
									onChange(p.from, p.to);
									setOpen(false);
								}}
								className="flex-1 py-1.5 rounded-lg text-[11px] font-semibold text-cyan-700 bg-cyan-50 hover:bg-cyan-100 active:scale-95 transition-all"
							>
								{p.label}
							</button>
						))}
					</div>

					{/* Month Navigation */}
					<div className="flex items-center justify-between mb-3">
						<button
							onClick={prevMonth}
							className="w-8 h-8 rounded-lg flex items-center justify-center text-gray-500 hover:bg-gray-100 active:scale-95"
						>
							<svg
								className="w-4 h-4"
								fill="none"
								stroke="currentColor"
								strokeWidth={2}
								viewBox="0 0 24 24"
							>
								<path
									strokeLinecap="round"
									strokeLinejoin="round"
									d="M15.75 19.5L8.25 12l7.5-7.5"
								/>
							</svg>
						</button>
						<span className="text-sm font-bold text-gray-900">
							{viewYear}년 {MONTH_NAMES[viewMonth]}
						</span>
						<button
							onClick={nextMonth}
							className="w-8 h-8 rounded-lg flex items-center justify-center text-gray-500 hover:bg-gray-100 active:scale-95"
						>
							<svg
								className="w-4 h-4"
								fill="none"
								stroke="currentColor"
								strokeWidth={2}
								viewBox="0 0 24 24"
							>
								<path
									strokeLinecap="round"
									strokeLinejoin="round"
									d="M8.25 4.5l7.5 7.5-7.5 7.5"
								/>
							</svg>
						</button>
					</div>

					{/* Weekday Headers */}
					<div className="grid grid-cols-7 gap-0 mb-1">
						{WEEKDAYS.map((d, i) => (
							<div
								key={d}
								className={`text-center text-[10px] font-semibold py-1 ${i === 0 ? "text-red-400" : i === 6 ? "text-blue-400" : "text-gray-400"}`}
							>
								{d}
							</div>
						))}
					</div>

					{/* Day Grid */}
					<div className="grid grid-cols-7 gap-0">
						{cells.map((dateStr, idx) => {
							if (!dateStr)
								return <div key={`empty-${idx}`} className="h-10" />;

							const day = parseInt(dateStr.split("-")[2], 10);
							const dayOfWeek = new Date(dateStr).getDay();
							const isStart = isSame(dateStr, tempFrom);
							const isEnd = isSame(dateStr, tempTo);
							const isInRange =
								tempFrom && tempTo && isBetween(dateStr, tempFrom, tempTo);
							const isToday = isSame(dateStr, today);

							let bgClass = "hover:bg-gray-100";
							let textClass =
								dayOfWeek === 0
									? "text-red-500"
									: dayOfWeek === 6
										? "text-blue-500"
										: "text-gray-700";

							if (isStart || isEnd) {
								bgClass = "bg-cyan-600 text-white";
								textClass = "text-white";
							} else if (isInRange) {
								bgClass = "bg-cyan-50";
								textClass = "text-cyan-700";
							}

							return (
								<button
									key={dateStr}
									onClick={() => handleDayClick(dateStr)}
									className={`h-10 flex items-center justify-center text-sm font-medium rounded-lg transition-all active:scale-90 ${bgClass} ${textClass}`}
								>
									<span className="relative">
										{day}
										{isToday && !isStart && !isEnd && (
											<span className="absolute -bottom-0.5 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-cyan-500" />
										)}
									</span>
								</button>
							);
						})}
					</div>

					{/* Selected Range Display */}
					{tempFrom && (
						<div className="mt-3 pt-3 border-t border-gray-100 text-center">
							<span className="text-xs text-gray-500">
								{isSame(tempFrom, tempTo)
									? fmtDisplay(tempFrom)
									: `${fmtDisplay(tempFrom)} ~ ${fmtDisplay(tempTo)}`}
							</span>
						</div>
					)}
				</div>
			)}
		</div>
	);
}
