'use client';

import { useState, useMemo } from 'react';
import { cn } from '@/lib/utils/cn';
import {
  parseField,
  rebuildFieldFromValues,
  validateCronField,
  FIELD_CONFIGS,
  MONTH_SHORT_NAMES,
  DOW_SHORT_NAMES,
  type FieldType,
} from '@/lib/cron/cron-engine';

// ── Per-field presets ─────────────────────────────────────────────────────────

interface Preset { label: string; value: string }

const FIELD_PRESETS: Record<FieldType, Preset[]> = {
  second: [
    { label: 'Any (*)', value: '*' },
    { label: '*/5',     value: '*/5' },
    { label: '*/10',    value: '*/10' },
    { label: '*/15',    value: '*/15' },
    { label: '*/30',    value: '*/30' },
  ],
  minute: [
    { label: 'Any (*)', value: '*' },
    { label: ':00',     value: '0' },
    { label: ':30',     value: '30' },
    { label: '*/5',     value: '*/5' },
    { label: '*/10',    value: '*/10' },
    { label: '*/15',    value: '*/15' },
    { label: '*/30',    value: '*/30' },
  ],
  hour: [
    { label: 'Any (*)',   value: '*' },
    { label: 'Midnight',  value: '0' },
    { label: '6 AM',      value: '6' },
    { label: '9 AM',      value: '9' },
    { label: 'Noon',      value: '12' },
    { label: '6 PM',      value: '18' },
    { label: 'Every 4h',  value: '*/4' },
    { label: 'Every 6h',  value: '*/6' },
    { label: '9–17',      value: '9-17' },
  ],
  dom: [
    { label: 'Any (*)',  value: '*' },
    { label: '1st',      value: '1' },
    { label: '10th',     value: '10' },
    { label: '15th',     value: '15' },
    { label: '20th',     value: '20' },
    { label: '1,15',     value: '1,15' },
    { label: '1–7',      value: '1-7' },
  ],
  month: [
    { label: 'Any (*)', value: '*' },
    { label: 'Q1',      value: '1-3' },
    { label: 'Q2',      value: '4-6' },
    { label: 'Q3',      value: '7-9' },
    { label: 'Q4',      value: '10-12' },
    { label: 'H1',      value: '1-6' },
    { label: 'H2',      value: '7-12' },
  ],
  dow: [
    { label: 'Any (*)',   value: '*' },
    { label: 'Weekdays',  value: '1-5' },
    { label: 'Weekends',  value: '0,6' },
    { label: 'Mon',       value: '1' },
    { label: 'Wed',       value: '3' },
    { label: 'Fri',       value: '5' },
    { label: 'Sun',       value: '0' },
  ],
};

// ── Grid configuration ────────────────────────────────────────────────────────

const GRID_COLS: Record<FieldType, string> = {
  second: 'grid-cols-10',
  minute: 'grid-cols-10',
  hour:   'grid-cols-8',
  dom:    'grid-cols-7',
  month:  'grid-cols-4',
  dow:    'grid-cols-7',
};

// ── Component ─────────────────────────────────────────────────────────────────

interface CronFieldEditorProps {
  fieldType: FieldType;
  value: string;
  onChange: (value: string) => void;
}

export function CronFieldEditor({ fieldType, value, onChange }: CronFieldEditorProps) {
  const [rawInput, setRawInput] = useState('');
  const [showRaw, setShowRaw] = useState(false);
  const [rawError, setRawError] = useState('');

  const config  = FIELD_CONFIGS[fieldType];
  const parsed  = useMemo(() => parseField(value, config), [value, config]);
  const presets = FIELD_PRESETS[fieldType];

  const isWildcard  = parsed?.isWildcard ?? false;
  const isSelected  = (v: number) => parsed?.values.has(v) ?? false;

  const cellLabel = (v: number): string => {
    if (fieldType === 'month') return MONTH_SHORT_NAMES[v - 1];
    if (fieldType === 'dow')   return DOW_SHORT_NAMES[v];
    return String(v).padStart(fieldType === 'second' || fieldType === 'minute' ? 2 : 1, '0');
  };

  const handleCellClick = (v: number) => {
    if (!parsed) return;
    if (isWildcard) { onChange(String(v)); return; }
    const next = new Set(parsed.values);
    if (next.has(v)) {
      next.delete(v);
      if (next.size === 0) { onChange('*'); return; }
    } else {
      next.add(v);
      if (next.size === config.max - config.min + 1) { onChange('*'); return; }
    }
    onChange(rebuildFieldFromValues(next, config));
  };

  const handleRawSubmit = () => {
    const { valid, error } = validateCronField(rawInput, fieldType);
    if (valid) {
      onChange(rawInput);
      setShowRaw(false);
      setRawInput('');
      setRawError('');
    } else {
      setRawError(error ?? 'Invalid');
    }
  };

  const cells = Array.from({ length: config.max - config.min + 1 }, (_, i) => i + config.min);
  // Pad to complete rows for DOM (31 cells, 7 cols → pad to 35)
  const colCount = parseInt(GRID_COLS[fieldType].replace('grid-cols-', ''), 10);
  const rem = cells.length % colCount;
  const padded: (number | null)[] = [...cells, ...(rem === 0 ? [] : Array<null>(colCount - rem).fill(null))];

  return (
    <div className="flex flex-col gap-4">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-baseline gap-2">
          <span className="text-xs font-mono text-muted-foreground uppercase tracking-widest">
            {config.label}
          </span>
          <span className="text-[10px] text-muted-foreground/50 font-mono">
            {config.min}–{config.max}
          </span>
        </div>
        <div className="flex items-center gap-2">
          {isWildcard && (
            <span className="text-[10px] font-mono text-primary/60 bg-primary/5 px-2 py-0.5 rounded border border-primary/15">
              any value
            </span>
          )}
          <span className="font-mono text-sm text-primary bg-primary/10 px-2.5 py-1 rounded-lg border border-primary/25">
            {value}
          </span>
        </div>
      </div>

      {/* Presets */}
      <div className="flex flex-wrap gap-1.5">
        {presets.map((preset) => (
          <button
            key={preset.value}
            onClick={() => onChange(preset.value)}
            className={cn(
              'px-2.5 py-1 text-[11px] font-mono rounded-lg border transition-all',
              value === preset.value
                ? 'bg-primary/20 border-primary/50 text-primary shadow-[0_0_8px_rgba(139,92,246,0.2)]'
                : 'glass border-border/30 text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-primary/5',
            )}
          >
            {preset.label}
          </button>
        ))}
      </div>

      {/* Value grid */}
      <div className={cn('grid gap-1', GRID_COLS[fieldType])}>
        {padded.map((v, i) => {
          if (v === null) return <div key={`pad-${i}`} />;
          const selected = isSelected(v);
          return (
            <button
              key={v}
              onClick={() => handleCellClick(v)}
              title={fieldType === 'month' ? MONTH_SHORT_NAMES[v - 1] : fieldType === 'dow' ? DOW_SHORT_NAMES[v] : String(v)}
              className={cn(
                'flex items-center justify-center text-[10px] font-mono rounded-md border transition-all',
                fieldType === 'month' || fieldType === 'dow'
                  ? 'py-2 px-1'
                  : 'aspect-square',
                isWildcard
                  ? 'bg-primary/8 border-primary/20 text-primary/50 hover:bg-primary/15 hover:border-primary/40 hover:text-primary'
                  : selected
                    ? 'bg-primary/25 border-primary/55 text-primary font-semibold shadow-[0_0_6px_rgba(139,92,246,0.25)]'
                    : 'glass border-border/20 text-muted-foreground/50 hover:border-primary/35 hover:text-foreground hover:bg-primary/5',
              )}
            >
              {cellLabel(v)}
            </button>
          );
        })}
      </div>

      {/* Custom raw input */}
      <div className="pt-1 border-t border-border/10">
        {showRaw ? (
          <div className="flex flex-col gap-2">
            <div className="flex items-center gap-2">
              <input
                value={rawInput}
                onChange={(e) => { setRawInput(e.target.value); setRawError(''); }}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') handleRawSubmit();
                  if (e.key === 'Escape') { setShowRaw(false); setRawError(''); }
                }}
                placeholder={`e.g. ${fieldType === 'minute' ? '*/15 or 0,30' : fieldType === 'hour' ? '9-17' : fieldType === 'dow' ? '1-5' : '*'}`}
                className={cn(
                  'flex-1 px-3 py-1.5 text-xs font-mono bg-muted/20 border rounded-lg focus:outline-none transition-colors',
                  rawError ? 'border-destructive/50 focus:border-destructive' : 'border-border/30 focus:border-primary/50',
                )}
                autoFocus
              />
              <button
                onClick={handleRawSubmit}
                className="px-3 py-1.5 text-xs font-mono bg-primary/20 text-primary border border-primary/30 rounded-lg hover:bg-primary/30 transition-all"
              >
                Set
              </button>
              <button
                onClick={() => { setShowRaw(false); setRawError(''); }}
                className="px-3 py-1.5 text-xs font-mono glass border-border/30 text-muted-foreground rounded-lg hover:text-foreground transition-all"
              >
                Cancel
              </button>
            </div>
            {rawError && (
              <p className="text-[10px] text-destructive font-mono">{rawError}</p>
            )}
          </div>
        ) : (
          <button
            onClick={() => { setRawInput(value); setShowRaw(true); }}
            className="text-[11px] font-mono text-muted-foreground/40 hover:text-primary/70 transition-colors"
          >
            Enter custom expression →
          </button>
        )}
      </div>
    </div>
  );
}
