/**
 * use{{ model_name }}FormState Hook
 *
 * A typed form state hook for {{ model_name }} that provides:
 * - Type-safe form values
 * - Field-level validation
 * - Dirty/touched tracking
 * - Reset/submit helpers
 *
 * @example
 * ```tsx
 * const form = use{{ model_name }}FormState({
 *   initialValues: {{ camel_name }} ?? undefined,
 *   onSubmit: async (values) => {
 *     if ({{ camel_name }}) {
 *       await mutations.update({{ camel_name }}.id, values);
 *     } else {
 *       await mutations.create(values);
 *     }
 *   },
 * });
 *
 * return (
 *   <form onSubmit={form.handleSubmit}>
 *     <input
 *       name="name"
 *       value={form.values.name}
 *       onChange={(e) => form.setValue('name', e.target.value)}
 *       onBlur={() => form.setTouched('name')}
 *     />
 *     {form.touched.name && form.errors.name && (
 *       <span className="error">{form.errors.name}</span>
 *     )}
 *     <button type="submit" disabled={form.isSubmitting || !form.isValid}>
 *       {form.isSubmitting ? 'Saving...' : 'Save'}
 *     </button>
 *   </form>
 * );
 * ```
 *
 * ⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
 */

import { useState, useCallback, useMemo } from 'react';
import type {
  {{ model_name }},
  {{ model_name }}Create,
  {{ model_name }}Update,
} from '../types/generated';

// ============================================================================
// Types
// ============================================================================

/** Form values type (same as create input) */
export type {{ model_name }}FormValues = {{ model_name }}Create;

/** Form errors - partial record of field to error message */
export type {{ model_name }}FormErrors = Partial<Record<keyof {{ model_name }}FormValues, string>>;

/** Touched state - which fields have been touched */
export type {{ model_name }}FormTouched = Partial<Record<keyof {{ model_name }}FormValues, boolean>>;

/** Validation function type */
export type {{ model_name }}Validator = (
  values: Partial<{{ model_name }}FormValues>
) => {{ model_name }}FormErrors;

/** Form state hook options */
export interface Use{{ model_name }}FormStateOptions {
  /** Initial form values (for edit mode) */
  initialValues?: Partial<{{ model_name }}FormValues>;
  /** Custom validation function */
  validate?: {{ model_name }}Validator;
  /** Submit handler */
  onSubmit?: (values: {{ model_name }}FormValues) => Promise<void> | void;
  /** Whether to validate on change */
  validateOnChange?: boolean;
  /** Whether to validate on blur */
  validateOnBlur?: boolean;
}

/** Form state */
export interface {{ model_name }}FormState {
  /** Current form values */
  values: Partial<{{ model_name }}FormValues>;
  /** Validation errors */
  errors: {{ model_name }}FormErrors;
  /** Which fields have been touched */
  touched: {{ model_name }}FormTouched;
  /** Whether form is currently submitting */
  isSubmitting: boolean;
  /** Whether form has been modified from initial values */
  isDirty: boolean;
  /** Whether form has any validation errors */
  isValid: boolean;
  /** Whether form has been submitted at least once */
  isSubmitted: boolean;
}

/** Form actions */
export interface {{ model_name }}FormActions {
  /** Set a single field value */
  setValue: <K extends keyof {{ model_name }}FormValues>(
    field: K,
    value: {{ model_name }}FormValues[K]
  ) => void;
  /** Set multiple field values */
  setValues: (values: Partial<{{ model_name }}FormValues>) => void;
  /** Mark a field as touched */
  setTouched: (field: keyof {{ model_name }}FormValues) => void;
  /** Set a field error manually */
  setError: (field: keyof {{ model_name }}FormValues, message: string | undefined) => void;
  /** Validate the form and return errors */
  validate: () => {{ model_name }}FormErrors;
  /** Reset form to initial values */
  reset: (newInitialValues?: Partial<{{ model_name }}FormValues>) => void;
  /** Handle form submission */
  handleSubmit: (e?: React.FormEvent) => Promise<void>;
  /** Get props for an input field */
  getFieldProps: (field: keyof {{ model_name }}FormValues) => {
    name: string;
    value: unknown;
    onChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => void;
    onBlur: () => void;
  };
}

/** Combined form state and actions */
export type Use{{ model_name }}FormStateResult = {{ model_name }}FormState & {{ model_name }}FormActions;

// ============================================================================
// Default Validation
// ============================================================================

/**
 * Default validation based on field specs.
 * Override with custom validate function if needed.
 */
function defaultValidate(values: Partial<{{ model_name }}FormValues>): {{ model_name }}FormErrors {
  const errors: {{ model_name }}FormErrors = {};

{%- for field in form_fields %}
{%- if field.required %}
  // {{ field.name }} is required
  if (values.{{ field.camel_name }} === undefined || values.{{ field.camel_name }} === null{% if field.type == 'string' %} || values.{{ field.camel_name }} === ''{% endif %}) {
    errors.{{ field.camel_name }} = '{{ field.label }} is required';
  }
{%- endif %}
{%- if field.type == 'string' and field.max_length %}
  // {{ field.name }} max length
  if (typeof values.{{ field.camel_name }} === 'string' && values.{{ field.camel_name }}.length > {{ field.max_length }}) {
    errors.{{ field.camel_name }} = '{{ field.label }} must be {{ field.max_length }} characters or less';
  }
{%- endif %}
{%- if field.type == 'string' and field.min_length %}
  // {{ field.name }} min length
  if (typeof values.{{ field.camel_name }} === 'string' && values.{{ field.camel_name }}.length < {{ field.min_length }}) {
    errors.{{ field.camel_name }} = '{{ field.label }} must be at least {{ field.min_length }} characters';
  }
{%- endif %}
{%- if field.min is not none %}
  // {{ field.name }} minimum value
  if (typeof values.{{ field.camel_name }} === 'number' && values.{{ field.camel_name }} < {{ field.min }}) {
    errors.{{ field.camel_name }} = '{{ field.label }} must be at least {{ field.min }}';
  }
{%- endif %}
{%- if field.max is not none %}
  // {{ field.name }} maximum value
  if (typeof values.{{ field.camel_name }} === 'number' && values.{{ field.camel_name }} > {{ field.max }}) {
    errors.{{ field.camel_name }} = '{{ field.label }} must be at most {{ field.max }}';
  }
{%- endif %}
{% endfor %}

  return errors;
}

// ============================================================================
// Hook Implementation
// ============================================================================

/**
 * Hook for managing {{ model_name }} form state.
 *
 * @param options - Form state options
 * @returns Form state and actions
 */
export function use{{ model_name }}FormState(
  options: Use{{ model_name }}FormStateOptions = {}
): Use{{ model_name }}FormStateResult {
  const {
    initialValues = {},
    validate = defaultValidate,
    onSubmit,
    validateOnChange = false,
    validateOnBlur = true,
  } = options;

  // State
  const [values, setValuesState] = useState<Partial<{{ model_name }}FormValues>>(initialValues);
  const [errors, setErrors] = useState<{{ model_name }}FormErrors>({});
  const [touched, setTouchedState] = useState<{{ model_name }}FormTouched>({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [isSubmitted, setIsSubmitted] = useState(false);
  const [initialValuesState, setInitialValuesState] = useState<Partial<{{ model_name }}FormValues>>(initialValues);

  // Computed state
  const isDirty = useMemo(() => {
    return JSON.stringify(values) !== JSON.stringify(initialValuesState);
  }, [values, initialValuesState]);

  const isValid = useMemo(() => {
    const validationErrors = validate(values);
    return Object.keys(validationErrors).length === 0;
  }, [values, validate]);

  // Actions
  const setValue = useCallback(
    <K extends keyof {{ model_name }}FormValues>(field: K, value: {{ model_name }}FormValues[K]) => {
      setValuesState((prev) => ({ ...prev, [field]: value }));
      if (validateOnChange) {
        const newValues = { ...values, [field]: value };
        const newErrors = validate(newValues);
        setErrors(newErrors);
      }
    },
    [values, validate, validateOnChange]
  );

  const setValues = useCallback(
    (newValues: Partial<{{ model_name }}FormValues>) => {
      setValuesState((prev) => ({ ...prev, ...newValues }));
      if (validateOnChange) {
        const merged = { ...values, ...newValues };
        const newErrors = validate(merged);
        setErrors(newErrors);
      }
    },
    [values, validate, validateOnChange]
  );

  const setTouched = useCallback(
    (field: keyof {{ model_name }}FormValues) => {
      setTouchedState((prev) => ({ ...prev, [field]: true }));
      if (validateOnBlur) {
        const newErrors = validate(values);
        setErrors(newErrors);
      }
    },
    [values, validate, validateOnBlur]
  );

  const setError = useCallback(
    (field: keyof {{ model_name }}FormValues, message: string | undefined) => {
      setErrors((prev) => {
        if (message === undefined) {
          const { [field]: _, ...rest } = prev;
          return rest;
        }
        return { ...prev, [field]: message };
      });
    },
    []
  );

  const validateForm = useCallback((): {{ model_name }}FormErrors => {
    const newErrors = validate(values);
    setErrors(newErrors);
    return newErrors;
  }, [values, validate]);

  const reset = useCallback(
    (newInitialValues?: Partial<{{ model_name }}FormValues>) => {
      const resetValues = newInitialValues ?? initialValuesState;
      setValuesState(resetValues);
      setErrors({});
      setTouchedState({});
      setIsSubmitting(false);
      setIsSubmitted(false);
      if (newInitialValues) {
        setInitialValuesState(newInitialValues);
      }
    },
    [initialValuesState]
  );

  const handleSubmit = useCallback(
    async (e?: React.FormEvent) => {
      e?.preventDefault();
      setIsSubmitted(true);

      // Mark all fields as touched
      const allTouched: {{ model_name }}FormTouched = {};
      for (const key of Object.keys(values) as (keyof {{ model_name }}FormValues)[]) {
        allTouched[key] = true;
      }
      setTouchedState(allTouched);

      // Validate
      const validationErrors = validate(values);
      setErrors(validationErrors);

      if (Object.keys(validationErrors).length > 0) {
        return;
      }

      if (onSubmit) {
        setIsSubmitting(true);
        try {
          await onSubmit(values as {{ model_name }}FormValues);
        } finally {
          setIsSubmitting(false);
        }
      }
    },
    [values, validate, onSubmit]
  );

  const getFieldProps = useCallback(
    (field: keyof {{ model_name }}FormValues) => ({
      name: String(field),
      value: values[field] ?? '',
      onChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
        const target = e.target;
        let newValue: unknown;

        if (target.type === 'checkbox') {
          newValue = (target as HTMLInputElement).checked;
        } else if (target.type === 'number') {
          newValue = target.value === '' ? undefined : Number(target.value);
        } else {
          newValue = target.value;
        }

        setValue(field, newValue as {{ model_name }}FormValues[typeof field]);
      },
      onBlur: () => setTouched(field),
    }),
    [values, setValue, setTouched]
  );

  // Build state object
  const state: {{ model_name }}FormState = {
    values,
    errors,
    touched,
    isSubmitting,
    isDirty,
    isValid,
    isSubmitted,
  };

  // Build actions object
  const actions: {{ model_name }}FormActions = {
    setValue,
    setValues,
    setTouched,
    setError,
    validate: validateForm,
    reset,
    handleSubmit,
    getFieldProps,
  };

  return {
    ...state,
    ...actions,
  };
}

export default use{{ model_name }}FormState;
