﻿// react
import React, { useState, useEffect } from "react";
// application
import AdminLayout from "~/admin/components/AdminLayout";
import ProtectedRoute from "~/admin/components/ProtectedRoute";
import { IBrand, IModel } from "~/admin/interfaces/vehicle";
import { vehiclesApi } from "~/admin/services/vehiclesApi";
import { toast } from "react-toastify";
import { downloadPdfTable } from "~/admin/utils/pdfExport";
import { ModelForm } from "~/admin/components/models/ModelForm";
import { ModelList } from "~/admin/components/models/ModelList";

function ModelsPage() {
  const [models, setModels] = useState<IModel[]>([]);
  const [allModels, setAllModels] = useState<IModel[]>([]);
  const [brands, setBrands] = useState<IBrand[]>([]);
  const [editingModel, setEditingModel] = useState<IModel | null>(null);
  const [showForm, setShowForm] = useState<boolean>(false);
  const [loading, setLoading] = useState(true);
  const [searchTerm, setSearchTerm] = useState("");

  useEffect(() => {
    loadModels();
  }, []);

  const loadModels = async () => {
    try {
      setLoading(true);
      const [data, brandsData] = await Promise.all([
        vehiclesApi.getAllModels(true),
        vehiclesApi.getAllBrands(),
      ]);
      setAllModels(data);
      setModels(data);
      // Orden canónico de marcas (igual que la página de Marcas):
      // fija el orden de los grupos de modelos aunque el backend
      // liste los modelos por sort_position + nombre.
      setBrands(
        [...brandsData].sort(
          (a, b) =>
            Number(a.sort_position ?? a.position ?? 0) -
            Number(b.sort_position ?? b.position ?? 0),
        ),
      );
    } catch (error: any) {
      toast.error(error.message || "Error al cargar modelos");
    } finally {
      setLoading(false);
    }
  };

  const handleSearch = (term: string) => {
    setSearchTerm(term);

    if (!term.trim()) {
      setModels(allModels);
      return;
    }

    const lowerTerm = term.toLowerCase().trim();

    const filtered = allModels.filter((model) => {
      return (
        model.name.toLowerCase().includes(lowerTerm) ||
        model.brand_name?.toLowerCase().includes(lowerTerm) ||
        model.id?.toString().includes(lowerTerm)
      );
    });

    setModels(filtered);
  };

  const handleCreateModel = () => {
    setEditingModel(null);
    setShowForm(true);
  };

  const handleEdit = (model: IModel) => {
    setEditingModel(model);
    setShowForm(true);
  };

  const handleSave = async (formData: FormData) => {
    try {
      if (editingModel?.id) {
        await vehiclesApi.updateModelWithFormData(editingModel.id, formData);
        toast.success("Modelo actualizado exitosamente");
      } else {
        await vehiclesApi.createModelWithFormData(formData);
        toast.success("Modelo creado exitosamente");
      }
      setShowForm(false);
      setEditingModel(null);
      loadModels();
    } catch (error: any) {
      toast.error(error.message || "Error al guardar modelo");
    }
  };

  const handleDelete = async (id: number) => {
    if (!confirm("¿Estás seguro de eliminar este modelo?")) {
      return;
    }

    try {
      await vehiclesApi.deleteModel(id);
      toast.success("Modelo eliminado exitosamente");
      loadModels();
    } catch (error: any) {
      toast.error(error.message || "Error al eliminar modelo");
    }
  };

  const handleReorder = async (group: IModel[]) => {
    try {
      // El backend rechaza asignar a una marca una posición ya usada por otro
      // modelo de esa marca. Para reordenar sin conflictos hacemos 2 fases:
      //   1) mover todos los modelos del grupo a posiciones temporales altas
      //   2) reasignar 1..n en el nuevo orden
      const groupItems = group.filter((m) => m.id);
      if (groupItems.length === 0) return;

      // Fase 1: posiciones temporales (todas por encima del máximo actual)
      const maxPos = Math.max(
        0,
        ...groupItems.map((m) => Number(m.sort_position ?? m.position ?? 0)),
      );
      for (let i = 0; i < groupItems.length; i++) {
        const m = groupItems[i];
        const temp = maxPos + 1 + i;
        await vehiclesApi.updateModel(m.id!, {
          ...m,
          position: temp,
          sort_position: temp,
          status: m.status === false || m.status === 0 ? 0 : 1,
        });
      }

      // Fase 2: reasignar las MISMAS posiciones que ya tenía el grupo
      // (ordenadas ascendente), solo intercambiadas entre los modelos del
      // grupo según el nuevo orden. Así el conjunto de posiciones del grupo
      // no cambia → el orden GLOBAL entre marcas se mantiene intacto y las
      // marcas NO se reordenan al arrastrar un modelo (el backend lista los
      // modelos ordenados globalmente por sort_position).
      const originalPositions = groupItems
        .map((m) => Number(m.sort_position ?? m.position ?? 0))
        .sort((a, b) => a - b);

      for (let i = 0; i < groupItems.length; i++) {
        const m = groupItems[i];
        const position = originalPositions[i] ?? i + 1;
        await vehiclesApi.updateModel(m.id!, {
          ...m,
          position,
          sort_position: position,
          status: m.status === false || m.status === 0 ? 0 : 1,
        });
      }

      toast.success("Orden de modelos actualizado");
      await loadModels();
    } catch (error: any) {
      toast.error(error?.message || "Error al actualizar el orden de modelos");
    }
  };

  const handleCancel = () => {
    setShowForm(false);
    setEditingModel(null);
  };

  const handleExportPdf = async () => {
    try {
      await downloadPdfTable(
        `listado-modelos-${Date.now()}.pdf`,
        "Listado de Modelos",
        [
          { header: "Orden", dataKey: "orden", align: "center" },
          { header: "Nombre", dataKey: "name" },
          { header: "Cant. Productos", dataKey: "cantProductos", align: "center" },
          { header: "Marca asignada", dataKey: "brand_name" },
          { header: "Estado", dataKey: "statusLabel", align: "center" },
        ],
        allModels.map((m) => ({
          orden: String(m.sort_position ?? m.position ?? "—"),
          name: m.name,
          cantProductos: String(m.products_count ?? 0),
          brand_name: m.brand_name ?? "",
          statusLabel: m.status === false || m.status === 0 ? "Inactivo" : "Activo",
        }))
      );
      toast.success("PDF generado correctamente");
    } catch (error: any) {
      toast.error(error?.message || "Error al generar PDF");
    }
  };

  if (loading && models.length === 0) {
    return (
      <ProtectedRoute>
        <AdminLayout>
          <div className="text-center py-5">
            <div className="spinner-border" role="status">
              <span className="sr-only">Cargando...</span>
            </div>
          </div>
        </AdminLayout>
      </ProtectedRoute>
    );
  }

  return (
    <ProtectedRoute>
      <AdminLayout>
        <div className="page-header">
          <h1>Modelos</h1>
          {!showForm && (
            <>
              <button
                className="btn btn-primary mr-2"
                onClick={handleCreateModel}
              >
                <i className="fas fa-plus" /> Nuevo Modelo
              </button>
              <button
                type="button"
                className="btn btn-secondary mr-2"
                onClick={handleExportPdf}
                disabled={allModels.length === 0}
              >
                <i className="fas fa-file-pdf" /> Exportar PDF
              </button>
            </>
          )}
        </div>

        {showForm ? (
          <ModelForm
            model={editingModel}
            existingModels={allModels}
            onSave={handleSave}
            onCancel={handleCancel}
          />
        ) : (
          <>
            <div className="card mb-3">
              <div className="card-body">
                <div className="input-group">
                  <div className="input-group-prepend">
                    <span className="input-group-text">
                      <i className="fas fa-search" />
                    </span>
                  </div>
                  <input
                    type="text"
                    className="form-control"
                    placeholder="Buscar por ID, marca, modelo o año..."
                    value={searchTerm}
                    onChange={(e) => handleSearch(e.target.value)}
                  />
                  {searchTerm && (
                    <div className="input-group-append">
                      <button
                        className="btn btn-outline-secondary"
                        type="button"
                        onClick={() => handleSearch("")}
                      >
                        <i className="fas fa-times" />
                      </button>
                    </div>
                  )}
                </div>
                {searchTerm && (
                  <small className="text-muted mt-2 d-block">
                    {models.length} modelo{models.length !== 1 ? "s" : ""}{" "}
                    encontrado{models.length !== 1 ? "s" : ""}
                  </small>
                )}
              </div>
            </div>
            <ModelList
              models={models}
              brandOrder={brands}
              onEdit={handleEdit}
              onDelete={handleDelete}
              onReorder={handleReorder}
            />
          </>
        )}
      </AdminLayout>
    </ProtectedRoute>
  );
}

export default ModelsPage;
