// Components/FormFieldRenderer.jsx
// Generic component to render form fields from config
import React, { useState, useEffect } from "react";
import { InputText } from "primereact/inputtext";
import { Dropdown } from "primereact/dropdown";
import { InputTextarea } from "primereact/inputtextarea";
import { Calendar } from "primereact/calendar";
import { InputNumber } from "primereact/inputnumber";
import { Checkbox } from "primereact/checkbox";
import { classNames } from "primereact/utils";
import { getVisibleFields, getFormConfig } from "@/configs/formConfigs";
import FormDropdown from "@/Components/FormDropdown";
import DocumentUpload from "@/Components/DocumentUpload";
import PendingDocumentUpload from "@/Components/PendingDocumentUpload";
import { Controller } from "react-hook-form";

const getByPath = (obj, path) => {
  if (!obj || !path) return undefined;
  return path.split(".").reduce((acc, key) => (acc ? acc[key] : undefined), obj);
};

const FormFieldRenderer = ({
  config,
  formName,
  formData,
  setFormData,
  errors = {},
  context = {},
  className = "h-11 w-full block",
  firstFieldClassName = "field",
}) => {
  // If formName is provided, get config from formConfigs, otherwise use provided config
  const fieldsConfig = formName
    ? getFormConfig(formName)
    : Array.isArray(config)
      ? config
      : [];

  // Filter visible fields
  const visibleFields = fieldsConfig.filter((field) => {
    const isVisible =
      typeof field.visible === "function"
        ? field.visible(context)
        : field.visible !== false;

    if (!isVisible) return false;

    const passesCondition =
      typeof field.conditionCheck === "function"
        ? field.conditionCheck(context)
        : true;

    return passesCondition;
  });

  return (
    <>
      {visibleFields.map((field, index) => {
        // Check visibility
        const isVisible =
          typeof field.visible === "function"
            ? field.visible(context)
            : field.visible !== false;

        if (!isVisible) return null;

        // Check additional conditions
        const passesCondition =
          typeof field.conditionCheck === "function"
            ? field.conditionCheck(context)
            : true;

        if (!passesCondition) return null;

        const label =
          typeof field.label === "function"
            ? field.label(context)
            : (field.label ?? "");

        const fieldClassName =
          index === 0 ? firstFieldClassName : className;
        const fieldValue = getByPath(formData, field.name);
        const fieldError = getByPath(errors, field.name);
        const isInvalid = fieldError ? "p-invalid" : "";

        // Set default className based on field type if not provided
        const getDefaultClassName = (fieldType) => {
          switch (fieldType) {
            case "text":
              return "w-full h-11";
            case "dropdown":
              return "w-full h-11";
            case "textarea":
              return "w-full";
            case "number":
              return "w-full h-11";
            case "file":
              return "real-file-input";
            default:
              return "";
          }
        };

        const fieldClassNameValue = field.className || getDefaultClassName(field.type);

        // Handle grid layout - default to col-span-12 md:col-span-6, or use colSpan from config
        const colSpan = field.colSpan || "col-span-12 md:col-span-6";
        const gridClass = colSpan;
        const wrapperClass = `${fieldClassName} ${gridClass}`.trim();

        return (
          <div key={field.name} className={wrapperClass}>
            {/* Document Upload (LC Module step-wise: same design as Requisition) */}
            {field.type === "document_upload" && (
              <div className="p-4 border rounded-lg bg-gray-50">
                {context.documentableId && context.modelStatus === "edit" ? (
                  <DocumentUpload
                    documentableType={context.documentableType}
                    documentableId={context.documentableId}
                    documentType={field.documentTitle}
                    showLabel={true}
                    label={label || "Documents"}
                    remark={field.remark}
                    className="w-full"
                  />
                ) : context.setPendingDocumentsByStep && context.toast?.current != null ? (
                  <PendingDocumentUpload
                    pendingDocuments={context.pendingDocumentsByStep?.[context.stepIndex] ?? []}
                    setPendingDocuments={(updater) => {
                      const current = context.pendingDocumentsByStep?.[context.stepIndex] ?? [];
                      const next = typeof updater === "function" ? updater(current) : updater;
                      context.setPendingDocumentsByStep(context.stepIndex, next);
                    }}
                    toast={context.toast}
                    label={label || "Documents"}
                    remark={field.remark}
                    documentType={field.documentTitle}
                  />
                ) : null}
              </div>
            )}

            {/* Text Input */}
            {field.type === "text" && (
              <>
                {context.control ? (
                  // Use Controller when react-hook-form is used for proper validation
                  <div className="p-float-label">
                    <Controller
                      name={field.name}
                      control={context.control}
                      rules={{
                        ...(field.required && { required: `${label} is required` }),
                        ...(field.validationRules || {}),
                      }}
                      render={({ field: controllerField, fieldState }) => (
                        <InputText
                          id={controllerField.name}
                          name={controllerField.name}
                          value={controllerField.value || ""}
                          onChange={(e) => {
                            const value = e.target.value;
                            controllerField.onChange(value);
                            if (field.onChange) {
                              field.onChange(e, setFormData, context);
                            }
                          }}
                          className={classNames(fieldClassNameValue, fieldState.invalid ? "p-invalid" : "")}
                          placeholder={field.placeholder}
                          aria-describedby={`${field.name}-help`}
                        />
                      )}
                    />
                    <label htmlFor={field.name}>
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                  </div>
                ) : (
                  // Regular label when no react-hook-form
                  <>
                    <label htmlFor={field.name} className="block">
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                    <InputText
                      id={field.name}
                      name={field.name}
                      value={fieldValue || ""}
                      onChange={(e) => {
                        if (field.onChange) {
                          field.onChange(e, setFormData, context);
                        } else {
                          setFormData((prev) => ({
                            ...prev,
                            [field.name]: e.target.value,
                          }));
                        }
                      }}
                      className={classNames(fieldClassNameValue, isInvalid)}
                      placeholder={field.placeholder}
                      aria-describedby={`${field.name}-help`}
                    />
                  </>
                )}
              </>
            )}

            {/* Number Input */}
            {field.type === "number" && (
              <>
                {context.control ? (
                  // Use Controller when react-hook-form is used
                  <div className="w-full p-float-label">
                    <Controller
                      name={field.name}
                      control={context.control}
                      rules={{
                        ...(field.required && { required: `${label} is required` }),
                      }}
                      render={({ field: controllerField, fieldState }) => (
                        <InputNumber
                          id={controllerField.name}
                          value={controllerField.value ?? null}
                          onValueChange={(e) => controllerField.onChange(e.value)}
                          mode={field.mode}
                          minFractionDigits={field.minFractionDigits}
                          maxFractionDigits={field.maxFractionDigits}
                          className={classNames("w-full", field.wrapperClassName)}
                          inputClassName={classNames(fieldClassNameValue, fieldState.invalid ? "p-invalid" : "")}
                          placeholder={field.placeholder}
                          aria-describedby={`${field.name}-help`}
                        />
                      )}
                    />
                    <label htmlFor={field.name}>
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                  </div>
                ) : (
                  // Use regular InputNumber when no control (simple state management)
                  <div className="w-full">
                    <label htmlFor={field.name} className="block">
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                    <InputNumber
                      id={field.name}
                      name={field.name}
                      value={fieldValue ?? null}
                      onValueChange={(e) => {
                        if (field.onChange) {
                          field.onChange(e, setFormData, context);
                        } else {
                          setFormData((prev) => ({
                            ...prev,
                            [field.name]: e.value,
                          }));
                        }
                      }}
                      mode={field.mode}
                      minFractionDigits={field.minFractionDigits}
                      maxFractionDigits={field.maxFractionDigits}
                      className={classNames("w-full", field.wrapperClassName)}
                      inputClassName={classNames(fieldClassNameValue, isInvalid)}
                      placeholder={field.placeholder}
                      aria-describedby={`${field.name}-help`}
                    />
                  </div>
                )}
              </>
            )}

            {/* Textarea */}
            {field.type === "textarea" && (
              <>
                {context.control ? (
                  // Use Controller when react-hook-form is used for proper validation
                  <div className="p-float-label">
                    <Controller
                      name={field.name}
                      control={context.control}
                      rules={{
                        ...(field.required && { required: `${label} is required` }),
                        ...(field.validationRules || {}),
                      }}
                      render={({ field: controllerField, fieldState }) => (
                        <InputTextarea
                          id={controllerField.name}
                          name={controllerField.name}
                          value={controllerField.value || ""}
                          onChange={(e) => {
                            const value = e.target.value;
                            controllerField.onChange(value);
                            if (field.onChange) {
                              field.onChange(e, setFormData, context);
                            }
                          }}
                          className={classNames(fieldClassNameValue, fieldState.invalid ? "p-invalid" : "")}
                          placeholder={field.placeholder}
                          rows={field.rows || 3}
                          aria-describedby={`${field.name}-help`}
                        />
                      )}
                    />
                    <label htmlFor={field.name}>
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                  </div>
                ) : (
                  // Regular label when no react-hook-form
                  <>
                    <label htmlFor={field.name} className="block">
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                    <InputTextarea
                      id={field.name}
                      name={field.name}
                      value={fieldValue || ""}
                      onChange={(e) => {
                        if (field.onChange) {
                          field.onChange(e, setFormData, context);
                        } else {
                          setFormData((prev) => ({
                            ...prev,
                            [field.name]: e.target.value,
                          }));
                        }
                      }}
                      className={classNames(fieldClassNameValue, isInvalid)}
                      placeholder={field.placeholder}
                      rows={field.rows || 3}
                      aria-describedby={`${field.name}-help`}
                    />
                  </>
                )}
              </>
            )}

            {/* Dropdown */}
            {field.type === "dropdown" && (
              <>
                {context.control && field.mode == "prentWiseDropdown" ? (
                  // Use FormDropdown when control is provided (react-hook-form)
                  <FormDropdown
                    name={field.name}
                    control={context.control}
                    options={
                      typeof field.getOptions === "function"
                        ? field.getOptions(context)
                        : field.options || []
                    }
                    label={label}
                    placeholder={field.placeholder || "Select"}
                    required={field.required || false}
                    filter={field.filter || false}
                    filterBy={field.filterBy}
                    optionLabel={field.optionLabel || "name"}
                    optionValue={field.optionValue || "id"}
                    showClear={field.showClear || false}
                    optionDisabled={field.optionDisabled}
                    className={fieldClassNameValue}
                    errors={errors}
                  />
                ) : context.control ? (
                  // Use Controller when react-hook-form is used for proper validation
                  <div className="w-full p-float-label">
                    <Controller
                      name={field.name}
                      control={context.control}
                      rules={{
                        ...(field.required && { required: `${label} is required` }),
                        ...(field.validationRules || {}),
                      }}
                      render={({ field: controllerField, fieldState }) => (
                        <Dropdown
                          id={controllerField.name}
                          name={controllerField.name}
                          value={
                            typeof field.getValue === "function"
                              ? field.getValue(formData, context)
                              : controllerField.value
                          }
                          options={
                            typeof field.getOptions === "function"
                              ? field.getOptions(context)
                              : field.options || []
                          }
                          onChange={(e) => {
                            const value = e.value;
                            controllerField.onChange(value);
                            if (field.onChange) {
                              field.onChange(e, setFormData, context);
                            } else if (typeof field.getValue !== "function") {
                              setFormData((prev) => ({
                                ...prev,
                                [field.name]: value,
                              }));
                            }
                          }}
                          optionLabel={field.optionLabel || "name"}
                          optionValue={field.optionValue || "id"}
                          filter={field.filter || false}
                          showClear={field.showClear || false}
                          filterBy={field.filterBy}
                          placeholder={field.placeholder || "Select"}
                          className={classNames(fieldClassNameValue, fieldState.invalid ? "p-invalid" : "")}
                          style={{ width: "100%" }}
                          optionDisabled={field.optionDisabled}
                          aria-describedby={`${field.name}-help`}
                        />
                      )}
                    />
                    <label htmlFor={field.name}>
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                  </div>
                ) : (
                  <div className="w-full p-float-label">

                    <Dropdown
                      id={field.name}
                      name={field.name}
                      value={
                        typeof field.getValue === "function"
                          ? field.getValue(formData, context)
                          : fieldValue
                      }
                      options={
                        typeof field.getOptions === "function"
                          ? field.getOptions(context)
                          : field.options || []
                      }
                      onChange={(e) => {
                        if (field.onChange) {
                          field.onChange(e, setFormData, context);
                        } else {
                          const value = e.value;
                          setFormData((prev) => ({
                            ...prev,
                            [field.name]: value,
                          }));
                        }
                      }}
                      optionLabel={field.optionLabel || "name"}
                      optionValue={field.optionValue || "id"}
                      filter={field.filter || false}
                      showClear={field.showClear || false}
                      filterBy={field.filterBy}
                      placeholder={field.placeholder || "Select"}
                      className={classNames(fieldClassNameValue, isInvalid)}
                      style={{ width: "100%" }}
                      optionDisabled={field.optionDisabled}
                      aria-describedby={`${field.name}-help`}
                    />
                    <label htmlFor={field.name}>
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                  </div>
                )}
              </>
            )}

            {/* Date/Calendar */}
            {field.type === "date" && (
              <>
                {context.control ? (
                  <div className="w-full p-float-label">
                    <Controller
                      name={field.name}
                      control={context.control}
                      rules={{
                        ...(field.required && {
                          required: `${label} is required`,
                        }),
                        ...(field.validationRules || {}),
                      }}
                      render={({ field: controllerField, fieldState }) => (
                        <Calendar
                          id={controllerField.name}
                          name={controllerField.name}
                          value={
                            controllerField.value
                              ? new Date(controllerField.value)
                              : null
                          }
                          onChange={(e) => {
                            // Store as YYYY-MM-DD string by default (matches existing usage)
                            const v = e.value
                              ? e.value.toISOString().slice(0, 10)
                              : "";
                            controllerField.onChange(v);
                            if (field.onChange) {
                              field.onChange(e, setFormData, context);
                            }
                          }}
                          dateFormat={field.dateFormat || "yy-mm-dd"}
                          showIcon
                          className={classNames(
                            fieldClassNameValue,
                            fieldState.invalid ? "p-invalid" : ""
                          )}
                          aria-describedby={`${field.name}-help`}
                        />
                      )}
                    />
                    <label htmlFor={field.name}>
                      {label}
                      {field.required && (
                        <span className="text-red-500">*</span>
                      )}
                    </label>
                  </div>
                ) : (
                  <Calendar
                    id={field.name}
                    name={field.name}
                    value={fieldValue ? new Date(fieldValue) : null}
                    onChange={(e) => {
                      if (field.onChange) {
                        field.onChange(e, setFormData, context);
                      } else {
                        setFormData((prev) => ({
                          ...prev,
                          [field.name]: e.value,
                        }));
                      }
                    }}
                    dateFormat={field.dateFormat || "dd/mm/yy"}
                    className={classNames(fieldClassNameValue, isInvalid)}
                    aria-describedby={`${field.name}-help`}
                  />
                )}
              </>
            )}

            {/* Checkbox */}
            {field.type === "checkbox" && (
              <div className="flex align-items-center">
                <Checkbox
                  inputId={field.name}
                  checked={fieldValue || false}
                  onChange={(e) => {
                    if (field.onChange) {
                      field.onChange(e, setFormData, context);
                    } else {
                      setFormData((prev) => ({
                        ...prev,
                        [field.name]: e.checked,
                      }));
                    }
                  }}
                  className={isInvalid}
                />
                {label && (
                  <label htmlFor={field.name} className="ml-2">
                    {label}
                  </label>
                )}
              </div>
            )}

            {/* File Input */}
            {field.type === "file" && (
              <FileInputWithPreview
                field={field}
                fieldValue={fieldValue}
                formData={formData}
                setFormData={setFormData}
                context={context}
                isInvalid={isInvalid}
                fieldError={fieldError}
                register={context.register}
                errors={errors}
                fieldClassNameValue={fieldClassNameValue}
              />
            )}

            {/* Error Message */}
            {/* Skip error display for FormDropdown fields as they handle their own errors */}
            {fieldError && !(field.type === "dropdown" && field.mode === "prentWiseDropdown" && context.control) && (
              <small
                id={`${field.name}-help`}
                className="p-error block"
              >
                {typeof fieldError === "string"
                  ? fieldError
                  : fieldError.message || fieldError[0]}
              </small>
            )}
          </div>
        );
      })}
    </>
  );
};

// File Input Component with Image Preview
const FileInputWithPreview = ({
  field,
  fieldValue,
  formData,
  setFormData,
  context,
  isInvalid,
  fieldError,
  register,
  errors,
  fieldClassNameValue,
}) => {
  const [preview, setPreview] = useState(null);
  const [previewUrl, setPreviewUrl] = useState(null);

  // Check if accept includes image types
  const isImageField = field.accept?.includes("image") || field.name === "image";

  // Handle existing image from formData (for edit mode)
  useEffect(() => {
    let objectUrl = null;

    if (fieldValue && typeof fieldValue === "string" && isImageField) {
      // If it's a string, it might be an existing image path
      const location = window.location.origin;
      setPreviewUrl(`${location}/upload/${fieldValue}`);
    } else if (fieldValue instanceof File && isImageField) {
      // If it's a File object, create preview URL
      objectUrl = URL.createObjectURL(fieldValue);
      setPreviewUrl(objectUrl);
    } else if (!fieldValue) {
      setPreviewUrl(null);
    }

    // Cleanup function to revoke the object URL when component unmounts or fieldValue changes
    return () => {
      if (objectUrl) {
        URL.revokeObjectURL(objectUrl);
      }
    };
  }, [fieldValue, isImageField]);

  // Cleanup preview URL on unmount
  useEffect(() => {
    return () => {
      if (previewUrl && previewUrl.startsWith("blob:")) {
        URL.revokeObjectURL(previewUrl);
      }
    };
  }, [previewUrl]);

  const handleFileChange = (event) => {
    const file = event.target.files?.[0];

    if (file && isImageField) {
      // Create preview for image files
      const url = URL.createObjectURL(file);
      setPreviewUrl(url);
      setPreview(file);

      // Store file in react-hook-form state immediately
      if (context.setValue) {
        context.setValue(field.name, file, { shouldValidate: true });
      }
    } else {
      setPreviewUrl(null);
      setPreview(null);
      if (!file && context.setValue) {
        context.setValue(field.name, null, { shouldValidate: false });
      }
    }

    if (field.onChange) {
      field.onChange(event, setFormData, context);
    } else {
      setFormData((prev) => ({
        ...prev,
        [field.name]: file,
      }));
    }
  };

  const handleRemoveImage = () => {
    if (previewUrl && previewUrl.startsWith("blob:")) {
      URL.revokeObjectURL(previewUrl);
    }
    setPreviewUrl(null);
    setPreview(null);
    setFormData((prev) => ({
      ...prev,
      [field.name]: "",
    }));
    // Reset file input
    const fileInput = document.getElementById(field.name);
    if (fileInput) {
      fileInput.value = "";
    }
    // Also clear from react-hook-form
    if (context.setValue) {
      context.setValue(field.name, null, { shouldValidate: false });
    }
  };

  // Use Controller instead of register to properly store File object (not FileList)
  const fileInputElement = context.control ? (
    <Controller
      name={field.name}
      control={context.control}
      rules={{
        validate: context.validateImage || undefined,
      }}
      render={({ field: controllerField, fieldState }) => (
        <input
          type="file"
          id={field.name}
          name={field.name}
          className={classNames(fieldClassNameValue, fieldState.invalid ? "p-invalid" : isInvalid)}
          accept={field.accept}
          onChange={(e) => {
            const file = e.target.files?.[0];
            // Store File object (not FileList) in react-hook-form
            controllerField.onChange(file || null);
            // Call handleFileChange for preview
            handleFileChange(e);
          }}
        />
      )}
    />
  ) : register ? (
    <input
      type="file"
      id={field.name}
      name={field.name}
      className={classNames(fieldClassNameValue, isInvalid)}
      accept={field.accept}
      onChange={(e) => {
        const file = e.target.files?.[0];
        handleFileChange(e);
        // Override register's default FileList storage with File object
        if (file && context.setValue) {
          setTimeout(() => {
            context.setValue(field.name, file, { shouldValidate: true });
          }, 0);
        }
      }}
      {...register(field.name, {
        validate: context.validateImage || undefined,
      })}
    />
  ) : (
    <input
      type="file"
      id={field.name}
      name={field.name}
      className={classNames(fieldClassNameValue, isInvalid)}
      accept={field.accept}
      onChange={handleFileChange}
    />
  );

  return (
    <>
      <div className="flex items-start gap-4">
        {/* File Input */}
        <div className="file-input-container flex-shrink-0">
          {fileInputElement}
          {field.customLabel && (
            <label htmlFor={field.name} className="custom-file-label">
              <span>
                <i className="bx bx-plus"></i>{" "}
                {field.labelText || "Choose a file"}
              </span>
            </label>
          )}
        </div>

        {/* Image Preview */}
        {isImageField && previewUrl && (
          <div className="relative flex-shrink-0">
            <div
              className="rounded-lg border-2 border-gray-200 shadow-md overflow-hidden bg-gray-50"
              style={{
                width: `${field.previewSize || 100}px`,
                height: `${field.previewSize || 100}px`,
              }}
            >
              <img
                src={previewUrl}
                alt="Preview"
                className="w-full h-full object-cover"
                onError={(e) => {
                  e.target.src =
                    "https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png";
                }}
              />
            </div>
            <button
              type="button"
              onClick={handleRemoveImage}
              className="absolute -top-2 -right-2 bg-red-500 hover:bg-red-600 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs font-bold shadow-lg transition-all hover:scale-110"
              title="Remove image"
            >
              ×
            </button>
          </div>
        )}
      </div>
    </>
  );
};

export default FormFieldRenderer;
