﻿// react
import React, { useCallback, useEffect, useState } from "react";
// third-party
import { useForm } from "react-hook-form";
// application
import { IBrand, IModel } from "~/admin/interfaces/vehicle";
import { vehiclesApi } from "~/admin/services/vehiclesApi";
import { InputImageSingle } from "~/admin/components/models/InputImageSingle";

interface Props {
  brand?: IBrand | null;
  /** Valor sugerido de posición al crear una marca nueva */
  defaultPosition?: number;
  /** Listado completo de marcas para comprobar posiciones ocupadas */
  existingBrands: IBrand[];
  onSave: (formData: FormData) => void;
  onCancel: () => void;
}

export const BrandForm = ({
  brand,
  defaultPosition = 1,
  existingBrands,
  onSave,
  onCancel,
}: Props) => {
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  /** Mensaje si la posición ya la usa otra marca (null = disponible o sin comprobar) */
  const [positionTakenMessage, setPositionTakenMessage] = useState<string | null>(null);
  /** Modelos asignados a la marca (solo al editar, para la vista previa) */
  const [brandModels, setBrandModels] = useState<IModel[]>([]);

  // Cargar los modelos de la marca al entrar a editar
  useEffect(() => {
    let active = true;
    if (!brand?.id) return;
    vehiclesApi
      .getAllModels(true)
      .then((all) => {
        if (!active) return;
        const own = all.filter((m) => m.vehicle_brandID === brand.id);
        setBrandModels(own);
      })
      .catch(() => {
        if (active) setBrandModels([]);
      });
    return () => {
      active = false;
    };
  }, [brand?.id]);

  const validatePositionAvailable = useCallback(
    (raw: string): boolean => {
      const trimmed = String(raw).trim();
      if (trimmed === "") {
        setPositionTakenMessage(null);
        return true;
      }
      const n = parseInt(trimmed, 10);
      if (Number.isNaN(n) || n < 0) {
        setPositionTakenMessage(null);
        return true;
      }
      const taken = existingBrands.some(
        (b) =>
          b.id !== brand?.id &&
          Number(b.sort_position ?? b.position ?? 0) === n
      );
      if (taken) {
        setPositionTakenMessage("Esta posición ya está en uso por otra marca.");
        return false;
      }
      setPositionTakenMessage(null);
      return true;
    },
    [existingBrands, brand?.id]
  );

  /** Solo dígitos 0–9: bloquea + - . , e E y cualquier otro carácter */
  const blockNonDigitPositionKeys = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.ctrlKey || e.metaKey || e.altKey) return;
    const allowed = [
      "Backspace",
      "Delete",
      "Tab",
      "Escape",
      "Enter",
      "ArrowLeft",
      "ArrowRight",
      "ArrowUp",
      "ArrowDown",
      "Home",
      "End",
    ];
    if (allowed.includes(e.key)) return;
    if (e.key.length === 1 && /[0-9]/.test(e.key)) return;
    e.preventDefault();
  };

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<IBrand>({
    defaultValues: brand
      ? {
          name: brand.name,
          imageUrl: brand.imageUrl,
          status: brand.status === 1 || brand.status === true,
          position: brand.sort_position ?? brand.position ?? 0,
        }
      : { name: "", imageUrl: "", status: true, position: defaultPosition },
  });

  const positionRegister = register("position", {
    setValueAs: (v) => {
      const digits = String(v ?? "").replace(/\D/g, "");
      if (digits === "") return 0;
      const n = parseInt(digits, 10);
      return Number.isNaN(n) ? 0 : n;
    },
    min: { value: 0, message: "No puede ser negativo" },
  });

  const sanitizePositionPaste = (e: React.ClipboardEvent<HTMLInputElement>) => {
    e.preventDefault();
    const paste = (e.clipboardData.getData("text") || "").replace(/\D/g, "");
    const input = e.currentTarget;
    const start = input.selectionStart ?? 0;
    const end = input.selectionEnd ?? 0;
    const merged = `${input.value.slice(0, start)}${paste}${input.value.slice(end)}`;
    const next = merged.replace(/\D/g, "");
    input.value = next;
    const caret = Math.min(start + paste.length, next.length);
    requestAnimationFrame(() => input.setSelectionRange(caret, caret));
    positionRegister.onChange({
      target: input,
      type: "change",
    } as React.ChangeEvent<HTMLInputElement>);
  };

  useEffect(() => {
    const initial =
      brand != null ? (brand.sort_position ?? brand.position ?? 0) : defaultPosition;
    validatePositionAvailable(String(initial));
  }, [brand?.id, defaultPosition, validatePositionAvailable]);

  const onSubmit = (data: IBrand) => {
    const posStr =
      typeof data.position === "number" && !Number.isNaN(data.position)
        ? String(data.position)
        : String(data.position ?? "");
    if (!validatePositionAvailable(posStr)) {
      return;
    }

    const formData = new FormData();
    formData.append("name", data.name.trim().toUpperCase());
    // On create, API sets status = 1; on edit, send current value
    formData.append("status", (brand ? data.status : true) ? "1" : "0");
    const pos =
      typeof data.position === "number" && !Number.isNaN(data.position)
        ? data.position
        : parseInt(String(data.position ?? "0"), 10) || 0;
    formData.append("position", String(pos));

    if (brand?.id) {
      formData.append("id", String(brand.id));
    }
    if (selectedFile) {
      formData.append("image", selectedFile);
    } else if (brand?.imageUrl) {
      formData.append("existingImageUrl", brand.imageUrl);
    }

    onSave(formData);
  };

  return (
    <div className="card">
      <div className="card-header">
        <h3>{brand ? `Editar: ${brand.name}` : "Nueva Marca"}</h3>
      </div>
      <div className="card-body">
        <form onSubmit={handleSubmit(onSubmit)}>
          <div className="row">
            <div className="col-md-6">
              <div className="form-group">
                <label>Nombre *</label>
                <input
                  type="text"
                  placeholder="TOYOTA"
                  className={`form-control ${errors.name ? "is-invalid" : ""}`}
                  {...register("name", { required: "La marca es requerida" })}
                />
                {errors.name && (
                  <div className="invalid-feedback">{errors.name.message}</div>
                )}
              </div>
            </div>
            <div className="col-md-6">
              <div className="form-group">
                <label>Posición (orden)</label>
                <input
                  type="text"
                  inputMode="numeric"
                  pattern="[0-9]*"
                  autoComplete="off"
                  placeholder="0"
                  className={`form-control ${
                    errors.position || positionTakenMessage ? "is-invalid" : ""
                  }`}
                  name={positionRegister.name}
                  ref={positionRegister.ref}
                  onChange={(e) => {
                    const el = e.currentTarget;
                    const next = el.value.replace(/\D/g, "");
                    if (el.value !== next) el.value = next;
                    positionRegister.onChange(e);
                  }}
                  onKeyDown={blockNonDigitPositionKeys}
                  onPaste={sanitizePositionPaste}
                  onBlur={(e) => {
                    positionRegister.onBlur(e);
                    validatePositionAvailable(e.currentTarget.value);
                  }}
                  onKeyUp={(e) =>
                    validatePositionAvailable((e.target as HTMLInputElement).value)
                  }
                />
                {positionTakenMessage && (
                  <div className="invalid-feedback d-block">{positionTakenMessage}</div>
                )}
                {errors.position && !positionTakenMessage && (
                  <div className="invalid-feedback d-block">{errors.position.message}</div>
                )}
              </div>
            </div>
          </div>

          <div className="form-group mt-3">
            <InputImageSingle
              initialImage={brand?.imageUrl}
              onFileChange={setSelectedFile}
              inputId="brand-image"
              label="Imagen de la marca (1 imagen)"
              helperText="Medidas recomendadas: 800 x 800 px (imagen cuadrada, proporcion 1:1)."
            />
          </div>

          {brand?.id && (
            <div className="form-group mt-3">
              <label>Modelos asignados a esta marca</label>
              {brandModels.length === 0 ? (
                <div className="alert alert-info py-2 mb-0" style={{ fontSize: 14 }}>
                  <i className="fas fa-info-circle mr-2" />
                  Esta marca aún no tiene modelos asignados. Agrégales desde la sección
                  &quot;Modelos&quot;.
                </div>
              ) : (
                <div
                  className="border rounded p-2"
                  style={{ maxHeight: 200, overflowY: "auto", background: "#fafafa" }}
                >
                  <ul className="list-unstyled mb-0">
                    {brandModels.map((m) => (
                      <li
                        key={m.id}
                        className="d-flex align-items-center justify-content-between px-2 py-1 border-bottom"
                      >
                        <span>
                          <i className="fas fa-car mr-2 text-muted" />
                          {m.name}
                        </span>
                        {typeof m.products_count === "number" && (
                          <span className="badge badge-light">
                            {m.products_count} prod.
                          </span>
                        )}
                      </li>
                    ))}
                  </ul>
                </div>
              )}
            </div>
          )}

          <div className="form-group mt-3">
            <div className="form-check">
              <input
                type="checkbox"
                id="brand-status"
                className="form-check-input"
                {...register("status")}
              />
              <label className="form-check-label" htmlFor="brand-status">
                Activo
              </label>
            </div>
            <small className="text-muted">Desactiva la marca para ocultarla sin eliminarla.</small>
          </div>

          <div className="form-actions mt-4">
            <button
              type="submit"
              className="btn btn-primary"
              disabled={!!positionTakenMessage}
            >
              <i className="fas fa-save" /> Guardar
            </button>
            <button
              type="button"
              className="btn btn-secondary ml-2"
              onClick={onCancel}
            >
              Cancelar
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};
