'use client';

import { useEffect, useMemo, useRef, useState } from 'react';

interface Props {
  value: string; // "YYYY-MM-DD"
  onChange: (value: string) => void;
  className?: string;
}

const MONTH_NAMES = [
  'Januar', 'Februar', 'Maerz', 'April', 'Mai', 'Juni',
  'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember',
];

const WEEKDAY_SHORT = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];

function pad(n: number): string {
  return String(n).padStart(2, '0');
}

function monthKey(date: Date): string {
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}`;
}

function monthLabel(ym: string): string {
  const [ys, ms] = ym.split('-');
  const y = Number(ys);
  const m = Number(ms);
  return `${MONTH_NAMES[m - 1]} ${y}`;
}

function shiftMonth(ym: string, delta: number): string {
  const [ys, ms] = ym.split('-');
  const d = new Date(Number(ys), Number(ms) - 1 + delta, 1);
  return monthKey(d);
}

function parseISODate(v: string): Date | null {
  if (!isValidDateString(v)) return null;
  const [ys, ms, ds] = v.split('-');
  return new Date(Number(ys), Number(ms) - 1, Number(ds));
}

function buildMonthGrid(ym: string): Array<number | null> {
  const [ys, ms] = ym.split('-');
  const y = Number(ys);
  const m = Number(ms);
  const first = new Date(y, m - 1, 1);
  const days = new Date(y, m, 0).getDate();
  const mondayStartOffset = (first.getDay() + 6) % 7;
  const cells: Array<number | null> = Array(mondayStartOffset).fill(null);
  for (let d = 1; d <= days; d += 1) cells.push(d);
  while (cells.length % 7 !== 0) cells.push(null);
  return cells;
}

function isValidDateString(v: string): boolean {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(v)) return false;
  const [ys, ms, ds] = v.split('-');
  const y = Number(ys);
  const m = Number(ms);
  const d = Number(ds);
  if (m < 1 || m > 12 || d < 1 || d > 31) return false;

  const dt = new Date(Date.UTC(y, m - 1, d));
  return (
    dt.getUTCFullYear() === y &&
    dt.getUTCMonth() === m - 1 &&
    dt.getUTCDate() === d
  );
}

function normalize(v: string): string {
  const digits = v.replace(/\D/g, '').slice(0, 8);
  const y = digits.slice(0, 4);
  const m = digits.slice(4, 6);
  const d = digits.slice(6, 8);

  if (digits.length <= 4) return y;
  if (digits.length <= 6) return `${y}-${m}`;
  return `${y}-${m}-${d}`;
}

export default function DateInput({ value, onChange, className = '' }: Props) {
  const [local, setLocal] = useState(value);
  const [error, setError] = useState(false);
  const [open, setOpen] = useState(false);
  const [viewMonth, setViewMonth] = useState(monthKey(new Date()));
  const wrapperRef = useRef<HTMLDivElement>(null);

  const selectedDate = useMemo(() => parseISODate(value), [value]);
  const dayCells = useMemo(() => buildMonthGrid(viewMonth), [viewMonth]);

  useEffect(() => {
    setLocal(value);
    setError(false);
  }, [value]);

  useEffect(() => {
    const date = parseISODate(value);
    if (date) setViewMonth(monthKey(date));
  }, [value]);

  useEffect(() => {
    function onDocMouseDown(ev: MouseEvent) {
      if (!wrapperRef.current) return;
      if (!wrapperRef.current.contains(ev.target as Node)) setOpen(false);
    }
    function onDocKeyDown(ev: KeyboardEvent) {
      if (ev.key === 'Escape') setOpen(false);
    }
    document.addEventListener('mousedown', onDocMouseDown);
    document.addEventListener('keydown', onDocKeyDown);
    return () => {
      document.removeEventListener('mousedown', onDocMouseDown);
      document.removeEventListener('keydown', onDocKeyDown);
    };
  }, []);

  function handleChange(raw: string) {
    setError(false);
    setLocal(normalize(raw));
  }

  function handleBlur() {
    if (local === '') {
      setLocal(value);
      setError(false);
      return;
    }

    if (isValidDateString(local)) {
      setError(false);
      onChange(local);
      return;
    }

    setError(true);
  }

  function selectDay(day: number) {
    const [ys, ms] = viewMonth.split('-');
    const iso = `${ys}-${ms}-${pad(day)}`;
    setLocal(iso);
    setError(false);
    onChange(iso);
    setOpen(false);
  }

  function isSelected(day: number): boolean {
    if (!selectedDate) return false;
    const [ys, ms] = viewMonth.split('-').map(Number);
    return selectedDate.getFullYear() === ys && selectedDate.getMonth() === ms - 1 && selectedDate.getDate() === day;
  }

  return (
    <div ref={wrapperRef} className={`relative ${className}`}>
      <div className="flex items-center gap-1">
        <input
          type="text"
          inputMode="numeric"
          value={local}
          onChange={(e) => handleChange(e.target.value)}
          onBlur={handleBlur}
          placeholder="YYYY-MM-DD"
          maxLength={10}
          className={`w-full px-2 py-1 border-2 rounded-lg bg-white text-sm text-gray-900 font-mono text-center focus:outline-none ${
            error ? 'border-red-500 focus:border-red-500' : 'border-gray-400 focus:border-blue-500'
          }`}
        />
        <button
          type="button"
          onClick={() => setOpen((v) => !v)}
          className="px-2 py-1 border-2 border-gray-400 rounded-lg bg-white text-xs text-gray-700 hover:bg-gray-50"
          aria-label="Kalender oeffnen"
        >
          Kalender
        </button>
      </div>

      {open && (
        <div className="absolute left-0 top-full mt-1 z-20 w-64 border-2 border-gray-300 rounded-lg bg-white shadow-lg p-2">
          <div className="flex items-center justify-between mb-2">
            <button
              type="button"
              onClick={() => setViewMonth((m) => shiftMonth(m, -1))}
              className="px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 text-sm"
              aria-label="Vorheriger Monat"
            >
              {'<'}
            </button>
            <div className="text-sm font-medium">{monthLabel(viewMonth)}</div>
            <button
              type="button"
              onClick={() => setViewMonth((m) => shiftMonth(m, 1))}
              className="px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 text-sm"
              aria-label="Naechster Monat"
            >
              {'>'}
            </button>
          </div>

          <div className="grid grid-cols-7 gap-1 mb-1">
            {WEEKDAY_SHORT.map((wd) => (
              <div key={wd} className="text-[11px] text-center text-gray-500 py-1">
                {wd}
              </div>
            ))}
          </div>

          <div className="grid grid-cols-7 gap-1">
            {dayCells.map((day, idx) => (
              <button
                key={`${viewMonth}-${idx}`}
                type="button"
                disabled={day === null}
                onClick={() => day !== null && selectDay(day)}
                className={`h-8 rounded text-sm ${
                  day === null
                    ? 'text-transparent cursor-default'
                    : isSelected(day)
                      ? 'bg-blue-600 text-white'
                      : 'bg-gray-50 hover:bg-gray-100 text-gray-800'
                }`}
              >
                {day ?? '-'}
              </button>
            ))}
          </div>
        </div>
      )}

      {error && (
        <p className="absolute left-0 top-full mt-0.5 text-xs text-red-600 whitespace-nowrap z-10">
          Ungueltiges Datum (YYYY-MM-DD)
        </p>
      )}
    </div>
  );
}
