import React, { useCallback, useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'

/* ─── Date helpers (duplicated locally so component is self-contained) ─ */

const MONTH_NAMES = [
  'January','February','March','April','May','June',
  'July','August','September','October','November','December',
]
const DAY_ABBR = ['Mo','Tu','We','Th','Fr','Sa','Su']

function daysInMonth(year, month) {
  return new Date(year, month + 1, 0).getDate()
}
function firstWeekday(year, month) {
  return (new Date(year, month, 1).getDay() + 6) % 7
}
function toISO(date) {
  return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,'0')}-${String(date.getDate()).padStart(2,'0')}`
}
function fromISO(str) {
  if (!str) return null
  const [y,m,d] = str.split('-').map(Number)
  return new Date(y, m-1, d)
}
function fmt(isoStr) {
  if (!isoStr) return ''
  const d = fromISO(isoStr)
  return d ? `${MONTH_NAMES[d.getMonth()].slice(0,3)} ${d.getDate()}, ${d.getFullYear()}` : ''
}
function isSameDay(a, b) {
  return !!a && !!b &&
    a.getFullYear()===b.getFullYear() && a.getMonth()===b.getMonth() && a.getDate()===b.getDate()
}

/* ─── Single month grid ─────────────────────────────────────────── */

function MonthGrid({ year, month, start, end, hover, onHover, onSelect, minDate, maxDate }) {
  const numDays = daysInMonth(year, month)
  const startWd = firstWeekday(year, month)
  const prevDays = daysInMonth(year, month - 1 < 0 ? 11 : month - 1)
  const cells = []

  for (let i = startWd - 1; i >= 0; i--)
    cells.push({ day: prevDays - i, current: false, date: new Date(year, month - 1, prevDays - i) })
  for (let d = 1; d <= numDays; d++)
    cells.push({ day: d, current: true, date: new Date(year, month, d) })
  let next = 1
  while (cells.length % 7 !== 0)
    cells.push({ day: next++, current: false, date: new Date(year, month + 1, next - 1) })

  const startDate = fromISO(start)
  const endDate   = fromISO(end)
  const hoverDate = hover ? fromISO(hover) : null
  const today = new Date(); today.setHours(0,0,0,0)

  // Range boundary to highlight (end could be hover while selecting)
  const rangeEnd = endDate ?? hoverDate

  return (
    <div className="p-3 min-w-[224px]">
      <div className="grid grid-cols-7 mb-1">
        {DAY_ABBR.map((d) => (
          <div key={d} className="text-center text-[10px] font-semibold text-slate-500 py-1">{d}</div>
        ))}
      </div>
      <div className="grid grid-cols-7 gap-y-0.5">
        {cells.map((cell, i) => {
          const iso      = toISO(cell.date)
          const isStart  = isSameDay(cell.date, startDate)
          const isEnd    = isSameDay(cell.date, endDate)
          const isToday  = isSameDay(cell.date, today)
          const disabled = (minDate && iso < minDate) || (maxDate && iso > maxDate)

          // In range?
          let inRange = false
          if (startDate && rangeEnd) {
            const lo = startDate <= rangeEnd ? startDate : rangeEnd
            const hi = startDate <= rangeEnd ? rangeEnd  : startDate
            inRange  = cell.date > lo && cell.date < hi
          }

          const isEdge = isStart || isEnd

          return (
            <button
              key={i}
              type="button"
              disabled={disabled || !cell.current}
              onClick={() => cell.current && !disabled && onSelect(iso)}
              onMouseEnter={() => cell.current && !disabled && onHover(iso)}
              className={[
                'relative flex items-center justify-center w-8 h-8 mx-auto rounded-lg text-sm transition-all',
                !cell.current ? 'opacity-0 pointer-events-none' : '',
                isEdge ? 'bg-accent text-white font-semibold shadow shadow-accent/30 z-10' : '',
                !isEdge && inRange ? 'bg-accent/20 text-white rounded-none' : '',
                !isEdge && !inRange && !disabled ? 'hover:bg-white/10 text-white' : '',
                isToday && !isEdge ? 'ring-1 ring-accent/50 text-accent' : '',
                disabled ? 'opacity-30 cursor-not-allowed' : 'cursor-pointer',
              ].join(' ')}
            >
              {cell.day}
            </button>
          )
        })}
      </div>
    </div>
  )
}

/* ─── DateRangePicker ────────────────────────────────────────────── */

/**
 * Nova DateRangePicker
 *
 * @prop {string}   start       - ISO 'YYYY-MM-DD'
 * @prop {string}   end         - ISO 'YYYY-MM-DD'
 * @prop {function} onChange    - called with { start, end }
 * @prop {string}   label
 * @prop {string}   placeholder
 * @prop {string}   error
 * @prop {string}   hint
 * @prop {boolean}  required
 * @prop {boolean}  clearable
 * @prop {string}   minDate
 * @prop {string}   maxDate
 */
export default function DateRangePicker({
  start = '',
  end   = '',
  onChange,
  label,
  placeholder = 'Select date range',
  error,
  hint,
  required = false,
  clearable = false,
  minDate,
  maxDate,
  id,
  disabled = false,
  className = '',
}) {
  const [open, setOpen]     = useState(false)
  const [dropPos, setPos]   = useState({ top: 0, left: 0, width: 480 })
  const [hover, setHover]   = useState('')
  // Selecting state: if we have a start but no end, next click sets end
  const [picking, setPicking] = useState(null) // null | 'start' | 'end'

  // View months: left and right panels
  const today      = new Date()
  const [lYear,  setLYear]  = useState(today.getFullYear())
  const [lMonth, setLMonth] = useState(today.getMonth() === 0 ? 11 : today.getMonth() - 1)
  // right panel = left + 1
  const rYear  = lMonth === 11 ? lYear + 1 : lYear
  const rMonth = lMonth === 11 ? 0 : lMonth + 1

  const triggerRef = useRef(null)
  const inputId    = id ?? (label ? `drp-${label.toLowerCase().replace(/\s+/g, '-')}` : 'date-range')

  const measure = useCallback(() => {
    if (!triggerRef.current) return
    const rect    = triggerRef.current.getBoundingClientRect()
    const panelW  = Math.max(rect.width, 480)
    const height  = 340
    const openUp  = window.innerHeight - rect.bottom < height + 8 && rect.top > height + 8
    setPos({
      top:   openUp ? rect.top - height - 4 : rect.bottom + 4,
      left:  Math.min(rect.left, window.innerWidth - panelW - 8),
      width: panelW,
    })
  }, [])

  const openPicker = () => { if (disabled) return; measure(); setOpen(true) }

  useEffect(() => {
    if (!open) return
    const handler = (e) => {
      if (
        !triggerRef.current?.contains(e.target) &&
        !document.getElementById(`drp-panel-${inputId}`)?.contains(e.target)
      ) { setOpen(false); setPicking(null) }
    }
    document.addEventListener('mousedown', handler)
    return () => document.removeEventListener('mousedown', handler)
  }, [open, inputId])

  useEffect(() => {
    if (!open) return
    const onScroll = (e) => {
      if (document.getElementById(`drp-panel-${inputId}`)?.contains(e.target)) return
      setOpen(false); setPicking(null)
    }
    const onResize = () => { setOpen(false); setPicking(null) }
    window.addEventListener('scroll', onScroll, true)
    window.addEventListener('resize', onResize)
    return () => { window.removeEventListener('scroll', onScroll, true); window.removeEventListener('resize', onResize) }
  }, [open, inputId])

  const handleSelect = (iso) => {
    if (!start || picking === 'start' || (start && end)) {
      // Start fresh
      onChange?.({ start: iso, end: '' })
      setPicking('end')
      setHover('')
    } else {
      // We have start, picking end
      const s = start < iso ? start : iso
      const e = start < iso ? iso   : start
      onChange?.({ start: s, end: e })
      setPicking(null)
      setOpen(false)
    }
  }

  const clearValue = (ev) => { ev.stopPropagation(); onChange?.({ start:'', end:'' }); setPicking(null) }

  const prevLeft = () => {
    if (lMonth === 0) { setLMonth(11); setLYear(y => y - 1) } else setLMonth(m => m - 1)
  }
  const nextLeft = () => {
    if (lMonth === 11) { setLMonth(0); setLYear(y => y + 1) } else setLMonth(m => m + 1)
  }

  const displayText = start ? `${fmt(start)} – ${end ? fmt(end) : '…'}` : ''

  const triggerClass = [
    'relative flex items-center h-[42px] rounded-xl border px-3.5 gap-2 cursor-pointer w-full',
    'bg-white/[0.06] text-sm transition-all duration-150',
    'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-0',
    error
      ? 'border-red-500/60 focus-visible:ring-red-500/40'
      : open
        ? 'border-accent/50 ring-2 ring-accent/40'
        : 'border-white/12 hover:border-white/22',
    disabled ? 'opacity-50 cursor-not-allowed pointer-events-none' : '',
    className,
  ].join(' ')

  return (
    <div className="flex flex-col gap-1.5">
      {label && (
        <label htmlFor={inputId} className="text-sm font-medium text-white/85 select-none">
          {label}{required && <span className="text-red-400 ml-1">*</span>}
        </label>
      )}

      <div ref={triggerRef} className={triggerClass} tabIndex={disabled ? -1 : 0}
        onClick={openPicker}
        onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); openPicker() } }}
        role="button" aria-label={label ?? placeholder} id={inputId}
      >
        {/* Calendar icon */}
        <svg width="14" height="14" viewBox="0 0 14 14" fill="none" className="text-slate-500 shrink-0" aria-hidden="true">
          <rect x="1" y="2.5" width="12" height="10.5" rx="1.5" stroke="currentColor" strokeWidth="1.3"/>
          <path d="M1 6h12" stroke="currentColor" strokeWidth="1.3"/>
          <path d="M4 1v3M10 1v3" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/>
        </svg>

        <span className={`flex-1 truncate ${displayText ? 'text-white' : 'text-slate-500'}`}>
          {displayText || placeholder}
        </span>

        {clearable && (start || end) && (
          <button type="button" tabIndex={-1} onClick={clearValue}
            className="w-5 h-5 flex items-center justify-center rounded text-slate-500 hover:text-white transition-colors"
            aria-label="Clear date range"
          >
            <svg width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
              <path d="M1 1l8 8M9 1L1 9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
            </svg>
          </button>
        )}
      </div>

      {error && <p role="alert" className="text-xs text-red-400">{error}</p>}
      {!error && hint && <p className="text-xs text-slate-500">{hint}</p>}

      {open && createPortal(
        <div
          id={`drp-panel-${inputId}`}
          className="fixed z-[500] rounded-2xl border border-white/12 bg-nova-900 shadow-2xl shadow-black/50 overflow-hidden"
          style={{ top: dropPos.top, left: dropPos.left, width: dropPos.width }}
          onMouseLeave={() => setHover('')}
        >
          {/* Header info */}
          {picking === 'end' && (
            <div className="px-4 pt-3 pb-1 text-xs text-accent/80 font-medium">
              Now click an end date
            </div>
          )}

          {/* Two calendars */}
          <div className="flex items-start">
            {/* Left month */}
            <div className="flex-1 border-r border-white/8">
              <div className="flex items-center justify-between px-3 pt-3">
                <button type="button" onClick={prevLeft}
                  className="w-8 h-8 flex items-center justify-center rounded-lg text-slate-400 hover:text-white hover:bg-white/8 transition-all"
                  aria-label="Previous month"
                >
                  <svg width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
                    <path d="M7 1L3 5l4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                </button>
                <span className="text-sm font-semibold text-white">{MONTH_NAMES[lMonth]} {lYear}</span>
                <div className="w-8" />
              </div>
              <MonthGrid year={lYear} month={lMonth} start={start} end={end} hover={hover}
                onHover={setHover} onSelect={handleSelect} minDate={minDate} maxDate={maxDate} />
            </div>

            {/* Right month */}
            <div className="flex-1">
              <div className="flex items-center justify-between px-3 pt-3">
                <div className="w-8" />
                <span className="text-sm font-semibold text-white">{MONTH_NAMES[rMonth]} {rYear}</span>
                <button type="button" onClick={nextLeft}
                  className="w-8 h-8 flex items-center justify-center rounded-lg text-slate-400 hover:text-white hover:bg-white/8 transition-all"
                  aria-label="Next month"
                >
                  <svg width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
                    <path d="M3 1l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                </button>
              </div>
              <MonthGrid year={rYear} month={rMonth} start={start} end={end} hover={hover}
                onHover={setHover} onSelect={handleSelect} minDate={minDate} maxDate={maxDate} />
            </div>
          </div>

          {/* Footer with preset shortcuts */}
          <div className="border-t border-white/8 px-4 py-2.5 flex items-center gap-3 flex-wrap">
            {[
              { label: 'Last 7 days',  fn: () => { const e=toISO(new Date()); const s=toISO(new Date(Date.now()-6*864e5)); onChange?.({start:s,end:e}); setOpen(false) } },
              { label: 'Last 30 days', fn: () => { const e=toISO(new Date()); const s=toISO(new Date(Date.now()-29*864e5)); onChange?.({start:s,end:e}); setOpen(false) } },
              { label: 'This month',   fn: () => { const n=new Date(); const s=toISO(new Date(n.getFullYear(),n.getMonth(),1)); const e=toISO(new Date(n.getFullYear(),n.getMonth()+1,0)); onChange?.({start:s,end:e}); setOpen(false) } },
            ].map((p) => (
              <button key={p.label} type="button" onClick={p.fn}
                className="text-xs text-slate-400 hover:text-accent transition-colors font-medium"
              >
                {p.label}
              </button>
            ))}
          </div>
        </div>,
        document.body,
      )}
    </div>
  )
}
