// Shared trip form used by both the Add Trip and Edit Trip pages.
//
// In the Angular application, AddTripComponent and EditTripComponent
// each built an identical nine-field ReactiveForms FormGroup and an
// identical ~120-line template — roughly 240 duplicated lines. This
// component consolidates that duplication into a single controlled
// form driven by useState, with the same required-field validation
// the Validators.required rules enforced. The page components only
// supply initial values and an onSubmit handler.
import { FormEvent, useEffect, useState } from 'react';
import { TripFormData } from '../models/trip';

interface TripFormProps {
  title: string;
  initialValues?: TripFormData;
  onSubmit: (formData: TripFormData) => Promise<void>;
}

const EMPTY_FORM: TripFormData = {
  code: '',
  name: '',
  length: '',
  start: '',
  resort: '',
  perPerson: '',
  image: '',
  description: ''
};

// Field metadata drives both rendering and validation, so adding a
// field to the schema is a one-line change here instead of a
// copy/paste block in two templates.
const FIELDS: Array<{
  key: keyof Omit<TripFormData, '_id'>;
  label: string;
  type: 'text' | 'date';
  requiredMessage: string;
}> = [
  { key: 'code', label: 'Code:', type: 'text', requiredMessage: 'Trip Code is required' },
  { key: 'name', label: 'Name:', type: 'text', requiredMessage: 'Name is required' },
  { key: 'length', label: 'Length:', type: 'text', requiredMessage: 'Length is required' },
  { key: 'start', label: 'Start:', type: 'date', requiredMessage: 'Date is required' },
  { key: 'resort', label: 'Resort:', type: 'text', requiredMessage: 'Resort is required' },
  { key: 'perPerson', label: 'Per Person:', type: 'text', requiredMessage: 'Per Person is required' },
  { key: 'image', label: 'Image Name:', type: 'text', requiredMessage: 'Image Name is required' },
  { key: 'description', label: 'Description:', type: 'text', requiredMessage: 'Description is required' }
];

export function validateTripForm(values: TripFormData): string[] {
  return FIELDS.filter((field) => !values[field.key].trim()).map(
    (field) => field.key
  );
}

export default function TripForm({
  title,
  initialValues,
  onSubmit
}: TripFormProps) {
  const [values, setValues] = useState<TripFormData>(
    initialValues ?? EMPTY_FORM
  );
  const [submitted, setSubmitted] = useState(false);
  const [submitError, setSubmitError] = useState('');

  // When the edit page finishes loading the trip, sync it into state.
  useEffect(() => {
    if (initialValues) {
      setValues(initialValues);
    }
  }, [initialValues]);

  const invalidFields = validateTripForm(values);

  const handleChange = (key: keyof Omit<TripFormData, '_id'>, value: string) => {
    setValues((previous) => ({ ...previous, [key]: value }));
  };

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault();
    setSubmitted(true);
    setSubmitError('');
    if (invalidFields.length > 0) {
      return;
    }
    try {
      await onSubmit(values);
    } catch {
      setSubmitError('The trip could not be saved. Please try again.');
    }
  };

  return (
    <div className="col-md-4">
      <h2 className="text-center">{title}</h2>
      {submitError && (
        <div role="alert" className="alert alert-danger">
          {submitError}
        </div>
      )}
      <form onSubmit={handleSubmit} noValidate>
        {FIELDS.map((field) => {
          const isInvalid = submitted && !values[field.key].trim();
          return (
            <div className="form-group" key={field.key}>
              <label htmlFor={field.key}>{field.label}</label>
              <input
                id={field.key}
                type={field.type}
                placeholder={field.label.replace(':', '')}
                className={`form-control${isInvalid ? ' is-invalid' : ''}`}
                value={values[field.key]}
                onChange={(event) => handleChange(field.key, event.target.value)}
              />
              {isInvalid && <div>{field.requiredMessage}</div>}
            </div>
          );
        })}
        <button type="submit" className="btn btn-info mt-3">
          Save
        </button>
      </form>
    </div>
  );
}
