/**
 * Start node (Zeitplan) — Karten-UI mit Konfiguration unter der gewählten Option.
 */

import React, { useState, useEffect, useCallback, useRef } from 'react';
import { AnimatePresence, LayoutGroup, motion, useReducedMotion } from 'framer-motion';
import type { NodeConfigRendererProps } from '../configs/types';
import {
  type ScheduleSpec,
  type ScheduleMode,
  type IntervalUnit,
  type CalendarPeriod,
  buildCronFromSpec,
  scheduleSpecFromParams,
  WEEKDAYS_MO_SO,
} from '../runtime/scheduleCron';
import styles from '../../editor/Automation2FlowEditor.module.css';

import { useLanguage } from '../../../../providers/language/LanguageContext';

function _getModeOptions(t: (key: string) => string): { value: ScheduleMode; title: string; subtitle: string }[] {
  return [
    { value: 'daily', title: t('scheduleStartNodeConfig.taeglich'), subtitle: t('scheduleStartNodeConfig.jedenTagZurGleichenZeit') },
    { value: 'weekdays', title: t('scheduleStartNodeConfig.werktage'), subtitle: t('scheduleStartNodeConfig.montagBisFreitag') },
    { value: 'weekly', title: t('scheduleStartNodeConfig.bestimmteTage'), subtitle: t('scheduleStartNodeConfig.wochentageAuswaehlen') },
    { value: 'calendar', title: t('scheduleStartNodeConfig.einAndererZeitraum'), subtitle: t('scheduleStartNodeConfig.monatlichOderJaehrlich') },
    { value: 'interval', title: t('scheduleStartNodeConfig.intervall'), subtitle: t('scheduleStartNodeConfig.inRegelmaessigenAbstaenden') },
  ];
}

const MONTH_NAMES_DE = [
  'Januar',
  'Februar',
  'März',
  'April',
  'Mai',
  'Juni',
  'Juli',
  'August',
  'September',
  'Oktober',
  'November',
  'Dezember',
];

function _getIntervalUnits(t: (key: string) => string): { value: IntervalUnit; label: string; title: string }[] {
  return [
    { value: 'seconds', label: t('scheduleStartNodeConfig.sek'), title: t('scheduleStartNodeConfig.sekunden') },
    { value: 'minutes', label: t('scheduleStartNodeConfig.min'), title: t('scheduleStartNodeConfig.minuten') },
    { value: 'hours', label: t('scheduleStartNodeConfig.h'), title: t('scheduleStartNodeConfig.stunden') },
    { value: 'days', label: t('scheduleStartNodeConfig.d'), title: t('scheduleStartNodeConfig.tage') },
    { value: 'years', label: t('scheduleStartNodeConfig.a'), title: t('scheduleStartNodeConfig.jahre') },
  ];
}

function timeString(hour: number, minute: number): string {
  return `${String(Math.max(0, Math.min(23, hour))).padStart(2, '0')}:${String(Math.max(0, Math.min(59, minute))).padStart(2, '0')}`;
}

function commitSpec(next: ScheduleSpec, updateParam: (key: string, value: unknown) => void) {
  updateParam('schedule', next);
  updateParam('cron', buildCronFromSpec(next));
}

function clampInterval(value: number, unit: IntervalUnit): number {
  const v = Math.max(1, Math.floor(value) || 1);
  switch (unit) {
    case 'seconds':
      return Math.min(59, v);
    case 'minutes':
      return Math.min(59, v);
    case 'hours':
      return Math.min(23, v);
    case 'days':
      return Math.min(31, v);
    case 'years':
      return Math.min(99, v);
    default:
      return v;
  }
}

const EASE_SMOOTH = [0.33, 1, 0.68, 1] as const;

export const ScheduleStartNodeConfig: React.FC<NodeConfigRendererProps> = ({ params, updateParam }) => {
  const { t } = useLanguage();
  const modeOptions = _getModeOptions(t);
  const intervalUnits = _getIntervalUnits(t);
  const [spec, setSpec] = useState<ScheduleSpec>(() => scheduleSpecFromParams(params));
  const prefersReducedMotion = useReducedMotion();
  const specModeRef = useRef(spec.mode);
  specModeRef.current = spec.mode;

  useEffect(() => {
    const derived = scheduleSpecFromParams(params as Record<string, unknown>);
    console.log('[ScheduleStartNode] useEffect params → setSpec', {
      paramsCron: params.cron,
      paramsSchedule: params.schedule,
      derivedMode: derived.mode,
      previousSpecMode: specModeRef.current,
    });
    setSpec(derived);
  }, [params.cron, params.schedule]);

  useEffect(() => {
    console.log('[ScheduleStartNode] spec.mode changed (UI sollte passen)', {
      specMode: spec.mode,
      cssBlockBase: styles.scheduleModeBlock,
      cssBlockActive: styles.scheduleModeBlockActive,
    });
  }, [spec.mode]);

  const push = useCallback(
    (next: ScheduleSpec) => {
      setSpec(next);
      commitSpec(next, updateParam);
    },
    [updateParam]
  );

  const setMode = (mode: ScheduleMode) => {
    console.log('[ScheduleStartNode] setMode', {
      from: spec.mode,
      to: mode,
      refMode: specModeRef.current,
    });
    const base: ScheduleSpec = { ...spec, mode };
    if (mode === 'weekly' && base.weekdays.length === 0) {
      base.weekdays = [1, 2, 3, 4, 5];
    }
    if (mode === 'calendar') {
      base.calendarPeriod = base.calendarPeriod ?? 'monthly';
    }
    push(base);
  };

  const onModeCardPointerEvent = (
    phase: 'pointerdown' | 'click',
    e: React.PointerEvent | React.MouseEvent,
    o: { value: ScheduleMode; title: string; subtitle: string }
  ) => {
    const el = e.target as HTMLElement;
    const cur = e.currentTarget as HTMLElement;
    const isLast = o.value === 'interval';
    if (!isLast) return;
    const cx = 'clientX' in e ? e.clientX : 0;
    const cy = 'clientY' in e ? e.clientY : 0;
    const hit = typeof document !== 'undefined' ? document.elementFromPoint(cx, cy) : null;
    const hitH = hit as HTMLElement | null;
    console.log(`[ScheduleStartNode] ${phase} — unterstes Element (Intervall)`, {
      intendedMode: o.value,
      title: o.title,
      specModeClosure: spec.mode,
      specModeRef: specModeRef.current,
      eventPhase: e.nativeEvent.eventPhase,
      target: { tag: el?.tagName, className: el?.className, id: el?.id },
      currentTarget: { tag: cur?.tagName, className: cur?.className },
      clientX: cx,
      clientY: cy,
      pointerId: 'pointerId' in e ? (e as React.PointerEvent).pointerId : undefined,
      isTrusted: e.nativeEvent.isTrusted,
      elementFromPoint: hitH
        ? {
            tag: hitH.tagName,
            className: hitH.className,
            dataScheduleMode: hitH.closest?.('[data-schedule-mode]')?.getAttribute('data-schedule-mode'),
            textSlice: (hitH.textContent ?? '').slice(0, 60),
          }
        : null,
    });
  };

  const onTimeChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
    const v = ev.target.value;
    if (!v) return;
    const [hs, ms] = v.split(':');
    const hour = Number(hs);
    const minute = Number(ms);
    if (Number.isNaN(hour) || Number.isNaN(minute)) return;
    push({ ...spec, hour, minute });
  };

  const toggleWeekday = (cronDow: number) => {
    const set = new Set(spec.weekdays);
    if (set.has(cronDow)) set.delete(cronDow);
    else set.add(cronDow);
    let weekdays = [...set];
    if (weekdays.length === 0) weekdays = [cronDow];
    push({ ...spec, weekdays });
  };

  const setCalendarPeriod = (calendarPeriod: CalendarPeriod) => {
    push({ ...spec, calendarPeriod });
  };

  const setIntervalUnit = (intervalUnit: IntervalUnit) => {
    const next = { ...spec, intervalUnit };
    next.intervalValue = clampInterval(next.intervalValue, intervalUnit);
    push(next);
  };

  const panelTransition = prefersReducedMotion
    ? { duration: 0 }
    : {
        height: { duration: 0.44, ease: EASE_SMOOTH },
        opacity: { duration: 0.3, ease: 'easeOut' as const },
      };

  return (
    <div className={styles.schedulePanel}>
      <p className={styles.startNodeDocIntro}>
        Legen Sie fest, <strong>wann</strong> dieser Workflow automatisch laufen soll. Der technische Cron-Ausdruck wird
        unten automatisch erzeugt.
      </p>

      <LayoutGroup>
      <div className={styles.scheduleModeStack}>
        {modeOptions.map((o) => (
          <motion.div
            key={o.value}
            data-schedule-mode={o.value}
            data-active={spec.mode === o.value ? 'true' : 'false'}
            className={
              spec.mode === o.value
                ? `${styles.scheduleModeBlock} ${styles.scheduleModeBlockActive}`
                : styles.scheduleModeBlock
            }
          >
            <motion.button
              type="button"
              className={styles.scheduleModeCard}
              onPointerDown={(e) => onModeCardPointerEvent('pointerdown', e, o)}
              onClick={(e) => {
                onModeCardPointerEvent('click', e, o);
                setMode(o.value);
              }}
              whileTap={prefersReducedMotion ? undefined : { scale: 0.992 }}
              transition={{ type: 'spring', stiffness: 520, damping: 32 }}
            >
              <span className={styles.scheduleModeCardTitle}>{o.title}</span>
              <span className={styles.scheduleModeCardSubtitle}>{o.subtitle}</span>
            </motion.button>

            <AnimatePresence initial={false}>
              {spec.mode === o.value && (
                <motion.div
                  key={`panel-${o.value}`}
                  className={styles.scheduleModeConfigShell}
                  initial={{ height: 0, opacity: 0 }}
                  animate={{ height: 'auto', opacity: 1 }}
                  exit={{ height: 0, opacity: 0 }}
                  transition={panelTransition}
                  style={{ overflow: 'hidden' }}
                >
                  <div className={styles.scheduleModeConfig}>
                {o.value === 'daily' && (
                  <label className={styles.scheduleFieldRow}>
                    <span className={styles.scheduleFieldLabel}>Uhrzeit</span>
                    <input
                      type="time"
                      step={60}
                      className={styles.scheduleTimeInput}
                      value={timeString(spec.hour, spec.minute)}
                      onChange={onTimeChange}
                    />
                  </label>
                )}

                {o.value === 'weekdays' && (
                  <label className={styles.scheduleFieldRow}>
                    <span className={styles.scheduleFieldLabel}>Uhrzeit</span>
                    <input
                      type="time"
                      step={60}
                      className={styles.scheduleTimeInput}
                      value={timeString(spec.hour, spec.minute)}
                      onChange={onTimeChange}
                    />
                  </label>
                )}

                {o.value === 'weekly' && (
                  <>
                    <div className={styles.scheduleFieldCol}>
                      <span className={styles.scheduleFieldLabel}>Wochentage</span>
                      <div className={styles.scheduleWeekdayToggles}>
                        {WEEKDAYS_MO_SO.map(({ cronDow, label }) => (
                          <button
                            key={cronDow}
                            type="button"
                            className={
                              spec.weekdays.includes(cronDow) ? styles.scheduleDayOn : styles.scheduleDayOff
                            }
                            onClick={() => toggleWeekday(cronDow)}
                          >
                            {label}
                          </button>
                        ))}
                      </div>
                    </div>
                    <label className={styles.scheduleFieldRow}>
                      <span className={styles.scheduleFieldLabel}>Uhrzeit</span>
                      <input
                        type="time"
                        step={60}
                        className={styles.scheduleTimeInput}
                        value={timeString(spec.hour, spec.minute)}
                        onChange={onTimeChange}
                      />
                    </label>
                  </>
                )}

                {o.value === 'calendar' && (
                  <>
                    <div className={styles.scheduleSubModes}>
                      <button
                        type="button"
                        className={
                          spec.calendarPeriod === 'monthly'
                            ? `${styles.scheduleSubModeBtn} ${styles.scheduleSubModeBtnOn}`
                            : styles.scheduleSubModeBtn
                        }
                        onClick={() => setCalendarPeriod('monthly')}
                      >
                        Monatlich
                      </button>
                      <button
                        type="button"
                        className={
                          spec.calendarPeriod === 'yearly'
                            ? `${styles.scheduleSubModeBtn} ${styles.scheduleSubModeBtnOn}`
                            : styles.scheduleSubModeBtn
                        }
                        onClick={() => setCalendarPeriod('yearly')}
                      >
                        Jährlich
                      </button>
                    </div>

                    {spec.calendarPeriod === 'monthly' && (
                      <label className={styles.scheduleFieldRow}>
                        <span className={styles.scheduleFieldLabel}>Monatstag</span>
                        <select
                          className={styles.scheduleSelect}
                          value={spec.monthDay}
                          onChange={(e) => push({ ...spec, monthDay: Number(e.target.value) })}
                        >
                          {Array.from({ length: 31 }, (_, i) => i + 1).map((d) => (
                            <option key={d} value={d}>
                              {d}.
                            </option>
                          ))}
                        </select>
                      </label>
                    )}

                    {spec.calendarPeriod === 'yearly' && (
                      <div className={styles.scheduleYearlyRow}>
                        <label className={styles.scheduleFieldRowGrow}>
                          <span className={styles.scheduleFieldLabel}>Monat</span>
                          <select
                            className={styles.scheduleSelect}
                            value={spec.monthIndex}
                            onChange={(e) => push({ ...spec, monthIndex: Number(e.target.value) })}
                          >
                            {MONTH_NAMES_DE.map((name, i) => (
                              <option key={i + 1} value={i + 1}>
                                {name}
                              </option>
                            ))}
                          </select>
                        </label>
                        <label className={styles.scheduleFieldRowGrow}>
                          <span className={styles.scheduleFieldLabel}>Tag</span>
                          <select
                            className={styles.scheduleSelect}
                            value={spec.monthDay}
                            onChange={(e) => push({ ...spec, monthDay: Number(e.target.value) })}
                          >
                            {Array.from({ length: 31 }, (_, i) => i + 1).map((d) => (
                              <option key={d} value={d}>
                                {d}.
                              </option>
                            ))}
                          </select>
                        </label>
                      </div>
                    )}

                    <label className={styles.scheduleFieldRow}>
                      <span className={styles.scheduleFieldLabel}>Uhrzeit</span>
                      <input
                        type="time"
                        step={60}
                        className={styles.scheduleTimeInput}
                        value={timeString(spec.hour, spec.minute)}
                        onChange={onTimeChange}
                      />
                    </label>
                  </>
                )}

                {o.value === 'interval' && (
                  <div className={styles.scheduleIntervalRow}>
                    <span className={styles.scheduleFieldLabel}>{t('scheduleStartNodeConfig.alle')}</span>
                    <input
                      type="number"
                      min={1}
                      className={styles.scheduleNumberInput}
                      value={spec.intervalValue}
                      onChange={(e) =>
                        push({
                          ...spec,
                          intervalValue: clampInterval(Number(e.target.value) || 1, spec.intervalUnit),
                        })
                      }
                    />
                    <select
                      className={styles.scheduleUnitSelect}
                      value={spec.intervalUnit}
                      onChange={(e) => setIntervalUnit(e.target.value as IntervalUnit)}
                      title={intervalUnits.find((u) => u.value === spec.intervalUnit)?.title}
                    >
                      {intervalUnits.map((u) => (
                        <option key={u.value} value={u.value} title={u.title}>
                          {u.label}
                        </option>
                      ))}
                    </select>
                  </div>
                )}
                  </div>
                </motion.div>
              )}
            </AnimatePresence>
          </motion.div>
        ))}
      </div>

      </LayoutGroup>
    </div>
  );
};
