// Component providing a customized date and time selector with formatted AM/PM pickers and calendar dropdown modal.
import React, { useState, useEffect, useRef, useCallback } from "react";
import { createPortal } from "react-dom";
import { Calendar, Clock, ChevronLeft, ChevronRight, X } from "lucide-react";
const MONTHS = ["January","February","March","April","May","June","July","August","September","October","November","December"];
const DAYS   = ["Su","Mo","Tu","We","Th","Fr","Sa"];
/* ─── Helpers ──────────────────────────────────────────────────────── */
const pad  = (n) => String(n).padStart(2, "0");
const ymd  = (d) => `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
/** Parse any ISO string into a local Date. Returns null if invalid. */
const parseISO = (str) => {
  if (!str) return null;
  const d = new Date(str);
  return isNaN(d.getTime()) ? null : d;
};
/** Build display string: DD-MM-YYYY hh:mm AM/PM  or  DD-MM-YYYY */
const displayStr = (isoStr, dateOnly) => {
  const d = parseISO(isoStr);
  if (!d) return "";
  const day   = pad(d.getDate());
  const month = pad(d.getMonth() + 1);
  const year  = d.getFullYear();
  if (dateOnly) return `${day}-${month}-${year}`;
  let h = d.getHours();
  const ampm = h >= 12 ? "PM" : "AM";
  h = h % 12 || 12;
  const min = pad(d.getMinutes());
  return `${day}-${month}-${year} ${pad(h)}:${min} ${ampm}`;
};
/** Convert picker state → ISO string the backend expects */
const toISO = (year, month, day, hour12, minute, ampm, dateOnly) => {
  let h = parseInt(hour12, 10) % 12;
  if (ampm === "PM") h += 12;
  const d = new Date(year, month, day, dateOnly ? 0 : h, dateOnly ? 0 : parseInt(minute, 10));
  if (dateOnly) return ymd(d);           // "YYYY-MM-DD"
  // local ISO without timezone shift
  return `${ymd(d)}T${pad(d.getHours())}:${pad(d.getMinutes())}:00`;
};
/* ─── Calendar grid builder ─────────────────────────────────────────── */
const buildGrid = (year, month) => {
  const first  = new Date(year, month, 1).getDay();
  const total  = new Date(year, month + 1, 0).getDate();
  const cells  = [];
  for (let i = 0; i < first; i++) cells.push(null);
  for (let d = 1; d <= total; d++) cells.push(d);
  return cells;
};
/* ─── Scroll-wheel selector ─────────────────────────────────────────── */
const ScrollSelector = ({ items, selected, onSelect, width = "48px" }) => {
  const ref = useRef(null);
  const isScrolling = useRef(false);
  const scrollTimeout = useRef(null);

  const loop = items.length > 2;
  const MULTIPLIER = loop ? 21 : 1;
  const MID_BLOCK = Math.floor(MULTIPLIER / 2);
  const displayItems = loop ? Array(MULTIPLIER).fill(items).flat() : items;

  useEffect(() => {
    if (!isScrolling.current) {
      const baseIdx = items.indexOf(String(selected));
      if (baseIdx !== -1 && ref.current) {
        const targetIdx = loop ? (MID_BLOCK * items.length) + baseIdx : baseIdx;
        ref.current.scrollTop = targetIdx * 36;
      }
    }
  }, [selected, items, loop, MID_BLOCK]);

  const handleScroll = () => {
    isScrolling.current = true;
    if (scrollTimeout.current) clearTimeout(scrollTimeout.current);

    scrollTimeout.current = setTimeout(() => {
      isScrolling.current = false;
      if (ref.current) {
        const rawIdx = Math.round(ref.current.scrollTop / 36);
        if (rawIdx >= 0 && rawIdx < displayItems.length) {
          const itemIdx = rawIdx % items.length;
          onSelect(items[itemIdx]);

          if (loop) {
            const resetIdx = (MID_BLOCK * items.length) + itemIdx;
            if (rawIdx !== resetIdx) {
              const oldSnap = ref.current.style.scrollSnapType;
              ref.current.style.scrollSnapType = 'none';
              ref.current.scrollTop = resetIdx * 36;
              // eslint-disable-next-line no-unused-expressions
              ref.current.offsetHeight; // force reflow
              ref.current.style.scrollSnapType = oldSnap;
            }
          }
        }
      }
    }, 150);
  };

  return (
    <div
      style={{
        width,
        height: "36px",
        overflowY: "scroll",
        scrollbarWidth: "none",
        scrollSnapType: "y mandatory",
        position: "relative",
      }}
      ref={ref}
      onScroll={handleScroll}
    >
      <style>{`.dtp-scroll::-webkit-scrollbar{display:none}`}</style>
      {displayItems.map((item, idx) => (
        <div
          key={`${item}-${idx}`}
          className="dtp-scroll"
          style={{
            height: "36px",
            lineHeight: "36px",
            textAlign: "center",
            scrollSnapAlign: "start",
            cursor: "pointer",
            borderRadius: "6px",
            fontSize: "14px",
            fontWeight: item === String(selected) ? "700" : "400",
            color: item === String(selected) ? "#2563eb" : "#475569",
            background: item === String(selected) ? "rgba(59, 130, 246, 0.08)" : "transparent",
            transition: "all 0.15s",
          }}
        >
          {item}
        </div>
      ))}
    </div>
  );
};
/* ─── Main Component ─────────────────────────────────────────────────── */
const DateTimePicker = ({
  value      = "",
  onChange,
  dateOnly   = false,
  placeholder,
  minDate    = "",
  maxDate    = "",
  disabled   = false,
  className  = "",
  name,
  yearNav    = false,
}) => {
  const today = new Date();
  const parsed = parseISO(value);
  /* Picker state */
  const [open, setOpen]       = useState(false);
  const [viewYear, setVY]     = useState(parsed?.getFullYear()  ?? today.getFullYear());
  const [viewMonth, setVM]    = useState(parsed?.getMonth()     ?? today.getMonth());
  const [selDay, setSD]       = useState(parsed?.getDate()      ?? null);
  const [hour12, setH]        = useState(() => {
    if (!parsed) return "12";
    let h = parsed.getHours() % 12 || 12;
    return pad(h);
  });
  const [minute, setMin]      = useState(parsed ? pad(parsed.getMinutes()) : "00");
  const [ampm, setAmPm]       = useState(parsed ? (parsed.getHours() >= 12 ? "PM" : "AM") : "AM");
  const wrapRef = useRef(null);
  const popupRef = useRef(null);
  const [popupCoords, setPopupCoords] = useState({ top: 0, left: 0 });
  const yearsList = [];
  const currYear = new Date().getFullYear();
  if (yearNav) {
    // Past dates (e.g. DOB): from currYear - 80 to currYear
    for (let y = currYear - 80; y <= currYear; y++) {
      yearsList.push(y);
    }
  } else {
    // Future dates (e.g. Expiry): from currYear to currYear + 25
    for (let y = currYear; y <= currYear + 25; y++) {
      yearsList.push(y);
    }
  }
  /* Sync state when value prop changes externally */
  useEffect(() => {
    const d = parseISO(value);
    if (d) {
      setVY(d.getFullYear());
      setVM(d.getMonth());
      setSD(d.getDate());
      let h = d.getHours() % 12 || 12;
      setH(pad(h));
      setMin(pad(d.getMinutes()));
      setAmPm(d.getHours() >= 12 ? "PM" : "AM");
    } else {
      setSD(null);
    }
  }, [value]);
  /* Handle dynamic positioning and outside click */
  useEffect(() => {
    if (!open) return;
    const updatePos = () => {
      if (!wrapRef.current) return;
      const rect = wrapRef.current.getBoundingClientRect();
      const popupHeight = popupRef.current ? popupRef.current.offsetHeight : (dateOnly ? 340 : 480);
      const popupWidth = popupRef.current ? popupRef.current.offsetWidth : (dateOnly ? 280 : 340);
      let top = rect.bottom + window.scrollY + 6;
      let left = rect.left + window.scrollX;
      // If opening below cuts off the bottom of the screen
      if (rect.bottom + popupHeight > window.innerHeight) {
        if (rect.top > popupHeight + 10) {
          // Open upwards if there's space above
          top = rect.top + window.scrollY - popupHeight - 6;
        } else {
          // Not enough space above OR below! Pin to bottom of screen
          top = window.scrollY + window.innerHeight - popupHeight - 12;
        }
      }
      // Safety clamp for top (never go above viewport)
      if (top < window.scrollY + 12) {
        top = window.scrollY + 12;
      }
            // Ensure it doesn't flow off the right edge
      if (rect.left + popupWidth > window.innerWidth) {
        left = window.scrollX + window.innerWidth - popupWidth - 12;
      }
      // Safety clamp for left
      if (left < window.scrollX + 12) {
        left = window.scrollX + 12;
      }

      setPopupCoords({ top, left });
    };
    updatePos();
    const handler = (e) => {
      if (
        wrapRef.current && !wrapRef.current.contains(e.target) &&
        popupRef.current && !popupRef.current.contains(e.target)
      ) {
        setOpen(false);
      }
    };
    document.addEventListener("mousedown", handler);
    window.addEventListener("scroll", updatePos, true);
    window.addEventListener("resize", updatePos);
    return () => {
      document.removeEventListener("mousedown", handler);
      window.removeEventListener("scroll", updatePos, true);
      window.removeEventListener("resize", updatePos);
    };
  }, [open, dateOnly]);
  /* Emit value upward */
  const emit = useCallback((day, h, m, ap) => {
    const iso = toISO(viewYear, viewMonth, day, h, m, ap, dateOnly);
    onChange && onChange(iso);
  }, [viewYear, viewMonth, dateOnly, onChange]);
  const handleDayClick = (day) => {
    const dateStr = `${viewYear}-${pad(viewMonth+1)}-${pad(day)}`;
    if (minDate && dateStr < minDate) return;
    if (maxDate && dateStr > maxDate) return;
    setSD(day);
    emit(day, hour12, minute, ampm);
    if (dateOnly) setOpen(false);
  };
  const handleHour   = (v) => { setH(v);   selDay && emit(selDay, v, minute, ampm); };
  const handleMin    = (v) => { setMin(v);  selDay && emit(selDay, hour12, v, ampm); };
  const handleAmPm   = (v) => { setAmPm(v); selDay && emit(selDay, hour12, minute, v); };
  const prevMonth = () => { if (viewMonth === 0) { setVY(y=>y-1); setVM(11); } else setVM(m=>m-1); };
  const nextMonth = () => { if (viewMonth === 11) { setVY(y=>y+1); setVM(0); } else setVM(m=>m+1); };
  const todayStr  = ymd(today);
  const selStr    = selDay ? `${viewYear}-${pad(viewMonth+1)}-${pad(selDay)}` : "";
  const cells     = buildGrid(viewYear, viewMonth);
  /* Hours/minutes lists */
  const hours   = Array.from({length:12}, (_, i) => pad(i+1));
  const minutes = Array.from({length:60}, (_, i) => pad(i));
  const ampmList= ["AM","PM"];
  const isDisabled = (day) => {
    const s = `${viewYear}-${pad(viewMonth+1)}-${pad(day)}`;
    return (minDate && s < minDate) || (maxDate && s > maxDate);
  };
  /* ── Styles ── */
  const triggerStyle = {
    display: "flex",
    alignItems: "center",
    gap: "8px",
    background: "rgba(15, 23, 42, 0.55)",
    border: "1px solid rgba(255, 255, 255, 0.08)",
    borderRadius: "8px",
    padding: "9px 14px",
    cursor: disabled ? "not-allowed" : "pointer",
    color: value ? "#ffffff" : "#64748b",
    fontSize: "14px",
    width: "100%",
    transition: "all 0.25s cubic-bezier(0.4, 0, 0.2, 1)",
    opacity: disabled ? 0.5 : 1,
    userSelect: "none",
  };
  const popupStyle = {
    position: "absolute",
    zIndex: 9999999,
    top: popupCoords.top,
    left: popupCoords.left,
    background: "#ffffff",
    border: "1.5px solid #a855f7",
    borderRadius: "16px",
    boxShadow: "0 10px 30px rgba(168, 85, 247, 0.15)",
    padding: "16px",
    minWidth: dateOnly ? "280px" : "340px",
    animation: "dtpFadeIn 0.18s ease",
  };
  return (
    <>
      <style>{`
        @keyframes dtpFadeIn {
          from { opacity:0; transform:translateY(-6px); }
          to   { opacity:1; transform:translateY(0); }
        }
        .dtp-day:hover { background: rgba(168, 85, 247, 0.08) !important; color:#a855f7 !important; }
        .dtp-trigger:hover {
          background: rgba(15, 23, 42, 0.75) !important;
          border-color: rgba(168, 85, 247, 0.45) !important;
        }
        .dtp-trigger:focus, .dtp-trigger:focus-within {
          border-color: #a855f7 !important;
          box-shadow: 0 0 0 0.25rem rgba(168, 85, 247, 0.25) !important;
          background: rgba(15, 23, 42, 0.9) !important;
          outline: none;
        }
      `}</style>
      <div ref={wrapRef} style={{ position: "relative", width: "100%" }} className={className}>
        {/* Trigger */}
        <div
          className="dtp-trigger"
          style={triggerStyle}
          onClick={() => !disabled && setOpen(o => !o)}
          tabIndex={disabled ? -1 : 0}
          role="button"
          aria-label={name}
          onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") setOpen(o=>!o); }}
        >
          {dateOnly
            ? <Calendar size={14} color="#a855f7" style={{flexShrink:0}} />
            : <Clock    size={14} color="#a855f7" style={{flexShrink:0}} />}
          <span style={{flex:1}}>
            {value ? displayStr(value, dateOnly) : (placeholder || (dateOnly ? "DD-MM-YYYY" : "DD-MM-YYYY hh:mm AM/PM"))}
          </span>
          {value && !disabled && (
            <span
              onClick={(e) => { e.stopPropagation(); onChange && onChange(""); setSD(null); }}
              style={{ color:"#64748b", cursor:"pointer", lineHeight:1 }}
              title="Clear"
            ><X size={13}/></span>
          )}
        </div>
        {/* Popup Rendered via Portal */}
        {open && createPortal(
          <div ref={popupRef} style={popupStyle}>
            {/* Month nav */}
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"12px"}}>
              <button onClick={prevMonth} style={{background:"none",border:"none",color:"#64748b",cursor:"pointer",padding:"4px",borderRadius:"6px",lineHeight:1}} aria-label="Prev month"><ChevronLeft size={16}/></button>
              <div style={{ display: "flex", gap: "4px" }}>
                <select
                  value={viewMonth}
                  onChange={(e) => setVM(parseInt(e.target.value, 10))}
                  style={{
                    fontWeight: "700",
                    fontSize: "13px",
                    color: "#0f172a",
                    background: "none",
                    border: "none",
                    cursor: "pointer",
                    outline: "none",
                    padding: 0
                  }}
                >
                  {MONTHS.map((m, idx) => (
                    <option key={idx} value={idx}>{m}</option>
                  ))}
                </select>
                <select
                  value={viewYear}
                  onChange={(e) => setVY(parseInt(e.target.value, 10))}
                  style={{
                    fontWeight: "700",
                    fontSize: "13px",
                    color: "#0f172a",
                    background: "none",
                    border: "none",
                    cursor: "pointer",
                    outline: "none",
                    padding: 0
                  }}
                >
                  {yearsList.map(yr => (
                    <option key={yr} value={yr}>{yr}</option>
                  ))}
                </select>
              </div>
              <button onClick={nextMonth} style={{background:"none",border:"none",color:"#475569",cursor:"pointer",padding:"4px",borderRadius:"6px",lineHeight:1}} aria-label="Next month"><ChevronRight size={16}/></button>
            </div>
            {/* Day headers */}
            <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",marginBottom:"6px"}}>
              {DAYS.map(d=>(
                <div key={d} style={{textAlign:"center",fontSize:"10px",fontWeight:"600",color:"#475569",padding:"4px 0"}}>{d}</div>
              ))}
            </div>
            {/* Day cells */}
            <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px"}}>
              {cells.map((day, i) => {
                if (!day) return <div key={i}/>;
                const dStr = `${viewYear}-${pad(viewMonth+1)}-${pad(day)}`;
                const isTod = dStr === todayStr;
                const isSel = dStr === selStr;
                const isDis = isDisabled(day);
                return (
                  <div
                    key={i}
                    className={isDis ? "" : "dtp-day"}
                    onClick={() => !isDis && handleDayClick(day)}
                    style={{
                      textAlign:"center", padding:"6px 2px", borderRadius:"8px", fontSize:"12px",
                      cursor: isDis ? "not-allowed" : "pointer",
                      color: isDis ? "#cbd5e1" : isSel ? "#fff" : isTod ? "#2563eb" : "#334155",
                      background: isSel ? "#2563eb" : isTod && !isSel ? "rgba(59,130,246,0.08)" : "transparent",
                      fontWeight: isSel || isTod ? "700" : "400",
                      border: isTod && !isSel ? "1px solid rgba(59,130,246,0.35)" : "1px solid transparent",
                      transition: "all 0.15s",
                    }}
                  >{day}</div>
                );
              })}
            </div>
            {/* Time picker */}
            {!dateOnly && (
              <>
                <div style={{height:"1px",background:"#e2e8f0",margin:"14px 0"}}/>
                <div style={{display:"flex",alignItems:"center",gap:"8px",justifyContent:"center"}}>
                  <Clock size={13} color="#3b82f6" style={{flexShrink:0}}/>
                  <span style={{fontSize:"11px",color:"#64748b",marginRight:"4px"}}>Time</span>
                  <div style={{display:"flex",gap:"4px",background:"#f8fafc",borderRadius:"10px",padding:"6px 8px",border:"1px solid #cbd5e1"}}>
                    <ScrollSelector items={hours}   selected={hour12} onSelect={handleHour} width="36px"/>
                    <div style={{color:"#475569",alignSelf:"center",fontWeight:"700",fontSize:"16px",padding:"0 2px"}}>:</div>
                    <ScrollSelector items={minutes} selected={minute} onSelect={handleMin}  width="36px"/>
                    <div style={{width:"1px",background:"#e2e8f0",margin:"0 4px"}}/>
                    <ScrollSelector items={ampmList} selected={ampm} onSelect={handleAmPm} width="38px"/>
                  </div>
                </div>

              </>
            )}
            {/* Done button */}
            {!dateOnly && (
              <button
                onClick={() => setOpen(false)}
                style={{width:"100%",marginTop:"12px",padding:"7px",borderRadius:"8px",border:"none",background:"#1e40af",color:"#fff",fontSize:"12px",fontWeight:"600",cursor:"pointer",letterSpacing:"0.5px"}}>
                Done
              </button>
            )}
          </div>,
          document.body
        )}
      </div>
    </>
  );
};
export default DateTimePicker;