import { useEffect, useState, type FormEvent } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { extractApiError } from '@/api/client';
import type { EngagementInput, EngagementStatus } from '@/api/types';
import {
  useCreateEngagement,
  useEngagement,
  usePatchEngagement,
} from '@/hooks/useEngagements';
import { useAuth } from '@/hooks/useAuth';
import { useToast } from '@/hooks/useToast';
import { FormField, Select, TextArea, TextInput } from '@/components/FormField';
import { LoadingState } from '@/components/LoadingState';
import { ErrorState } from '@/components/ErrorState';
import { C2ConfigCard } from '@/components/C2ConfigCard';
import { engagementStatusLabel } from '@/i18n/status';

interface FormState {
  name: string;
  description: string;
  start_date: string;
  end_date: string;
  status: EngagementStatus;
}

const EMPTY: FormState = {
  name: '',
  description: '',
  start_date: '',
  end_date: '',
  status: 'planned',
};

export function EngagementFormPage(): JSX.Element {
  const { t } = useTranslation();
  const { id } = useParams<{ id: string }>();
  const editing = Boolean(id);
  const numericId = id ? Number(id) : undefined;
  const navigate = useNavigate();
  const { push } = useToast();
  const { canEditEngagements } = useAuth();

  const detail = useEngagement(editing ? numericId : undefined);
  const createMutation = useCreateEngagement();
  const patchMutation = usePatchEngagement(numericId ?? 0);

  const [form, setForm] = useState<FormState>(EMPTY);
  const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});
  const [submitError, setSubmitError] = useState<string | null>(null);

  const STATUS_OPTIONS: { value: EngagementStatus; label: string }[] = [
    { value: 'planned', label: engagementStatusLabel('planned') },
    { value: 'active', label: engagementStatusLabel('active') },
    { value: 'closed', label: engagementStatusLabel('closed') },
  ];

  function validate(state: FormState): Partial<Record<keyof FormState, string>> {
    const errs: Partial<Record<keyof FormState, string>> = {};
    if (!state.name.trim()) errs.name = t('engagement.form.validation.nameRequired');
    if (!state.start_date) errs.start_date = t('engagement.form.validation.startDateRequired');
    if (state.end_date && state.start_date && state.end_date < state.start_date) {
      errs.end_date = t('engagement.form.validation.endDateAfterStart');
    }
    return errs;
  }

  // Hydrate edit form when data arrives.
  useEffect(() => {
    if (editing && detail.data) {
      setForm({
        name: detail.data.name,
        description: detail.data.description ?? '',
        start_date: detail.data.start_date,
        end_date: detail.data.end_date ?? '',
        status: detail.data.status,
      });
    }
  }, [editing, detail.data]);

  if (editing && detail.isLoading) return <LoadingState label={t('engagement.form.loading')} />;
  if (editing && detail.isError) {
    return (
      <ErrorState
        message={extractApiError(detail.error, t('engagement.form.error.load'))}
        onRetry={() => detail.refetch()}
      />
    );
  }

  const onSubmit = async (e: FormEvent) => {
    e.preventDefault();
    setSubmitError(null);
    const v = validate(form);
    setErrors(v);
    if (Object.keys(v).length > 0) return;

    const payload: EngagementInput = {
      name: form.name.trim(),
      start_date: form.start_date,
      status: form.status,
    };
    if (form.description.trim()) payload.description = form.description.trim();
    // PATCH with null clears end_date; POST with omitted leaves it null
    if (editing) {
      // Always include end_date for edit: '' → null to clear, otherwise value
      payload.end_date = form.end_date === '' ? null : form.end_date;
    } else if (form.end_date) {
      payload.end_date = form.end_date;
    }

    try {
      if (editing && numericId) {
        await patchMutation.mutateAsync(payload);
        push(t('engagement.form.toast.updated'), 'success');
        navigate(`/engagements/${numericId}`);
      } else {
        const created = await createMutation.mutateAsync(payload);
        push(t('engagement.form.toast.created'), 'success');
        navigate(`/engagements/${created.id}`);
      }
    } catch (err) {
      setSubmitError(extractApiError(err, t('engagement.form.error.save')));
    }
  };

  const submitting = createMutation.isPending || patchMutation.isPending;

  return (
    <div className="flex flex-col gap-xl">
      <header>
        <h1 className="text-[32px] font-medium leading-none">
          {editing ? t('engagement.form.title.edit') : t('engagement.form.title.new')}
        </h1>
        <p className="text-charcoal text-[16px] mt-sm">
          {editing ? t('engagement.form.subtitle.edit') : t('engagement.form.subtitle.new')}
        </p>
      </header>

      <div
        className={
          editing && canEditEngagements
            ? 'grid grid-cols-1 lg:grid-cols-2 gap-xl items-start'
            : 'max-w-2xl'
        }
      >
        <form onSubmit={onSubmit} noValidate className="card-product flex flex-col gap-md">
          <FormField label={t('engagement.form.field.name')} htmlFor="eng-name" required error={errors.name}>
            <TextInput
              id="eng-name"
              name="name"
              value={form.name}
              onChange={(e) => setForm({ ...form, name: e.target.value })}
              required
            />
          </FormField>

          <FormField label={t('engagement.form.field.description')} htmlFor="eng-description">
            <TextArea
              id="eng-description"
              name="description"
              value={form.description}
              onChange={(e) => setForm({ ...form, description: e.target.value })}
            />
          </FormField>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-md">
            <FormField
              label={t('engagement.form.field.startDate')}
              htmlFor="eng-start"
              required
              error={errors.start_date}
            >
              <TextInput
                id="eng-start"
                type="date"
                name="start_date"
                value={form.start_date}
                onChange={(e) => setForm({ ...form, start_date: e.target.value })}
                required
              />
            </FormField>

            <FormField
              label={t('engagement.form.field.endDate')}
              htmlFor="eng-end"
              hint={t('engagement.form.field.endDateHint')}
              error={errors.end_date}
            >
              <TextInput
                id="eng-end"
                type="date"
                name="end_date"
                value={form.end_date}
                onChange={(e) => setForm({ ...form, end_date: e.target.value })}
              />
            </FormField>
          </div>

          <FormField label={t('engagement.form.field.status')} htmlFor="eng-status" required>
            <Select
              id="eng-status"
              name="status"
              value={form.status}
              onChange={(e) => setForm({ ...form, status: e.target.value as EngagementStatus })}
              options={STATUS_OPTIONS}
            />
          </FormField>

          {submitError ? (
            <div role="alert" className="text-[14px] text-bloom-deep">
              {submitError}
            </div>
          ) : null}

          <div className="flex items-center gap-md pt-sm">
            <button type="submit" className="btn-primary" disabled={submitting} data-testid="btn-submit">
              {submitting
                ? t('engagement.form.btn.saving')
                : editing
                  ? t('engagement.form.btn.save')
                  : t('engagement.form.btn.create')}
            </button>
            <Link
              to={editing && numericId ? `/engagements/${numericId}` : '/engagements'}
              className="btn-outline-ink"
            >
              {t('engagement.form.btn.cancel')}
            </Link>
          </div>
        </form>

        {editing && numericId && canEditEngagements && (
          <C2ConfigCard engagementId={numericId} />
        )}
      </div>
    </div>
  );
}
