/**
 * AppointmentModal — create/edit an appointment (or task) entry.
 *
 * Pre-fills start_at / end_at when the caller supplies a `prefillDate`
 * (used by clicking an empty day cell in MonthView).
 */

import React, { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Modal } from '@/components/ui/Modal';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Select } from '@/components/ui/Select';
import {
  createEntry,
  updateEntry,
  deleteEntry,
  type Calendar,
  type CalendarEntry,
  type EntryCreatePayload,
  type EntryPriority,
  type EntrySubtype,
} from '@/api/calendar';

export interface AppointmentModalProps {
  open: boolean;
  onClose: () => void;
  /** Existing entry for edit mode. */
  entry?: CalendarEntry | null;
  /** Date used to pre-fill start_at in create mode (defaults to today). */
  prefillDate?: Date | null;
  /** Available calendars (user must pick one for create). */
  calendars: Calendar[];
  /** Active calendar id, used as the default selection. */
  defaultCalendarId?: string | null;
  /** Called after a successful save. */
  onSaved: (entry: CalendarEntry) => void;
  /** Called after a successful delete. */
  onDeleted: (entryId: string) => void;
}

function toDateTimeLocalValue(d: Date | null | undefined): string {
  if (!d) return '';
  // datetime-local needs YYYY-MM-DDTHH:mm in local time
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

function fromDateTimeLocalValue(v: string): Date | null {
  if (!v) return null;
  const d = new Date(v);
  if (Number.isNaN(d.getTime())) return null;
  return d;
}

export function AppointmentModal({
  open,
  onClose,
  entry,
  prefillDate,
  calendars,
  defaultCalendarId,
  onSaved,
  onDeleted,
}: AppointmentModalProps) {
  const { t } = useTranslation();
  const isEdit = !!entry;

  const initialStart = useMemo(() => {
    if (entry?.start_at) return new Date(entry.start_at);
    if (prefillDate) {
      const d = new Date(prefillDate);
      d.setHours(9, 0, 0, 0);
      return d;
    }
    const d = new Date();
    d.setHours(9, 0, 0, 0);
    return d;
  }, [entry, prefillDate]);

  const initialEnd = useMemo(() => {
    if (entry?.end_at) return new Date(entry.end_at);
    const d = new Date(initialStart);
    d.setHours(d.getHours() + 1);
    return d;
  }, [entry, initialStart]);

  const [title, setTitle] = useState('');
  const [description, setDescription] = useState('');
  const [location, setLocation] = useState('');
  const [startAt, setStartAt] = useState<string>(toDateTimeLocalValue(initialStart));
  const [endAt, setEndAt] = useState<string>(toDateTimeLocalValue(initialEnd));
  const [allDay, setAllDay] = useState(false);
  const [priority, setPriority] = useState<EntryPriority>('medium');
  const [subtype, setSubtype] = useState<EntrySubtype>('normal');
  const [calendarId, setCalendarId] = useState<string>('');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Reset form when entry / prefill / open changes
  useEffect(() => {
    if (!open) return;
    setTitle(entry?.title ?? '');
    setDescription(entry?.description ?? '');
    setLocation(entry?.location ?? '');
    setStartAt(toDateTimeLocalValue(entry?.start_at ? new Date(entry.start_at) : initialStart));
    setEndAt(toDateTimeLocalValue(entry?.end_at ? new Date(entry.end_at) : initialEnd));
    setAllDay(entry?.all_day ?? false);
    setPriority(entry?.priority ?? 'medium');
    setSubtype(entry?.subtype ?? 'normal');
    const fallbackId =
      entry?.calendar_id ?? defaultCalendarId ?? calendars[0]?.id ?? '';
    setCalendarId(fallbackId);
    setError(null);
  }, [open, entry, defaultCalendarId, calendars, initialStart, initialEnd]);

  const handleSave = async () => {
    if (!title.trim()) {
      setError(t('validation.required'));
      return;
    }
    if (!calendarId) {
      setError(t('calendar.noCalendars'));
      return;
    }
    setSubmitting(true);
    setError(null);
    try {
      const startDate = fromDateTimeLocalValue(startAt);
      const endDate = fromDateTimeLocalValue(endAt);
      if (isEdit && entry) {
        const updated = await updateEntry(entry.id, {
          title,
          description: description || null,
          location: location || null,
          start_at: startDate ? startDate.toISOString() : null,
          end_at: endDate ? endDate.toISOString() : null,
          all_day: allDay,
          priority,
          subtype,
          calendar_id: calendarId,
        });
        onSaved(updated);
      } else {
        const payload: EntryCreatePayload = {
          calendar_id: calendarId,
          entry_type: 'appointment',
          title,
          description: description || null,
          location: location || null,
          start_at: startDate ? startDate.toISOString() : null,
          end_at: endDate ? endDate.toISOString() : null,
          all_day: allDay,
          priority,
          subtype,
          status: 'open',
        };
        const created = await createEntry(payload);
        onSaved(created);
      }
      onClose();
    } catch (e) {
      const err = e as { message?: string };
      setError(err.message ?? t('calendar.errorSave'));
    } finally {
      setSubmitting(false);
    }
  };

  const handleDelete = async () => {
    if (!entry) return;
    if (!window.confirm(t('calendar.deleteEntryConfirm'))) return;
    setSubmitting(true);
    setError(null);
    try {
      await deleteEntry(entry.id);
      onDeleted(entry.id);
      onClose();
    } catch (e) {
      const err = e as { message?: string };
      setError(err.message ?? t('calendar.errorSave'));
    } finally {
      setSubmitting(false);
    }
  };

  const calendarOptions = useMemo(
    () => [
      ...calendars.map((c) => ({ value: c.id, label: c.name })),
    ],
    [calendars]
  );

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isEdit ? t('calendar.editAppointment') : t('calendar.newAppointment')}
      size="lg"
    >
      <div className="space-y-4" data-testid="appointment-modal">
        <div>
          <label className="block text-sm font-medium text-secondary-700 mb-1">
            {t('calendar.appointmentTitle')} *
          </label>
          <Input
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            placeholder={t('calendar.appointmentTitle')}
            data-testid="appointment-title"
          />
        </div>

        <div>
          <label className="block text-sm font-medium text-secondary-700 mb-1">
            {t('calendar.appointmentCalendar')} *
          </label>
          <Select
            value={calendarId}
            onChange={(e) => setCalendarId(e.target.value)}
            options={calendarOptions}
            data-testid="appointment-calendar"
          />
        </div>

        <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-1">
              {t('calendar.appointmentStart')}
            </label>
            <Input
              type="datetime-local"
              value={startAt}
              onChange={(e) => setStartAt(e.target.value)}
              data-testid="appointment-start"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-1">
              {t('calendar.appointmentEnd')}
            </label>
            <Input
              type="datetime-local"
              value={endAt}
              onChange={(e) => setEndAt(e.target.value)}
              data-testid="appointment-end"
            />
          </div>
        </div>

        <div className="flex items-center gap-2">
          <input
            id="appointment-allday"
            type="checkbox"
            checked={allDay}
            onChange={(e) => setAllDay(e.target.checked)}
            className="h-4 w-4 rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
            data-testid="appointment-allday"
          />
          <label htmlFor="appointment-allday" className="text-sm text-secondary-700">
            {t('calendar.appointmentAllDay')}
          </label>
        </div>

        <div>
          <label className="block text-sm font-medium text-secondary-700 mb-1">
            {t('calendar.appointmentLocation')}
          </label>
          <Input
            value={location}
            onChange={(e) => setLocation(e.target.value)}
            placeholder={t('calendar.appointmentLocation')}
            data-testid="appointment-location"
          />
        </div>

        <div>
          <label className="block text-sm font-medium text-secondary-700 mb-1">
            {t('calendar.appointmentDescription')}
          </label>
          <textarea
            value={description}
            onChange={(e) => setDescription(e.target.value)}
            rows={3}
            className="w-full rounded-md border-secondary-300 focus:border-primary-500 focus:ring-primary-500"
            data-testid="appointment-description"
          />
        </div>

        <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-1">
              {t('calendar.appointmentPriority')}
            </label>
            <Select
              value={priority}
              onChange={(e) => setPriority(e.target.value as EntryPriority)}
              options={[
                { value: 'low', label: t('calendar.priority.low') },
                { value: 'medium', label: t('calendar.priority.medium') },
                { value: 'high', label: t('calendar.priority.high') },
              ]}
              data-testid="appointment-priority"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-1">
              {t('calendar.appointmentSubtype')}
            </label>
            <Select
              value={subtype}
              onChange={(e) => setSubtype(e.target.value as EntrySubtype)}
              options={[
                { value: 'normal', label: t('calendar.subtype.normal') },
                { value: 'follow_up', label: t('calendar.subtype.follow_up') },
                { value: 'private', label: t('calendar.subtype.private') },
              ]}
              data-testid="appointment-subtype"
            />
          </div>
        </div>

        {error && (
          <div className="text-sm text-danger-700 bg-danger-50 border border-danger-200 rounded-md p-2" data-testid="appointment-error">
            {error}
          </div>
        )}

        <div className="flex justify-between gap-2 pt-2">
          <div>
            {isEdit && (
              <Button
                variant="danger"
                onClick={handleDelete}
                disabled={submitting}
                data-testid="appointment-delete"
              >
                {t('calendar.delete')}
              </Button>
            )}
          </div>
          <div className="flex gap-2">
            <Button variant="ghost" onClick={onClose} disabled={submitting}>
              {t('calendar.cancel')}
            </Button>
            <Button
              variant="primary"
              onClick={handleSave}
              isLoading={submitting}
              data-testid="appointment-save"
            >
              {t('calendar.save')}
            </Button>
          </div>
        </div>
      </div>
    </Modal>
  );
}

export default AppointmentModal;
