// components/forms/DynamicFieldGroup.jsx
import { Controller } from "react-hook-form";
import { InputText } from "primereact/inputtext";
import { Button } from "primereact/button";
import { classNames } from "primereact/utils";
import fieldModes from "@/configs/fieldModes";
import { Dropdown } from "primereact/dropdown";
import { priceCalculation } from "@/Utils/helper";
import { Calendar } from "primereact/calendar";
import { useInputHotKey } from "@/Hooks/useInputHotKey";
import { useContext, useState } from "react";
import { authUser } from "@/Components/AuthProvider";

const DynamicFieldGroup = ({
  control,
  watch,
  setValue,
  remove,
  index,
  onDelete = false,
  getFormErrorMessageMultiple,
  mode,
  deleteColumn = 2,
  readOnlyFields = [],
  onAddNewItem = null, // Callback for plus button: (dropdownType) => void
  labelPrint = false, // Add status prop to determine create/update mode
  showAppendButton = false, // default hidden
  onAppendButton = null, // (index, rowData, allFormData, event) => void
  appendButtonLabel = "Add more attribute",
  showRowIndex = true, // when true, shows #1, #2, … from index (no prop from parent)
}) => {
  useInputHotKey();
  const { permission } = useContext(authUser);

  const [multiDateEditStr, setMultiDateEditStr] = useState({});

  const config = fieldModes[mode] || [];

  let totalColumn = config.reduce(
    (acc, field) => acc + (field.visible ? field.colSpan : 0),
    0
  );

  const columnsPerRow = 12;
  const lastLineColumns = totalColumn % columnsPerRow;

  let columnsNeeded =
    lastLineColumns > 0 ? columnsPerRow - lastLineColumns : 0;

  if (columnsNeeded === 0) columnsNeeded = 12;
  else if (columnsNeeded === 6) columnsNeeded = 10;
  else if (lastLineColumns === 8) columnsNeeded = 6;

  const rowBg =
    index % 2 === 0
      ? "bg-gradient-to-r from-gray-50 to-gray-100"
      : "bg-gradient-to-r from-blue-50 to-gray-100";

  const inputClass = (invalid) =>
    classNames({ "p-invalid": invalid }) +
    " w-full h-10 px-2 rounded-md border border-gray-300 text-sm bg-white shadow-sm " +
    "focus:ring-2 focus:ring-blue-300 focus:border-blue-500 transition";

  // --- Helpers for multi-date text input (Expire Date) ---
  const formatDisplayDate = (date) => {
    const d = date instanceof Date ? date : new Date(date);
    if (Number.isNaN(d.getTime())) return "";
    const dd = String(d.getDate()).padStart(2, "0");
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const yyyy = d.getFullYear();
    return `${dd}/${mm}/${yyyy}`;
  };

  const formatStoreDate = (date) => {
    const d = date instanceof Date ? date : new Date(date);
    if (Number.isNaN(d.getTime())) return null;
    const yyyy = d.getFullYear();
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const dd = String(d.getDate()).padStart(2, "0");
    return `${yyyy}-${mm}-${dd}`;
  };

  // Parse tokens like "01022026", "010226", or "01/02/2026"
  const parseTokenToDate = (token) => {
    const trimmed = token.trim();
    if (!trimmed) return null;

    const digits = trimmed.replace(/\D/g, "");
    let day;
    let month;
    let year;

    if (digits.length === 6) {
      // ddmmyy
      day = parseInt(digits.slice(0, 2), 10);
      month = parseInt(digits.slice(2, 4), 10);
      year = 2000 + parseInt(digits.slice(4, 6), 10);
    } else if (digits.length === 8) {
      // ddmmyyyy
      day = parseInt(digits.slice(0, 2), 10);
      month = parseInt(digits.slice(2, 4), 10);
      year = parseInt(digits.slice(4, 8), 10);
    } else {
      // Try dd/mm/yyyy or dd-mm-yyyy
      const m = trimmed.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{2}|\d{4})$/);
      if (!m) return null;
      day = parseInt(m[1], 10);
      month = parseInt(m[2], 10);
      year = parseInt(m[3], 10);
      if (m[3].length === 2) year = 2000 + year;
    }

    if (
      Number.isNaN(day) ||
      Number.isNaN(month) ||
      Number.isNaN(year) ||
      month < 1 ||
      month > 12
    ) {
      return null;
    }

    const d = new Date(year, month - 1, day);
    if (d.getFullYear() !== year || d.getMonth() !== month - 1 || d.getDate() !== day) {
      return null;
    }

    return {
      date: d,
      store: formatStoreDate(d),
      display: formatDisplayDate(d),
    };
  };

  return (
    <>
      {/* OUTER DESIGN WRAPPER */}
      <div
        className={`
                    col-span-12 p-3 rounded-xl border relative shadow-sm
                 
                    ${rowBg}
                    transition-all
                `}
      >
        {showRowIndex && (
          <div
            className="mb-1 pr-11 text-xs font-medium tabular-nums text-gray-500"
            aria-label={`Row ${index + 1}`}
          >
            #{index + 1}
          </div>
        )}
        {/* DELETE BUTTON TOP RIGHT */}
        <button
          onClick={(e) => {
            e.preventDefault();

            if (onDelete) {
              onDelete(
                e,
                remove,
                index,
                watch(`list.${index}`),
                watch()
              );
            } else {
              if (confirm("Are you sure?")) remove(index);
            }
          }}
          className="
                        absolute top-2 right-2
                        bg-red-500 hover:bg-red-600 text-white 
                        w-9 h-9 rounded-full shadow-md
                        flex items-center justify-center
                        text-xs transition-transform
                        hover:scale-105
                    "
        >
          <i className="pi pi-trash"></i>
        </button>

        {/* FIELDS */}
        <div
          className={`grid grid-cols-12 ${showRowIndex ? "pt-0" : "pt-3"}`}
        >
          {config.map((field) => {
            // Handle visible as function or boolean
            const isVisible = typeof field.visible === 'function'
              ? field.visible(permission)
              : field.visible;
            if (!isVisible) return null;

            // original conditionRendering logic preserved
            const hideField =
              field.conditionRendering &&
              field.conditionRendering(
                watch(`list.${index}.other`)
              );
            if (hideField) return null;

            return (
              <div
                key={field.name}
                className={`
                                    col-span-12 md:col-span-${field.colSpan}
                                    ${field.classNameParent}
                                    flex flex-col gap-1 p-1
                                `}
              >
                <Controller
                  name={`list.${index}.${field.name}`}
                  control={control}
                  rules={
                    typeof field.rulesCustom === "function"
                      ? field.rulesCustom(
                        watch(`list.${index}`),
                        permission
                      ) || field.rules
                      : field.rules
                  }
                  render={({ field: f, fieldState }) => (
                    <>
                      {/* LABEL */}
                      {field.type !== "button" && (
                        <div className="flex items-center mb-1">
                          <label className="text-xs font-semibold text-gray-700 flex items-center gap-1">
                            <span>
                              {typeof field.label === "function"
                                ? field.label(permission)
                                : field.label}
                            </span>

                            {field.fieldLabel && (
                              <span className="text-gray-500">
                                {field.fieldLabel(
                                  watch(`list.${index}.other`)
                                    ?.attribute ??
                                  watch(`list.${index}.other`)
                                )}
                              </span>
                            )}

                            {field?.rules?.required && (
                              <span className="text-red-500">*</span>
                            )}
                          </label>

                          {field.showAddButton && onAddNewItem && (
                            <Button
                              icon="pi pi-plus"
                              className="p-button-text p-button-rounded p-button-xs ml-2 !h-4 !w-4 !p-0 flex items-center justify-center text-[10px] text-slate-500 hover:text-slate-800"
                              onClick={(e) => {
                                e.preventDefault();
                                if (field.addButtonType) {
                                  onAddNewItem(field.addButtonType);
                                }
                              }}
                              tooltip={`Add new ${field.addButtonType || field.label.toLowerCase()}`}
                              tooltipOptions={{ position: "top" }}
                            />
                          )}
                        </div>
                      )}

                      {/* DROPDOWN */}
                      {field.type === "dropdown" && (
                        <div className={field.showAddButton ? "p-inputgroup" : ""}>
                          <Dropdown
                            id={f.name}
                            value={f.value}
                            onChange={(e) => {
                              // Update the field value first
                              f.onChange(e.value);

                              // If there's a custom onChange handler, call it
                              if (field.onChange) {
                                field.onChange(
                                  e,
                                  f,
                                  index,
                                  setValue,
                                  watch(`list.${index}`),
                                  watch,
                                  permission
                                );
                              }
                            }}
                            options={
                              field.options
                                ? field.options(
                                  watch(`list.${index}`),
                                  setValue,
                                  index
                                )
                                : []
                            }
                            optionLabel={field.optionLabel || "name"}
                            optionValue={field.optionValue || "id"}
                            placeholder="Select"
                            showClear
                            filter
                            className={inputClass(fieldState.invalid)}
                          />
                          {/* {field.showAddButton && onAddNewItem && (
                            <Button
                              icon="pi pi-plus"
                              className="p-button-success p-button-icon-only"
                              onClick={(e) => {
                                e.preventDefault();
                                if (field.addButtonType) {
                                  onAddNewItem(field.addButtonType);
                                }
                              }}
                              tooltip={`Add new ${field.addButtonType || field.label.toLowerCase()}`}
                              tooltipOptions={{ position: "top" }}
                              style={{
                                minWidth: "2.5rem",
                                height: "2.5rem",
                                width: "2.5rem",
                                padding: "0",
                                display: "flex",
                                alignItems: "center",
                                justifyContent: "center",
                                borderRadius: "0 0.375rem 0.375rem 0",
                                borderLeft: "1px solid rgba(255, 255, 255, 0.15)",
                                transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
                                fontSize: "0.875rem",
                                backgroundColor: "#22c55e",
                                border: "none",
                                boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.1)",
                              }}
                              onMouseEnter={(e) => {
                                e.currentTarget.style.transform = "scale(1.08)";
                                e.currentTarget.style.boxShadow = "0 4px 12px rgba(34, 197, 94, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
                                e.currentTarget.style.backgroundColor = "#16a34a";
                                e.currentTarget.style.borderLeft = "1px solid rgba(255, 255, 255, 0.25)";
                              }}
                              onMouseLeave={(e) => {
                                e.currentTarget.style.transform = "scale(1)";
                                e.currentTarget.style.boxShadow = "inset 0 1px 0 rgba(255, 255, 255, 0.1)";
                                e.currentTarget.style.backgroundColor = "#22c55e";
                                e.currentTarget.style.borderLeft = "1px solid rgba(255, 255, 255, 0.15)";
                              }}
                              onMouseDown={(e) => {
                                e.currentTarget.style.transform = "scale(0.95)";
                              }}
                              onMouseUp={(e) => {
                                e.currentTarget.style.transform = "scale(1.08)";
                              }}
                            />
                          )} */}
                        </div>
                      )}

                      {/* SINGLE DATE CALENDAR */}
                      {field.type === "date" && (
                        <Calendar
                          id={f.name}
                          value={f.value ? new Date(f.value) : null}
                          onChange={(e) => {
                            const dateValue = e.value;
                            f.onChange(dateValue);
                            if (field.onChange) {
                              field.onChange(
                                { value: dateValue },
                                f,
                                index,
                                setValue,
                                watch(`list.${index}`),
                                watch,
                                permission
                              );
                            }
                          }}
                          dateFormat="dd/mm/yy"
                          className={inputClass(fieldState.invalid)}
                        />
                      )}

                      {/* MULTIPLE DATES (Expire Date) — type 01022026␣ → 01/02/2026, supports multiple values */}
                      {field.type === "calendar-multiple" && (
                        <input
                          id={f.name}
                          type="text"
                          placeholder="e.g. 01022026 15032026 or 01/02/2026, 15/03/2026"
                          value={
                            multiDateEditStr[`${index}-${field.name}`] !== undefined
                              ? multiDateEditStr[`${index}-${field.name}`]
                              : Array.isArray(f.value) && f.value.length
                                ? f.value.map((d) => formatDisplayDate(d)).join(", ")
                                : ""
                          }
                          onChange={(e) => {
                            const key = `${index}-${field.name}`;
                            const raw = e.target.value;
                            // Always show what user types
                            setMultiDateEditStr((prev) => ({ ...prev, [key]: raw }));

                            const trimmed = raw.trimEnd();
                            if (!trimmed) {
                              // User cleared field
                              f.onChange([]);
                              setValue(f.name, [], { shouldValidate: true });
                              return;
                            }

                            const lastChar = raw.slice(-1);
                            // Commit a token only when user types space or comma
                            if (lastChar !== " " && lastChar !== ",") {
                              return;
                            }

                            // Find last token before the space/comma
                            const match = trimmed.match(/([^,\s]+)$/);
                            if (!match) return;
                            const token = match[1]; // e.g. "01022026" or "01/02/2026"

                            const parsed = parseTokenToDate(token);
                            if (!parsed) {
                              // Not a complete/valid date yet; keep letting the user type
                              return;
                            }

                            // Rebuild display: everything before token + formatted + ", "
                            const beforeToken = trimmed.slice(0, trimmed.length - token.length);
                            const newDisplay = `${beforeToken}${parsed.display}, `;

                            setMultiDateEditStr((prev) => ({ ...prev, [key]: newDisplay }));

                            // Append to current form value array (stored as "YYYY-MM-DD")
                            const current = Array.isArray(f.value) ? [...f.value] : [];
                            current.push(parsed.store);
                            f.onChange(current);
                            setValue(f.name, current, { shouldValidate: true });

                            if (field.onChange) {
                              field.onChange(
                                { value: current },
                                f,
                                index,
                                setValue,
                                watch(`list.${index}`),
                                watch,
                                permission
                              );
                            }
                          }}
                          onBlur={(e) => {
                            const key = `${index}-${field.name}`;
                            const str = (e.target.value || "").trim();

                            if (!str) {
                              f.onChange([]);
                              setValue(f.name, [], { shouldValidate: true });
                              setMultiDateEditStr((prev) => {
                                const next = { ...prev };
                                delete next[key];
                                return next;
                              });
                              return;
                            }

                            // Parse all tokens separated by comma/space
                            const parts = str.split(/[\s,]+/).filter(Boolean);
                            const values = [];
                            const displayParts = [];

                            parts.forEach((s) => {
                              const parsed = parseTokenToDate(s);
                              if (parsed) {
                                values.push(parsed.store);
                                displayParts.push(parsed.display);
                              }
                            });

                            f.onChange(values);
                            setValue(f.name, values, { shouldValidate: true });
                            setMultiDateEditStr((prev) => ({
                              ...prev,
                              [key]: displayParts.join(", "),
                            }));
                          }}
                          className={inputClass(fieldState.invalid)}
                        />
                      )}

                      {/* BUTTON FIELD */}
                      {field.type === "button" && labelPrint == true && (
                        <Button
                          icon="pi pi-print"
                          label="Label Print"
                          className="p-button-outlined h-10 text-sm"
                          onClick={(e) => {
                            e.preventDefault();
                            const rowData = watch(`list.${index}`);
                            const attributeId =
                              rowData?.other?.attribute?.id ??
                              rowData?.attribute_id ??
                              rowData?.attrId ??
                              rowData?.id;

                            if (!attributeId) {
                              return;
                            }

                            window.open(
                              `label/print/${attributeId}`,
                              "_blank",
                              "noopener,noreferrer"
                            );
                          }}
                        />
                      )}

                      {/* TEXT INPUT */}
                      {field.type !== "dropdown" &&
                        field.type !== "calendar-multiple" &&
                        field.type !== "date" &&
                        field.type !== "button" && (
                          <InputText
                            id={f.name}
                            type={field.type || "text"}
                            value={f.value}
                            step={field.type === "number" && field.name === "quantity" ? "any" : undefined}
                            readOnly={
                              typeof field.readOnly === "function"
                                ? field.readOnly(
                                  watch(`list.${index}`),
                                  watch,
                                  index
                                )
                                : field.readOnly ||
                                readOnlyFields.includes(
                                  field.name
                                )
                            }
                            onChange={(e) => {
                              // For number fields, allow decimal values
                              if (field.type === "number") {
                                const value = e.target.value;
                                // Allow empty, numbers, and decimals
                                if (value === "" || /^-?\d*\.?\d*$/.test(value)) {
                                  f.onChange(value);
                                }
                              } else {
                                f.onChange(e);
                              }

                              if (field.onChange) {
                                field.onChange(
                                  e,
                                  f,
                                  index,
                                  setValue,
                                  watch(
                                    `list.${index}`
                                  ),
                                  watch,
                                  permission
                                );
                              } else if (field.autoCalc === "total") {
                                const lineTotal = priceCalculation(
                                  index,
                                  watch
                                );
                                setValue(
                                  `list.${index}.total`,
                                  Math.round(lineTotal)
                                );
                              }
                            }}
                            onKeyDown={(e) => {
                              field.keyPress &&
                                field.keyPress(
                                  e,
                                  index,
                                  setValue,
                                  f,
                                  watch,
                                  permission
                                );
                            }}
                            className={inputClass(fieldState.invalid)}
                          />
                        )}

                      {/* ERROR */}
                      <small className="text-red-500 text-[10px]">
                        {getFormErrorMessageMultiple(
                          field.name,
                          index
                        )}
                      </small>
                    </>
                  )}
                />
              </div>
            );
          })}

          {/* LOGIC-BASED DELETE SPACER */}
          <div
            className={`col-span-6 md:col-span-${columnsNeeded}`}
          ></div>
        </div>

        {/* APPEND BUTTON (BOTTOM LEFT) */}
        {showAppendButton && (
          <div className="absolute -bottom-9 left-1">
            <Button
              type="button"
              label={appendButtonLabel}
              icon="pi pi-plus"
              className="p-button-text p-button-sm"
              onClick={(e) => {
                e.preventDefault();
                if (typeof onAppendButton === "function") {
                  onAppendButton(index, watch(`list.${index}`), watch(), e);
                }
              }}
            />
          </div>
        )}
      </div>
    </>
  );
};

export default DynamicFieldGroup;
