'use client';

import { useEffect, useState } from 'react';
import { Calendar, Clock, MapPin, Zap, Info, Loader2 } from 'lucide-react';
import type {
  LeagueConfigFormModel,
  LeagueSchedulePreviewDTO,
} from '@gridpilot/racing/application';
import type { Weekday } from '@gridpilot/racing/domain/value-objects/Weekday';
import Heading from '@/components/ui/Heading';
import Input from '@/components/ui/Input';
import SegmentedControl from '@/components/ui/SegmentedControl';

type RecurrenceStrategy = NonNullable<LeagueConfigFormModel['timings']>['recurrenceStrategy'];

interface LeagueTimingsSectionProps {
  form: LeagueConfigFormModel;
  onChange?: (form: LeagueConfigFormModel) => void;
  readOnly?: boolean;
  errors?: {
    qualifyingMinutes?: string;
    mainRaceMinutes?: string;
    roundsPlanned?: string;
  };
  /**
   * Optional override for the section heading.
   * When omitted, defaults to "Schedule & timings".
   */
  title?: string;
  /**
   * Local wizard-only weekend template identifier.
   */
  weekendTemplate?: string;
  /**
   * Callback when the weekend template selection changes.
   */
  onWeekendTemplateChange?: (template: string) => void;
}

export function LeagueTimingsSection({
  form,
  onChange,
  readOnly,
  errors,
  title,
  weekendTemplate,
  onWeekendTemplateChange,
}: LeagueTimingsSectionProps) {
  const disabled = readOnly || !onChange;
  const timings = form.timings;

  const [schedulePreview, setSchedulePreview] =
    useState<LeagueSchedulePreviewDTO | null>(null);
  const [schedulePreviewError, setSchedulePreviewError] = useState<string | null>(
    null,
  );
  const [isSchedulePreviewLoading, setIsSchedulePreviewLoading] = useState(false);

  const updateTimings = (
    patch: Partial<NonNullable<LeagueConfigFormModel['timings']>>,
  ) => {
    if (!onChange) return;
    onChange({
      ...form,
      timings: {
        ...timings,
        ...patch,
      },
    });
  };

  const handleRoundsChange = (value: string) => {
    if (!onChange) return;
    const trimmed = value.trim();
    if (trimmed === '') {
      updateTimings({ roundsPlanned: undefined });
      return;
    }
    const parsed = parseInt(trimmed, 10);
    updateTimings({
      roundsPlanned: Number.isNaN(parsed) || parsed <= 0 ? undefined : parsed,
    });
  };

  const showSprint =
    form.scoring.patternId === 'sprint-main-driver' ||
    (typeof timings.sprintRaceMinutes === 'number' && timings.sprintRaceMinutes > 0);

  const recurrenceStrategy: RecurrenceStrategy =
    timings.recurrenceStrategy ?? 'weekly';

  const weekdays: Weekday[] = (timings.weekdays ?? []) as Weekday[];

  const handleWeekdayToggle = (day: Weekday) => {
    const current = new Set(weekdays);
    if (current.has(day)) {
      current.delete(day);
    } else {
      current.add(day);
    }
    updateTimings({ weekdays: Array.from(current).sort() });
  };

  const handleRecurrenceChange = (value: string) => {
    updateTimings({
      recurrenceStrategy: value as RecurrenceStrategy,
    });
  };

  const requiresWeekdaySelection =
    (recurrenceStrategy === 'weekly' || recurrenceStrategy === 'everyNWeeks') &&
    weekdays.length === 0;

  useEffect(() => {
    if (!timings) return;

    const {
      seasonStartDate,
      raceStartTime,
      timezoneId,
      recurrenceStrategy: currentStrategy,
      intervalWeeks,
      weekdays: currentWeekdays,
      monthlyOrdinal,
      monthlyWeekday,
      roundsPlanned,
    } = timings;

    const hasCoreFields =
      !!seasonStartDate &&
      !!raceStartTime &&
      !!timezoneId &&
      !!currentStrategy &&
      typeof roundsPlanned === 'number' &&
      roundsPlanned > 0;

    if (!hasCoreFields) {
      setSchedulePreview(null);
      setSchedulePreviewError(null);
      setIsSchedulePreviewLoading(false);
      return;
    }

    if (
      (currentStrategy === 'weekly' || currentStrategy === 'everyNWeeks') &&
      (!currentWeekdays || currentWeekdays.length === 0)
    ) {
      setSchedulePreview(null);
      setSchedulePreviewError(null);
      setIsSchedulePreviewLoading(false);
      return;
    }

    const controller = new AbortController();
    const timeoutId = setTimeout(async () => {
      try {
        setIsSchedulePreviewLoading(true);
        setSchedulePreviewError(null);

        const payload = {
          seasonStartDate,
          raceStartTime,
          timezoneId,
          recurrenceStrategy: currentStrategy,
          intervalWeeks,
          weekdays: currentWeekdays,
          monthlyOrdinal,
          monthlyWeekday,
          plannedRounds: roundsPlanned,
        };

        const response = await fetch('/api/leagues/schedule-preview', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(payload),
          signal: controller.signal,
        });

        if (!response.ok) {
          const message =
            response.status === 400
              ? 'Could not compute schedule with current values.'
              : 'Failed to load schedule preview.';
          setSchedulePreviewError(message);
          return;
        }

        const data = (await response.json()) as LeagueSchedulePreviewDTO;
        setSchedulePreview(data);
      } catch (err) {
        if ((err as any).name === 'AbortError') {
          return;
        }
        setSchedulePreviewError('Could not compute schedule with current values.');
      } finally {
        setIsSchedulePreviewLoading(false);
      }
    }, 400);

    return () => {
      clearTimeout(timeoutId);
      controller.abort();
    };
  }, [
    timings?.seasonStartDate,
    timings?.raceStartTime,
    timings?.timezoneId,
    timings?.recurrenceStrategy,
    timings?.intervalWeeks,
    timings?.monthlyOrdinal,
    timings?.monthlyWeekday,
    timings?.roundsPlanned,
    // eslint-disable-next-line react-hooks/exhaustive-deps
    JSON.stringify(timings?.weekdays ?? []),
  ]);

  if (disabled) {
    return (
      <div className="space-y-4">
        <Heading level={3} className="text-lg font-semibold text-white">
          {title ?? 'Schedule & timings'}
        </Heading>

        <div className="space-y-3 text-sm text-gray-300">
          <div>
            <span className="font-medium text-gray-200">Planned rounds:</span>{' '}
            <span>{timings.roundsPlanned ?? '—'}</span>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
            <div>
              <span className="font-medium text-gray-200">Qualifying:</span>{' '}
              <span>{timings.qualifyingMinutes} min</span>
            </div>
            <div>
              <span className="font-medium text-gray-200">Main race:</span>{' '}
              <span>{timings.mainRaceMinutes} min</span>
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
            <div>
              <span className="font-medium text-gray-200">Practice:</span>{' '}
              <span>
                {typeof timings.practiceMinutes === 'number'
                  ? `${timings.practiceMinutes} min`
                  : '—'}
              </span>
            </div>
            {showSprint && (
              <div>
                <span className="font-medium text-gray-200">Sprint:</span>{' '}
                <span>
                  {typeof timings.sprintRaceMinutes === 'number'
                    ? `${timings.sprintRaceMinutes} min`
                    : '—'}
                </span>
              </div>
            )}
          </div>

          <div>
            <span className="font-medium text-gray-200">Sessions per weekend:</span>{' '}
            <span>{timings.sessionCount}</span>
          </div>

          <p className="text-xs text-gray-500">
            Used for planning and hints; alpha-only and not yet fully wired into
            race scheduling.
          </p>
        </div>
      </div>
    );
  }

  const handleNumericMinutesChange = (
    field:
      | 'practiceMinutes'
      | 'qualifyingMinutes'
      | 'sprintRaceMinutes'
      | 'mainRaceMinutes',
    raw: string,
  ) => {
    if (!onChange) return;
    const trimmed = raw.trim();
    if (trimmed === '') {
      updateTimings({ [field]: undefined } as Partial<
        NonNullable<LeagueConfigFormModel['timings']>
      >);
      return;
    }
    const parsed = parseInt(trimmed, 10);
    updateTimings({
      [field]:
        Number.isNaN(parsed) || parsed <= 0 ? undefined : parsed,
    } as Partial<NonNullable<LeagueConfigFormModel['timings']>>);
  };

  const handleSessionCountChange = (raw: string) => {
    const trimmed = raw.trim();
    if (trimmed === '') {
      updateTimings({ sessionCount: 1 });
      return;
    }
    const parsed = parseInt(trimmed, 10);
    updateTimings({
      sessionCount: Number.isNaN(parsed) || parsed <= 0 ? 1 : parsed,
    });
  };

  const weekendTemplateValue = weekendTemplate ?? '';

  return (
    <div className="space-y-8">
      {/* Step intro */}
      <div className="rounded-lg bg-primary-blue/5 border border-primary-blue/20 p-4">
        <div className="flex items-start gap-2">
          <Info className="w-4 h-4 text-primary-blue shrink-0 mt-0.5" />
          <p className="text-sm text-gray-300">
            <span className="font-medium text-primary-blue">Quick setup:</span> Pick a weekend template and season length. The detailed schedule configuration is optional—you can set it now or schedule races manually later.
          </p>
        </div>
      </div>

      {/* 1. Weekend template - FIRST */}
      <section className="space-y-4">
        <div className="flex items-center gap-2">
          <Zap className="w-4 h-4 text-primary-blue" />
          <h4 className="text-sm font-semibold text-white">
            1. Choose your race weekend format
          </h4>
        </div>
        <p className="text-xs text-gray-500">
          This determines session counts and sets sensible duration defaults
        </p>
        <SegmentedControl
          options={[
            { value: 'feature', label: 'Feature only', description: '1 race per weekend' },
            { value: 'sprintFeature', label: 'Sprint + Feature', description: '2 races per weekend' },
            { value: 'endurance', label: 'Endurance', description: 'Longer races' },
          ]}
          value={weekendTemplateValue}
          onChange={onWeekendTemplateChange}
        />
      </section>

      {/* 2. Season length */}
      <section className="space-y-4">
        <div className="flex items-center gap-2">
          <Calendar className="w-4 h-4 text-primary-blue" />
          <h4 className="text-sm font-semibold text-white">
            2. How many race rounds?
          </h4>
        </div>
        <div className="space-y-2">
          <Input
            type="number"
            value={
              typeof timings.roundsPlanned === 'number'
                ? String(timings.roundsPlanned)
                : ''
            }
            onChange={(e) => handleRoundsChange(e.target.value)}
            min={1}
            error={!!errors?.roundsPlanned}
            errorMessage={errors?.roundsPlanned}
            className="w-32"
            placeholder="e.g., 10"
          />
          <div className="flex flex-wrap gap-2">
            <button
              type="button"
              onClick={() => handleRoundsChange('6')}
              className="px-3 py-1.5 rounded text-xs bg-iron-gray border border-charcoal-outline text-gray-300 hover:border-primary-blue hover:text-primary-blue transition-colors"
            >
              Short season (6)
            </button>
            <button
              type="button"
              onClick={() => handleRoundsChange('10')}
              className="px-3 py-1.5 rounded text-xs bg-iron-gray border border-charcoal-outline text-gray-300 hover:border-primary-blue hover:text-primary-blue transition-colors"
            >
              Medium season (10)
            </button>
            <button
              type="button"
              onClick={() => handleRoundsChange('16')}
              className="px-3 py-1.5 rounded text-xs bg-iron-gray border border-charcoal-outline text-gray-300 hover:border-primary-blue hover:text-primary-blue transition-colors"
            >
              Long season (16)
            </button>
          </div>
          <p className="text-xs text-gray-500">
            Used for drop rule suggestions. Can be approximate—you can always add or remove rounds.
          </p>
        </div>
      </section>

      {/* 3. Optional: Detailed schedule */}
      <section className="space-y-4">
        <div className="rounded-lg border-2 border-dashed border-charcoal-outline p-4 space-y-4">
          <div className="flex items-start justify-between gap-4">
            <div className="flex-1">
              <div className="flex items-center gap-2 mb-1">
                <Clock className="w-4 h-4 text-gray-400" />
                <h4 className="text-sm font-semibold text-white">
                  3. Automatic schedule (optional)
                </h4>
              </div>
              <p className="text-xs text-gray-500">
                Configure when races happen automatically, or skip this and schedule rounds manually later
              </p>
            </div>
          </div>

          <div className="space-y-4">
            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
            <div>
              <label className="mb-1 block text-sm font-medium text-gray-300">
                Season start date
              </label>
              <div className="max-w-xs">
                <Input
                  type="date"
                  value={timings.seasonStartDate ?? ''}
                  onChange={(e) =>
                    updateTimings({ seasonStartDate: e.target.value || undefined })
                  }
                />
              </div>
              <p className="mt-1 text-xs text-gray-500">
                Round 1 will use this date; later rounds follow your pattern.
              </p>
            </div>

            <div>
              <label className="mb-1 block text-sm font-medium text-gray-300">
                Race start time
              </label>
              <div className="max-w-xs">
                <Input
                  type="time"
                  value={timings.raceStartTime ?? ''}
                  onChange={(e) =>
                    updateTimings({ raceStartTime: e.target.value || undefined })
                  }
                />
              </div>
              <p className="mt-1 text-xs text-gray-500">
                Local time in your league's timezone.
              </p>
            </div>

            <div>
              <label className="mb-1 block text-sm font-medium text-gray-300">
                Timezone
              </label>
              <div className="max-w-xs">
                <select
                  className="block w-full rounded-md border-0 px-4 py-3 bg-iron-gray text-white shadow-sm ring-1 ring-inset ring-charcoal-outline focus:ring-2 focus:ring-inset focus:ring-primary-blue transition-all duration-150 sm:text-sm sm:leading-6"
                  value={timings.timezoneId ?? 'Europe/Berlin'}
                  onChange={(e) =>
                    updateTimings({ timezoneId: e.target.value || undefined })
                  }
                >
                  <option value="Europe/Berlin">Europe/Berlin</option>
                  <option value="Europe/London">Europe/London</option>
                  <option value="UTC">UTC</option>
                  <option value="America/New_York">America/New_York</option>
                  <option value="America/Los_Angeles">America/Los_Angeles</option>
                </select>
              </div>
            </div>
            </div>

            <div className="space-y-3">
              <label className="block text-sm font-medium text-gray-300">
                How often do races occur?
              </label>
              <SegmentedControl
                options={[
                  { value: 'weekly', label: 'Weekly' },
                  { value: 'everyNWeeks', label: 'Bi-weekly' },
                ]}
                value={recurrenceStrategy}
                onChange={handleRecurrenceChange}
              />
              
              {recurrenceStrategy === 'everyNWeeks' && (
                <div className="flex items-center gap-2 text-sm">
                  <span className="text-gray-300">Every</span>
                  <Input
                    type="number"
                    min={1}
                    value={
                      typeof timings.intervalWeeks === 'number'
                        ? String(timings.intervalWeeks)
                        : '2'
                    }
                    onChange={(e) => {
                      const raw = e.target.value.trim();
                      if (raw === '') {
                        updateTimings({ intervalWeeks: undefined });
                        return;
                      }
                      const parsed = parseInt(raw, 10);
                      updateTimings({
                        intervalWeeks:
                          Number.isNaN(parsed) || parsed <= 0 ? 2 : parsed,
                      });
                    }}
                    className="w-20"
                  />
                  <span className="text-gray-300">weeks</span>
                </div>
              )}
            </div>

            <div className="space-y-2">
              <div className="flex items-center justify-between gap-2">
                <label className="block text-sm font-medium text-gray-300">
                  Which day(s)?
                </label>
                {requiresWeekdaySelection && (
                  <span className="text-xs text-warning-amber">
                    Pick at least one
                  </span>
                )}
              </div>
              <div className="flex flex-wrap gap-2">
                {(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as Weekday[]).map(
                  (day) => {
                    const isActive = weekdays.includes(day);
                    return (
                      <button
                        key={day}
                        type="button"
                        onClick={() => handleWeekdayToggle(day)}
                        className={`px-3 py-1.5 text-xs font-medium rounded-full border transition-all duration-200 ${
                          isActive
                            ? 'bg-primary-blue text-white border-primary-blue shadow-[0_0_10px_rgba(25,140,255,0.3)]'
                            : 'bg-iron-gray/80 text-gray-300 border-charcoal-outline hover:bg-charcoal-outline hover:text-white hover:border-gray-500'
                        }`}
                      >
                        {day}
                      </button>
                    );
                  },
                )}
              </div>
            </div>
          </div>

          {/* Schedule preview */}
          {(timings.seasonStartDate && timings.raceStartTime && weekdays.length > 0) && (
            <div className="space-y-3 rounded-lg border border-charcoal-outline bg-iron-gray/40 p-4">
            <div className="flex items-center justify-between gap-2">
              <div className="flex items-center gap-2">
                <Calendar className="w-4 h-4 text-primary-blue" />
                <div>
                  <p className="text-sm font-medium text-gray-200">
                    Schedule preview
                  </p>
                  <p className="text-xs text-gray-400">
                    {schedulePreview?.summary ??
                      'Set a start date, time, and at least one weekday to preview the schedule.'}
                  </p>
                </div>
              </div>
              {isSchedulePreviewLoading && (
                <Loader2 className="w-4 h-4 text-primary-blue animate-spin" />
              )}
            </div>

            <div className="space-y-2">
              {schedulePreviewError && (
                <div className="rounded-md bg-warning-amber/10 p-3 border border-warning-amber/20 text-xs text-warning-amber flex items-start gap-2">
                  <span className="shrink-0">⚠️</span>
                  <span>{schedulePreviewError}</span>
                </div>
              )}

              {!schedulePreview && !schedulePreviewError && (
                <p className="text-xs text-gray-500 flex items-start gap-1.5">
                  <Info className="w-3 h-3 mt-0.5 shrink-0" />
                  <span>Adjust the fields above to see a preview of your calendar.</span>
                </p>
              )}

              {schedulePreview && (
                <div className="space-y-2">
                  <p className="text-xs text-gray-500">
                    First few rounds with your current settings:
                  </p>
                  <div className="space-y-1.5">
                    {schedulePreview.rounds.map((round) => {
                      const date = new Date(round.scheduledAt);
                      const dateStr = date.toLocaleDateString(undefined, {
                        weekday: 'short',
                        day: 'numeric',
                        month: 'short',
                      });
                      const timeStr = date.toLocaleTimeString([], {
                        hour: '2-digit',
                        minute: '2-digit',
                      });

                      return (
                        <div
                          key={round.roundNumber}
                          className="flex items-center justify-between gap-2 px-3 py-2 rounded-md bg-deep-graphite/40 text-xs"
                        >
                          <span className="font-medium text-gray-300">
                            Round {round.roundNumber}
                          </span>
                          <span className="text-gray-200">
                            {dateStr}, {timeStr}{' '}
                            <span className="text-gray-500">
                              {round.timezoneId}
                            </span>
                          </span>
                        </div>
                      );
                    })}

                    {typeof timings.roundsPlanned === 'number' &&
                      timings.roundsPlanned > schedulePreview.rounds.length && (
                        <p className="pt-1 text-xs text-gray-500 text-center">
                          + {timings.roundsPlanned - schedulePreview.rounds.length} more rounds scheduled
                        </p>
                      )}
                  </div>
                </div>
              )}
            </div>
          </div>
            </div>
          )}
        </div>
      </section>

      {/* 4. Optional: Session duration overrides */}
      <details className="group">
        <summary className="cursor-pointer list-none">
          <div className="flex items-center justify-between p-4 rounded-lg border border-charcoal-outline bg-iron-gray/20 hover:border-primary-blue/50 transition-colors">
            <div className="flex items-center gap-2">
              <Clock className="w-4 h-4 text-gray-400" />
              <h4 className="text-sm font-semibold text-white">
                4. Customize session durations (optional)
              </h4>
            </div>
            <span className="text-xs text-gray-500 group-open:hidden">
              Click to customize
            </span>
          </div>
        </summary>
        
        <div className="mt-4 pl-6 space-y-4">
          <p className="text-xs text-gray-500">
            Your weekend template already set reasonable defaults. Only change these if you need specific timings.
          </p>
          
          <div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4">
            <div className="space-y-2">
              <label className="block text-xs font-medium text-gray-300">
                Practice (min)
              </label>
              <Input
                type="number"
                value={
                  typeof timings.practiceMinutes === 'number' && timings.practiceMinutes > 0
                    ? String(timings.practiceMinutes)
                    : ''
                }
                onChange={(e) => handleNumericMinutesChange('practiceMinutes', e.target.value)}
                min={0}
                className="w-24"
                placeholder="20"
              />
            </div>

            <div className="space-y-2">
              <label className="block text-xs font-medium text-gray-300">
                Qualifying (min)
              </label>
              <Input
                type="number"
                value={
                  typeof timings.qualifyingMinutes === 'number' && timings.qualifyingMinutes > 0
                    ? String(timings.qualifyingMinutes)
                    : ''
                }
                onChange={(e) => handleNumericMinutesChange('qualifyingMinutes', e.target.value)}
                min={5}
                error={!!errors?.qualifyingMinutes}
                errorMessage={errors?.qualifyingMinutes}
                className="w-24"
                placeholder="30"
              />
            </div>

            {showSprint && (
              <div className="space-y-2">
                <label className="block text-xs font-medium text-gray-300">
                  Sprint (min)
                </label>
                <Input
                  type="number"
                  value={
                    typeof timings.sprintRaceMinutes === 'number' && timings.sprintRaceMinutes > 0
                      ? String(timings.sprintRaceMinutes)
                      : ''
                  }
                  onChange={(e) => handleNumericMinutesChange('sprintRaceMinutes', e.target.value)}
                  min={0}
                  className="w-24"
                  placeholder="20"
                />
              </div>
            )}

            <div className="space-y-2">
              <label className="block text-xs font-medium text-gray-300">
                Main race (min)
              </label>
              <Input
                type="number"
                value={
                  typeof timings.mainRaceMinutes === 'number' && timings.mainRaceMinutes > 0
                    ? String(timings.mainRaceMinutes)
                    : ''
                }
                onChange={(e) => handleNumericMinutesChange('mainRaceMinutes', e.target.value)}
                min={10}
                error={!!errors?.mainRaceMinutes}
                errorMessage={errors?.mainRaceMinutes}
                className="w-24"
                placeholder="40"
              />
            </div>
          </div>
        </div>
      </details>
    </div>
  );
}