"use client";
import { useState, useRef, useEffect } from "react";
import { ChevronLeft, ChevronRight, Calendar } from "lucide-react";
import { PRIMARY_COLOR, type CSSPropertiesWithVars } from "@/lib/common";

interface DatePickerProps {
  label?: string;
  value?: string | Date | null;
  onChange: (date: Date) => void;
  error?: string;
  onBlur?: () => void;
  className?: string;
  disabled?: boolean;
}

const parseDateValue = (value?: string | Date | null): Date | null => {
  if (!value) return null;
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
  if (typeof value === "string") {
    const normalized = value.trim();
    if (!normalized) return null;
    const isoMatch = normalized.match(/^(\d{4})-(\d{2})-(\d{2})$/);
    if (isoMatch) {
      const year = Number(isoMatch[1]);
      const month = Number(isoMatch[2]);
      const day = Number(isoMatch[3]);
      const date = new Date(year, month - 1, day);
      return Number.isNaN(date.getTime()) ? null : date;
    }
    const parsed = new Date(normalized);
    return Number.isNaN(parsed.getTime()) ? null : parsed;
  }
  return null;
};

const formatDisplayDate = (date: Date): string => {
  const day = String(date.getDate()).padStart(2, "0");
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const year = String(date.getFullYear());
  return `${day}/${month}/${year}`;
};

/** Parse a typed string in DD/MM/YYYY (or D/M/YYYY) format */
const parseTypedDate = (raw: string): Date | null => {
  const trimmed = raw.trim();
  // Accept DD/MM/YYYY or D/M/YYYY
  const match = trimmed.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
  if (!match) return null;
  const day = Number(match[1]);
  const month = Number(match[2]);
  const year = Number(match[3]);
  if (month < 1 || month > 12 || day < 1 || day > 31 || year < 1000) return null;
  const date = new Date(year, month - 1, day);
  // Guard against invalid combos like 31/02/2024
  if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) return null;
  return date;
};

/** Auto-insert slashes as the user types digits */
const autoFormat = (prev: string, next: string): string => {
  // Strip all non-digit chars to work with raw digits
  const digits = next.replace(/\D/g, "");
  if (digits.length === 0) return "";
  let result = digits.slice(0, 2);
  if (digits.length > 2) result += "/" + digits.slice(2, 4);
  if (digits.length > 4) result += "/" + digits.slice(4, 8);
  return result;
};

export default function DatePicker({
  label = "Select Date",
  value,
  onChange,
  error,
  onBlur,
  className = "",
  disabled = false,
}: DatePickerProps) {
  const [show, setShow] = useState(false);
  const [isTyping, setIsTyping] = useState(false);
  const [typedValue, setTypedValue] = useState("");
  const [typeError, setTypeError] = useState(false);

  const selectedDate = parseDateValue(value);

  const [currentMonth, setCurrentMonth] = useState(
    selectedDate && !isNaN(selectedDate.getTime()) ? selectedDate : new Date()
  );
  const pickerRef = useRef<HTMLDivElement>(null);
  const calendarRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const blurTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    const date = parseDateValue(value);
    if (date && !isNaN(date.getTime())) {
      setCurrentMonth(new Date(date));
    }
  }, [value]);

  // When typing mode activates, pre-fill with current value
  const startTyping = () => {
    if (disabled) return;
    setTypeError(false);
    setTypedValue(selectedDate ? formatDisplayDate(selectedDate) : "");
    setIsTyping(true);
    setShow(false);
    // Focus the input on next tick
    setTimeout(() => inputRef.current?.focus(), 0);
  };

  const commitTyped = () => {
    const parsed = parseTypedDate(typedValue);
    if (parsed) {
      onChange(parsed);
      setCurrentMonth(new Date(parsed));
      setTypeError(false);
    } else if (typedValue.trim() !== "") {
      setTypeError(true);
      return; // keep typing mode open so user can fix it
    }
    setIsTyping(false);
    setTypedValue("");
  };

  const handleTypedKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter" || e.key === "Tab") {
      e.preventDefault();
      commitTyped();
    } else if (e.key === "Escape") {
      setIsTyping(false);
      setTypedValue("");
      setTypeError(false);
    }
  };

  const handleTypedChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const formatted = autoFormat(typedValue, e.target.value);
    setTypedValue(formatted);
    setTypeError(false);
    // Auto-confirm when a full valid date is typed
    const parsed = parseTypedDate(formatted);
    if (parsed) {
      onChange(parsed);
      setCurrentMonth(new Date(parsed));
      setIsTyping(false);
      setTypedValue("");
    }
  };

  const handleTypedBlur = () => {
    commitTyped();
    if (onBlur) setTimeout(onBlur, 100);
  };

  const handleDayClick = (day: Date) => {
    onChange(day);
    setShow(false);
    setIsTyping(false);
    setTypedValue("");
    setTypeError(false);
  };

  const daysInMonth = (date: Date) =>
    new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();

  const firstDayOfMonth = (date: Date) =>
    new Date(date.getFullYear(), date.getMonth(), 1).getDay();

  const nextMonth = () =>
    setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1));

  const prevMonth = () =>
    setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1));

  const handleBlur = (e: React.FocusEvent<HTMLDivElement>) => {
    if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
    const relatedTarget = e.relatedTarget as Node | null;
    const isFocusMovingToCalendar = relatedTarget && calendarRef.current?.contains(relatedTarget);
    if (isFocusMovingToCalendar || show) return;
    blurTimeoutRef.current = setTimeout(() => {
      const activeElement = document.activeElement;
      const isFocusInCalendar = calendarRef.current?.contains(activeElement);
      if (!show && !isFocusInCalendar && onBlur) onBlur();
    }, 150);
  };

  const handleCalendarMouseDown = (e: React.MouseEvent) => {
    e.preventDefault();
  };

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {
        setShow(false);
        if (isTyping) {
          commitTyped();
        }
        if (onBlur) setTimeout(onBlur, 100);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
      if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
    };
  }, [onBlur, show, isTyping, typedValue]);

  const displayValue =
    selectedDate && !isNaN(selectedDate.getTime()) ? formatDisplayDate(selectedDate) : "";

  const hasError = error || typeError;
  const errorMessage = error || (typeError ? "Invalid date. Use DD/MM/YYYY." : undefined);

  return (
    <div className={`relative w-full ${className}`} ref={pickerRef}>
      {label && (
        <label
          className={`mb-1 text-xs font-semibold uppercase tracking-wide ${
            hasError ? "text-red-600" : "text-gray-600"
          }`}
        >
          {label}
        </label>
      )}

      {/* Input area */}
      <div
        className={`group flex items-center justify-between border rounded-lg px-3 py-1.5 min-h-[2.25rem] bg-white transition-all duration-200 ease-in-out ${
          hasError
            ? "border-red-400"
            : disabled
            ? "border-gray-200 bg-gray-100"
            : "border-gray-200 hover:border-[#428B4D]/60 focus-within:border-[#428B4D] focus-within:ring-1 focus-within:ring-[#428B4D]/15"
        } ${disabled ? "cursor-not-allowed" : "cursor-text"}`}
        onBlur={handleBlur}
        onMouseEnter={(e) => {
          if (!disabled && !hasError) {
            e.currentTarget.style.borderColor = `${PRIMARY_COLOR}99`;
          }
        }}
        onMouseLeave={(e) => {
          if (!disabled && !hasError) {
            e.currentTarget.style.borderColor = "";
          }
        }}
      >
        {isTyping ? (
          /* ── Typing mode: raw text input ── */
          <input
            ref={inputRef}
            type="text"
            value={typedValue}
            onChange={handleTypedChange}
            onKeyDown={handleTypedKeyDown}
            onBlur={handleTypedBlur}
            placeholder="DD/MM/YYYY"
            maxLength={10}
            className="flex-1 text-sm bg-transparent outline-none text-gray-800 placeholder-gray-400"
          />
        ) : (
          /* ── Display mode: click to open calendar or start typing ── */
          <span
            className={`flex-1 text-sm ${displayValue ? "text-gray-800" : "text-gray-400"}`}
            onClick={() => {
              if (!disabled) setShow((s) => !s);
            }}
            onKeyDown={(e) => {
              if (disabled) return;
              // Start typing on digit keys
              if (/^\d$/.test(e.key)) {
                e.preventDefault();
                setTypedValue(e.key);
                setIsTyping(true);
                setShow(false);
                setTimeout(() => {
                  if (inputRef.current) {
                    inputRef.current.focus();
                    // Move cursor to end
                    inputRef.current.setSelectionRange(1, 1);
                  }
                }, 0);
              } else if (e.key === "Enter" || e.key === " ") {
                setShow((s) => !s);
              }
            }}
            tabIndex={disabled ? -1 : 0}
            role="button"
            aria-label={displayValue || "Select a date"}
          >
            {displayValue || "Select a date"}
          </span>
        )}

        {/* Calendar icon — always toggles calendar picker */}
        <button
          type="button"
          tabIndex={disabled ? -1 : 0}
          disabled={disabled}
          aria-label="Open calendar"
          onClick={() => {
            if (disabled) return;
            if (isTyping) {
              commitTyped();
            }
            setShow((s) => !s);
          }}
          className="ml-2 flex items-center focus:outline-none"
        >
          <Calendar
            className={`h-4 w-4 transition-colors duration-200 ${
              disabled ? "text-gray-300" : "text-gray-500 group-hover:text-[#428B4D]"
            }`}
          />
        </button>
      </div>

      {errorMessage && (
        <span className="text-red-500 text-sm mt-1 block">{errorMessage}</span>
      )}

      {show && !disabled && (
        <div
          ref={calendarRef}
          onMouseDown={handleCalendarMouseDown}
          className="absolute z-50 mt-2 w-72 rounded-lg border border-gray-200 bg-white p-4 focus:outline-none shadow-sm"
        >
          {/* Month Header */}
          <div className="flex items-center justify-between mb-4">
            <button
              type="button"
              onClick={prevMonth}
              className="p-1 hover:bg-[#428B4D]/10 rounded-lg transition-all duration-200 hover:scale-110 active:scale-95"
            >
              <ChevronLeft className="h-5 w-5 text-gray-600 transition-colors duration-200 hover:text-[#428B4D]" />
            </button>

            <h2 className="font-semibold text-gray-800">
              {currentMonth.toLocaleString("default", { month: "long" })}{" "}
              {currentMonth.getFullYear()}
            </h2>

            <button
              type="button"
              onClick={nextMonth}
              className="p-1 hover:bg-[#428B4D]/10 rounded-lg transition-all duration-200 hover:scale-110 active:scale-95"
            >
              <ChevronRight className="h-5 w-5 text-gray-600 transition-colors duration-200 hover:text-[#428B4D]" />
            </button>
          </div>

          {/* Week Days */}
          <div className="grid grid-cols-7 text-center text-sm text-gray-500 font-semibold mb-2">
            {["S", "M", "T", "W", "T", "F", "S"].map((d, index) => (
              <div key={`weekday-${index}`}>{d}</div>
            ))}
          </div>

          {/* Days */}
          <div className="grid grid-cols-7 text-center">
            {[...Array(firstDayOfMonth(currentMonth)).keys()].map((i) => (
              <div key={"empty-" + i}></div>
            ))}

            {[...Array(daysInMonth(currentMonth)).keys()].map((i) => {
              const day = new Date(
                currentMonth.getFullYear(),
                currentMonth.getMonth(),
                i + 1
              );
              const isSelected = selectedDate?.toDateString() === day.toDateString();

              return (
                <div
                  key={i}
                  onClick={() => handleDayClick(day)}
                  className={`mx-auto my-1 w-9 h-9 flex items-center justify-center rounded-lg cursor-pointer transition-all duration-200
                  ${
                    isSelected
                      ? "bg-[#428B4D] text-white shadow-md shadow-[#428B4D]/30 scale-105"
                      : "hover:bg-[#428B4D]/10 text-gray-800 hover:scale-110 active:scale-95"
                  }`}
                >
                  {i + 1}
                </div>
              );
            })}
          </div>

          {/* Hint */}
          <p className="text-xs text-gray-400 text-center mt-3">
            Or type a date directly in the field above
          </p>
        </div>
      )}
    </div>
  );
}