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

const STATUS_OPTIONS: { value: EngagementStatus; label: string }[] = [
  { value: 'planned', label: 'Planned' },
  { value: 'active', label: 'Active' },
  { value: 'closed', label: 'Closed' },
];

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',
};

function validate(state: FormState): Partial<Record<keyof FormState, string>> {
  const errors: Partial<Record<keyof FormState, string>> = {};
  if (!state.name.trim()) errors.name = 'Name is required';
  if (!state.start_date) errors.start_date = 'Start date is required';
  if (state.end_date && state.start_date && state.end_date < state.start_date) {
    errors.end_date = 'End date must be on or after start date';
  }
  return errors;
}

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

  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);

  // 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="Loading engagement…" />;
  if (editing && detail.isError) {
    return (
      <ErrorState
        message={extractApiError(detail.error, 'Could not load engagement')}
        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('Engagement updated', 'success');
        navigate(`/engagements/${numericId}`);
      } else {
        const created = await createMutation.mutateAsync(payload);
        push('Engagement created', 'success');
        navigate(`/engagements/${created.id}`);
      }
    } catch (err) {
      setSubmitError(extractApiError(err, 'Could not save engagement'));
    }
  };

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

  return (
    <div className="flex flex-col gap-xl max-w-2xl">
      <header>
        <h1 className="text-[44px] font-medium leading-none">
          {editing ? 'Edit engagement' : 'New engagement'}
        </h1>
        <p className="text-charcoal text-[16px] mt-sm">
          {editing
            ? 'Update the engagement metadata.'
            : 'Create a new red team mission to host simulations.'}
        </p>
      </header>

      <form onSubmit={onSubmit} noValidate className="card-product flex flex-col gap-md">
        <FormField label="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="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="Start date"
            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="End date"
            htmlFor="eng-end"
            hint="Leave empty to clear / leave open-ended"
            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="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}>
            {submitting ? 'Saving…' : editing ? 'Save changes' : 'Create engagement'}
          </button>
          <Link
            to={editing && numericId ? `/engagements/${numericId}` : '/engagements'}
            className="btn-outline-ink"
          >
            Cancel
          </Link>
        </div>
      </form>
    </div>
  );
}
