import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { View } from '../view'
import { Text } from '../text'
import { Button } from '../button'
import { useLocale } from '../locale/index.js'
import {
  dateInputValueToMs,
  formatDisplayDate,
  msToDateInputValue,
} from './time.js'

function getDaysInMonth(year, month) {
  return new Date(year, month + 1, 0).getDate()
}

function getMondayFirstOffset(year, month) {
  return (new Date(year, month, 1).getDay() + 6) % 7
}

const calendarPanelStyle = {
  position: 'absolute',
  top: 'calc(100% + var(--space-xs, 4px))',
  left: 0,
  zIndex: 101,
  minWidth: 280,
  boxShadow: '0 8px 24px hsla(0, 0%, 0%, 0.12)',
}

/**
 * Custom date picker — displays a calendar popover and persists Unix ms (ADR 0004).
 */
export function DatePicker({
  id,
  name,
  value,
  onChange,
  disabled,
  placeholder,
  minMs,
  maxMs,
  style = {},
  ...rest
}) {
  const { t, language } = useLocale()
  const containerRef = useRef(null)
  const [open, setOpen] = useState(false)

  const ms = useMemo(() => {
    if (typeof value === 'number' && !Number.isNaN(value)) return value
    if (value == null || value === '') return undefined
    return dateInputValueToMs(msToDateInputValue(value))
  }, [value])

  const today = new Date()
  const [viewYear, setViewYear] = useState(ms ? new Date(ms).getFullYear() : today.getFullYear())
  const [viewMonth, setViewMonth] = useState(ms ? new Date(ms).getMonth() : today.getMonth())

  useEffect(() => {
    if (ms == null) return
    const d = new Date(ms)
    setViewYear(d.getFullYear())
    setViewMonth(d.getMonth())
  }, [ms])

  useEffect(() => {
    if (!open) return
    const onDocClick = (event) => {
      if (!containerRef.current?.contains(event.target)) setOpen(false)
    }
    document.addEventListener('mousedown', onDocClick)
    return () => document.removeEventListener('mousedown', onDocClick)
  }, [open])

  const commitMs = useCallback(
    (nextMs) => {
      onChange({
        target: {
          id: id ?? name,
          name,
          type: 'number',
          value: nextMs,
        },
      })
      setOpen(false)
    },
    [id, name, onChange],
  )

  const monthLabel = useMemo(() => {
    const locale = language === 'sv' ? 'sv-SE' : 'en-GB'
    return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(
      new Date(viewYear, viewMonth, 1),
    )
  }, [viewYear, viewMonth, language])

  const weekdayLabels = useMemo(() => {
    const locale = language === 'sv' ? 'sv-SE' : 'en-GB'
    const monday = new Date(2025, 0, 6)
    return Array.from({ length: 7 }, (_, i) => {
      const d = new Date(monday)
      d.setDate(monday.getDate() + i)
      return new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(d)
    })
  }, [language])

  const todayKey = msToDateInputValue(today.getTime())
  const daysInMonth = getDaysInMonth(viewYear, viewMonth)
  const firstDayOffset = getMondayFirstOffset(viewYear, viewMonth)
  const cells = []
  for (let i = 0; i < firstDayOffset; i++) cells.push(null)
  for (let d = 1; d <= daysInMonth; d++) cells.push(d)

  const selectedKey = ms != null ? msToDateInputValue(ms) : null
  const display =
    ms != null
      ? formatDisplayDate(ms, language)
      : (placeholder ?? t('design-system.fields.datePlaceholder'))

  const isDayDisabled = (dayMs) => {
    if (minMs != null && dayMs < minMs) return true
    if (maxMs != null && dayMs > maxMs) return true
    return false
  }

  return (
    <View ref={containerRef} style={{ position: 'relative', ...style }} {...rest}>
      <Button
        type="button"
        id={id}
        variant="neutral"
        disabled={disabled}
        suffix="calendar"
        onClick={() => !disabled && setOpen(o => !o)}
        style={{ justifyContent: 'flex-start', width: '100%' }}
        aria-expanded={open}
        aria-haspopup="dialog"
      >
        {display}
      </Button>
      {open && (
        <View
          surface="primary"
          roundness="m"
          inset="m"
          gap="s"
          role="dialog"
          aria-label={t('design-system.fields.datePickerLabel')}
          style={calendarPanelStyle}
        >
          <View layout="row" justifyContent="space-between" alignItems="center">
            <Button
              type="button"
              variant="neutral"
              size="s"
              aria-label={t('design-system.fields.datePrevMonth')}
              onClick={() => {
                if (viewMonth === 0) {
                  setViewMonth(11)
                  setViewYear(y => y - 1)
                } else {
                  setViewMonth(m => m - 1)
                }
              }}
            >
              ‹
            </Button>
            <Text weight="medium">{monthLabel}</Text>
            <Button
              type="button"
              variant="neutral"
              size="s"
              aria-label={t('design-system.fields.dateNextMonth')}
              onClick={() => {
                if (viewMonth === 11) {
                  setViewMonth(0)
                  setViewYear(y => y + 1)
                } else {
                  setViewMonth(m => m + 1)
                }
              }}
            >
              ›
            </Button>
          </View>
          <View
            layout="row"
            gap="xs"
            style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)' }}
          >
            {weekdayLabels.map(label => (
              <Text key={label} variant="small" style={{ textAlign: 'center', opacity: 0.6 }}>
                {label}
              </Text>
            ))}
          </View>
          <View gap="xs" style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)' }}>
            {cells.map((day, idx) => {
              if (!day) return <View key={`empty-${idx}`} />
              const dateKey = `${viewYear}-${String(viewMonth + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`
              const dayMs = dateInputValueToMs(dateKey)
              const isSelected = selectedKey === dateKey
              const isToday = todayKey === dateKey
              const dayDisabled = isDayDisabled(dayMs)
              return (
                <Button
                  key={dateKey}
                  type="button"
                  variant={isSelected ? 'tag-active' : isToday ? 'tag' : 'neutral'}
                  size="s"
                  disabled={dayDisabled}
                  onClick={() => !dayDisabled && commitMs(dayMs)}
                  style={{ padding: '8px 4px', minWidth: 0 }}
                >
                  {day}
                </Button>
              )
            })}
          </View>
          {ms != null && (
            <Button
              type="button"
              variant="link"
              size="s"
              onClick={() => commitMs(undefined)}
            >
              {t('design-system.fields.dateClear')}
            </Button>
          )}
        </View>
      )}
    </View>
  )
}
