"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslations } from "next-intl";

import { Button, Spinner, TextInput, Typography } from "@/components/ui";
import { ActionField } from "@/types";

import { DatePicker, TimePicker } from "..";

import styles from "./ActionFieldsForm.module.scss";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type FormValues = Record<string, any>;
type FormErrors = Record<string, string>;
type TouchedFields = Record<string, boolean>;

interface ActionFieldsFormProps {
  fields: ActionField[];
  onSubmit: (values: FormValues) => void;
  isLoading?: boolean;
  buttonText: string;
}

export default function ActionFieldsForm({
  fields,
  onSubmit,
  isLoading,
  buttonText,
}: ActionFieldsFormProps) {
  const t = useTranslations("ActionFieldsForm");
  const initialValues = useMemo(() => {
    return fields.reduce((acc, field) => {
      acc[field.key] = field.value ?? null;
      return acc;
    }, {} as FormValues);
  }, [fields]);

  const [formValues, setFormValues] = useState<FormValues>(initialValues);
  const [touched, setTouched] = useState<TouchedFields>({});
  const [errors, setErrors] = useState<FormErrors>({});

  const validate = useCallback(
    (fields: ActionField[], values: FormValues): FormErrors => {
      const errors: FormErrors = {};

      for (const field of fields) {
        const value = values[field.key];
        if (value === null || value === "" || value === undefined) {
          errors[field.key] = t("required_field");
        }
      }

      return errors;
    },
    [t]
  );

  useEffect(() => {
    const validationErrors = validate(fields, formValues);
    setErrors(validationErrors);
  }, [formValues, fields, validate]);

  const handleBlur = useCallback((key: string) => {
    setTouched(prev => ({ ...prev, [key]: true }));
  }, []);

  const handleChange = (key: string, value: unknown) => {
    setFormValues(prev => ({ ...prev, [key]: value }));
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const allTouched = fields.reduce((acc, field) => {
      acc[field.key] = true;
      return acc;
    }, {} as TouchedFields);
    setTouched(allTouched);

    const validationErrors = validate(fields, formValues);
    if (Object.keys(validationErrors).length === 0) {
      onSubmit(formValues);
    }
  };

  const isFormValid = Object.keys(errors).length === 0;

  const renderField = (field: ActionField) => {
    const key = field.key;
    const value = formValues[key];
    const error = touched[key] ? errors[key] : undefined;

    switch (field.inputType) {
      case "text":
        return (
          <TextInput
            value={value || ""}
            onChange={e => handleChange(key, e.target.value)}
            error={error}
            placeholder={field.title}
            onBlur={() => handleBlur(key)}
          />
        );
      case "date":
        return (
          <DatePicker
            value={value}
            onChange={newValue => handleChange(key, newValue)}
            error={error}
            label={field.title}
            onBlur={() => handleBlur(key)}
          />
        );
      case "time":
        return (
          <TimePicker
            value={value}
            onChange={newValue => handleChange(key, newValue)}
            error={error}
            label={field.title}
            // onBlur={() => handleBlur(key)}
          />
        );
      default:
        return (
          <TextInput
            value={value || ""}
            onChange={e => handleChange(key, e.target.value)}
            placeholder={field.title}
            error={`Unsupported field type: ${field.inputType}`}
            onBlur={() => handleBlur(key)}
          />
        );
    }
  };

  return (
    <form onSubmit={handleSubmit} className={styles.form} noValidate>
      {fields.map(field => (
        <div key={field.key} className={styles.fieldWrapper}>
          {renderField(field)}
        </div>
      ))}
      <div className={styles.buttonWrapper}>
        <Button
          className={styles.button}
          type="submit"
          disabled={!isFormValid || isLoading}
        >
          {!isLoading && (
            <Typography size="xl" color="white">
              {buttonText}
            </Typography>
          )}
          {isLoading && <Spinner />}
        </Button>
      </div>
    </form>
  );
}
