"use client";

import { useEffect, useState, useCallback, useRef } from "react";
import TableCard from "./components/TableCard";
import TableList from "./components/TableList";
import ConfigPanel from "./components/ConfigPanel";
import ConnectionPanel from "./components/ConnectionPanel";
import TableDetailModal from "./components/TableDetailModal";
import { useMigrationStream } from "./hooks/useMigrationStream";
import MigrationProgress from "./components/dashboard/MigrationProgress";
import { useConfigPanel } from "./hooks/useConfigPanel";
import { JsonDataFormatter } from "./components/tables/JsonDataFormatter";
import { API_BASE_URL } from "./lib/api";

type TableData = {
  table: string;
  status: "OK" | "ERROR";
  tag: string;
  isCritical: boolean;
  compareBy: "DAY" | "WEEK" | "MONTH";
  metrics: {
    rows: { source: number; target: number };
    columns: { source: number; target: number };
  };
  match: number;
  maxId: number;
};

type ApiResponse = {
  generatedAt: string;
  summary: { totalTables: number; ok: number; errors: number };
  pagination: {
    page: number;
    perPage: number;
    total: number;
    totalPages: number;
  };
  globalStatus: "OK" | "ERROR";
  tables: TableData[];
};

type ArchivedTable = {
  id: number;
  table_name: string;
  rule_type: string;
  total_records_archived: number;
  last_archive_date: string;
};

type ArchivedLog = {
  id: number;
  table_name: string;
  record_id: string;
  rule_type: string;
  data_content: Record<string, any>;
  status: string;
  created_at: string;
};

export default function Page() {
  const [data, setData] = useState<ApiResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [initialLoad, setInitialLoad] = useState(true);
  const [syncing, setSyncing] = useState(false);
  const [syncData, setSyncData] = useState<Record<string, any>>({});
  const [actionMessage, setActionMessage] = useState("");
  const [actionError, setActionError] = useState(false);
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState("");
  const [selectedTable, setSelectedTable] = useState<any>(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [activeTab, setActiveTab] = useState<"produccion" | "archivo">(
    "produccion",
  );

  const [connectionName, setConnectionName] = useState<string>("");
  const [databaseName, setDatabaseName] = useState<string>("");
  const [sourceDatabaseName, setSourceDatabaseName] = useState<string>("");
  const [streamActive, setStreamActive] = useState(false);
  const [archivedTables, setArchivedTables] = useState<ArchivedTable[]>([]);
  const [selectedArchivedTable, setSelectedArchivedTable] =
    useState<string>("");
  const [archivedLogs, setArchivedLogs] = useState<ArchivedLog[]>([]);
  const [logsTotalPages, setLogsTotalPages] = useState(1);
  const [logsPage, setLogsPage] = useState(1);
  const [logsSearch, setLogsSearch] = useState("");
  const [loadingLogs, setLoadingLogs] = useState(false);
  const [restoringId, setRestoringId] = useState<number | null>(null);
  const [isRestoringAll, setIsRestoringAll] = useState(false);

  const migratingRef = useRef(false);

  const configState = useConfigPanel({
    connectionName: "source",
    databaseName: sourceDatabaseName,
    itemsPerPage: 5,
  });

  const fetchData = useCallback(
    async (currentPage = page, currentSearch = search) => {
      try {
        const res = await fetch(
          `${API_BASE_URL}/validation/report?page=${currentPage}&search=${encodeURIComponent(currentSearch)}`,
          { cache: "no-store" },
        );
        const json = await res.json();

        if (json.status === "error") {
          setActionMessage(json.message);
          setActionError(true);
          setData(null);
          return;
        }
        setActionMessage("");
        setActionError(false);
        setData(json);
      } catch (error) {
        console.error("Error fetching validation:", error);
        setActionMessage("Cannot connect to backend");
        setActionError(true);
        setData(null);
      } finally {
        setLoading(false);
        setInitialLoad(false);
      }
    },
    [],
  );

  const fetchArchivedTables = useCallback(async () => {
    try {
      const res = await fetch(
        `${API_BASE_URL}/unified-repository/tables`,
      );
      const json = await res.json();

      if (Array.isArray(json)) {
        setArchivedTables(json);
      } else {
        setArchivedTables([]);
      }
    } catch (err) {
      console.error("Error cargando tablas archivadas:", err);
      setArchivedTables([]);
    }
  }, []);

  const fetchArchivedLogs = useCallback(
    async (
      tableName: string,
      currentPage = logsPage,
      currentSearch = logsSearch,
    ) => {
      if (!tableName) return;
      try {
        setLoadingLogs(true);
        const res = await fetch(
          `${API_BASE_URL}/unified-repository/logs?table_name=${tableName}&page=${currentPage}&size=5&search=${encodeURIComponent(currentSearch)}`,
        );
        const json = await res.json();
        setArchivedLogs(json.items || []);
        setLogsTotalPages(Math.ceil((json.total || 0) / 5));
      } catch (err) {
        console.error("Error cargando logs históricos:", err);
      } finally {
        setLoadingLogs(false);
      }
    },
    [],
  );

  const handleRestore = async (logId: number) => {
    try {
      setRestoringId(logId);
      const res = await fetch(
        `${API_BASE_URL}/unified-repository/restore/${logId}`,
        { method: "POST" },
      );
      const json = await res.json();

      if (!res.ok) throw new Error(json.detail || "Error al restaurar");

      setActionMessage(
        json.message || "Registro recuperado e insertado en origen con éxito.",
      );
      setActionError(false);

      await fetchArchivedTables();
      if (archivedLogs.length === 1 && logsPage > 1) {
        setLogsPage((prev) => prev - 1);
      } else {
        await fetchArchivedLogs(selectedArchivedTable, logsPage, logsSearch);
      }
      await fetchData(page, search);
    } catch (err: any) {
      setActionMessage(err.message || "Error conectando con el servidor");
      setActionError(true);
    } finally {
      setRestoringId(null);
    }
  };

  const handleRestoreAll = async (tableName: string) => {
    if (!tableName) return;

    const confirmed = window.confirm(
      `¿Estás seguro de que deseas recuperar TODOS los registros archivados de la tabla "${tableName}"?\n\nEsta acción revertirá el archivado de forma masiva en producción.`,
    );
    if (!confirmed) return;

    setIsRestoringAll(true);
    try {
      const res = await fetch(
        `${API_BASE_URL}/unified-repository/restore-all?table_name=${tableName}`,
        {
          method: "POST",
        },
      );

      const dataJson = await res.json();

      if (res.ok) {
        alert(dataJson.message || "Registros recuperados exitosamente.");

        setSelectedArchivedTable("");
        setArchivedLogs([]);
        setLogsPage(1);

        if (typeof fetchArchivedTables === "function") {
          fetchArchivedTables();
        }
      } else {
        alert(
          `Error: ${dataJson.detail || "No se pudo completar la restauración masiva."}`,
        );
      }
    } catch (error) {
      console.error("Error al restaurar todo en lote:", error);
      alert("Ocurrió un error en la conexión con el servidor.");
    } finally {
      setIsRestoringAll(false);
    }
  };

  useEffect(() => {
    if (activeTab === "archivo") {
      fetchArchivedTables();
    }
  }, [activeTab, fetchArchivedTables]);

  useEffect(() => {
    if (selectedArchivedTable) {
      fetchArchivedLogs(selectedArchivedTable, logsPage, logsSearch);
    }
  }, [selectedArchivedTable, logsPage, logsSearch, fetchArchivedLogs]);

  const handleSourceConnectionSuccess = useCallback(
    (conn: string = "source", db: string = "pideprueba") => {
      setConnectionName(conn);
      setDatabaseName(db);
      setSourceDatabaseName(db);
      fetchData(1, "");
    },
    [fetchData],
  );

  const handleTargetConnectionSuccess = useCallback(() => {
    // La conexión destino no afecta el panel de configuración (siempre usa source).
  }, []);

  const handleMigrationComplete = useCallback(() => {
    setActionMessage("Migration completed");
    migratingRef.current = false;
    setStreamActive(false);
    fetchData(page, search);
  }, [fetchData, page, search]);

  const { migrating, migrationProgress, startStream, resetProgress } =
    useMigrationStream(streamActive, handleMigrationComplete);

  useEffect(() => {
    migratingRef.current = migrating;
  }, [migrating]);

  async function runMigration() {
    try {
      setActionMessage("");
      setActionError(false);
      resetProgress();
      setStreamActive(true);

      const res = await fetch(`${API_BASE_URL}/migration/start`, {
        method: "POST",
      });
      const json = await res.json();

      if (json.status === "error") {
        setActionMessage(json.message);
        setActionError(true);
        setStreamActive(false);
        return;
      }

      setActionMessage("Migration started successfully");
    } catch (error) {
      console.error("LOG [PAGE] -> Error al iniciar la migración:", error);
      setActionMessage("Cannot connect to backend");
      setActionError(true);
      setStreamActive(false);
    }
  }

  const runSync = useCallback(async () => {
    try {
      setSyncing(true);
      setActionMessage("");
      setActionError(false);

      const res = await fetch(`${API_BASE_URL}/api-v2/sync/run`);
      const json = await res.json();

      if (json.status === "error") {
        setActionMessage(json.message);
        setActionError(true);
        return;
      }

      setSyncData(json.tables || {});
      setActionMessage("Sync completed successfully");
      await fetchData(page, search);
    } catch (error) {
      console.error("Error running sync:", error);
      setActionMessage("Cannot connect to backend");
      setActionError(true);
    } finally {
      setSyncing(false);
    }
  }, [fetchData, page, search]);

  useEffect(() => {
    fetchData(page, search);
  }, [fetchData, page, search]);

  useEffect(() => {
    const syncInterval = setInterval(() => {
      if (!migratingRef.current) {
        runSync();
      }
    }, 3600000);

    return () => clearInterval(syncInterval);
  }, [runSync]);

  if (loading && initialLoad) {
    return (
      <div className="min-h-screen bg-black text-white p-6">
        <h1 className="text-xl font-mono">Cargando Sistema...</h1>
      </div>
    );
  }

  if (!data) {
    return (
      <div className="min-h-screen bg-[#0a0a0a] text-gray-300 p-6">
        <h1 className="text-2xl font-black text-white italic mb-6">
          PANEL DE MIGRACIÓN
        </h1>
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
          <ConnectionPanel
            connectionType="source"
            onConnectionSuccess={(conn, db) =>
              handleSourceConnectionSuccess(conn, db)
            }
          />
          <ConnectionPanel
            connectionType="target"
            onConnectionSuccess={handleTargetConnectionSuccess}
          />
        </div>
        {actionMessage && (
          <div
            className={`mt-6 px-4 py-3 rounded border text-sm ${actionError ? "bg-red-500/10 border-red-500 text-red-400" : "bg-green-500/10 border-green-500 text-green-400"}`}
          >
            {actionMessage}
          </div>
        )}
      </div>
    );
  }

  const activeTableRule = archivedTables.find(
    (t) => t.table_name === selectedArchivedTable,
  )?.rule_type;

  const processedStages =
    migrationProgress?.stages && migrationProgress.stages.length > 0
      ? migrationProgress.stages
      : [
          {
            id: 1,
            stage_number: 1,
            status: "completed" as
              | "pending"
              | "running"
              | "completed"
              | "failed",
            total_tables: data.tables?.length || 0,
            created_at: new Date().toISOString(),
            tables: (data.tables || []).map((t, idx) => ({
              id: idx,
              table_name: t.table,
              is_critical: !!t.isCritical,
              size_kb: 0,
            })),
          },
        ];

  return (
    <div className="min-h-screen bg-[#0a0a0a] text-gray-300 p-6">
      <h1 className="text-3xl font-black text-white italic mb-6">
        PANEL DE MIGRACIÓN
      </h1>

      <div className="mb-6">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
          <ConnectionPanel
            connectionType="source"
            onConnectionSuccess={(conn, db) =>
              handleSourceConnectionSuccess(conn, db)
            }
          />
          <ConnectionPanel
            connectionType="target"
            onConnectionSuccess={handleTargetConnectionSuccess}
          />
        </div>
      </div>

      <div className="mb-6">
        <ConfigPanel configState={configState} />
      </div>

      {/* ACTIONS */}
      <div className="mb-6 flex items-center gap-3">
        <button
          onClick={runMigration}
          disabled={migrating}
          className={`px-4 py-2 rounded text-sm font-mono transition ${
            migrating
              ? "bg-gray-700 text-gray-400 cursor-not-allowed"
              : "bg-blue-500 hover:bg-blue-600 text-white"
          }`}
        >
          {migrating ? "Migrando..." : "Ejecutar migración"}
        </button>

        <button
          onClick={runSync}
          disabled={syncing || migrating}
          className={`px-4 py-2 rounded text-sm font-mono transition ${
            syncing || migrating
              ? "bg-gray-700 text-gray-400 cursor-not-allowed"
              : "bg-purple-500 hover:bg-purple-600 text-white"
          }`}
        >
          {syncing ? "Sincronizando..." : "Ejecutar sincronización"}
        </button>

        <span
          className={`px-3 py-1 rounded text-sm font-mono ${data.globalStatus === "OK" ? "bg-green-500/20 text-green-400" : "bg-red-500/20 text-red-400"}`}
        >
          Estado global: {data.globalStatus}
        </span>
      </div>

      {actionMessage && (
        <div
          className={`mb-6 px-4 py-3 rounded border text-sm ${actionError ? "bg-red-500/10 border-red-500 text-red-400" : "bg-green-500/10 border-green-500 text-green-400"}`}
        >
          {actionMessage}
        </div>
      )}

      <MigrationProgress
        migrating={migrating}
        migrationProgress={migrationProgress}
      />

      {/* PESTAÑAS CONTENEDORAS */}
      <div className="mt-8 mb-4 flex border-b border-gray-800 gap-2">
        <button
          onClick={() => setActiveTab("produccion")}
          className={`px-4 py-2 text-sm font-medium border-b-2 transition-all ${
            activeTab === "produccion"
              ? "border-blue-500 text-white font-bold"
              : "border-transparent text-gray-500 hover:text-gray-300"
          }`}
        >
          📁 Tablas Migradas
        </button>
        <button
          onClick={() => setActiveTab("archivo")}
          className={`px-4 py-2 text-sm font-medium border-b-2 transition-all ${
            activeTab === "archivo"
              ? "border-purple-500 text-white font-bold"
              : "border-transparent text-gray-500 hover:text-gray-300"
          }`}
        >
          🗑️ Repositorio Unificado
        </button>
      </div>

      {/* RENDERIZADO CONDICIONAL DE VISTAS */}
      {activeTab === "produccion" ? (
        data.tables && data.tables.length > 0 ? (
          <TableList
            tables={data.tables}
            onRefresh={() => fetchData(page, search)}
            page={page}
            totalPages={data.pagination.totalPages}
            search={search}
            setPage={setPage}
            setSearch={setSearch}
            onSelect={(table) => {
              setSelectedTable(table);
              setModalOpen(true);
            }}
            backendStages={processedStages}
          />
        ) : search.trim() !== "" ? (
          <div className="flex flex-col items-center justify-center p-12 border border-dashed border-gray-800 rounded-xl bg-[#0e0e0e] text-center max-w-4xl mx-auto my-4">
            <h3 className="text-white font-bold text-base">
              No se encontraron tablas asignadas que coincidan con "{search}"
            </h3>
            <button
              onClick={() => {
                setSearch("");
                fetchData(page, "");
              }}
              className="mt-3 text-xs bg-blue-500/10 text-blue-400 border border-blue-500/20 px-3 py-1.5 rounded-lg hover:bg-blue-500 hover:text-white transition-all"
            >
              Limpiar búsqueda
            </button>
          </div>
        ) : (
          <div className="flex flex-col items-center justify-center p-12 border border-dashed border-gray-800 rounded-xl bg-[#0e0e0e] text-center max-w-4xl mx-auto my-4 animate-fadeIn">
            <h3 className="text-white font-bold text-base">
              No se realizó ninguna migración
            </h3>
            <p className="text-gray-500 text-xs mt-2 max-w-md">
              Esta base de datos está limpia o es nueva. Selecciona las tablas
              que deseas procesar en el panel de configuración superior y
              ejecuta la migración para ver su estado aquí abajo.
            </p>
          </div>
        )
      ) : (
        <div className="bg-[#111] p-6 rounded-xl border border-gray-800 animate-fadeIn">
          <div className="flex flex-col md:flex-row items-end gap-4 mb-6 w-full">
            <div className="w-full md:w-1/3">
              <label className="block text-xs text-gray-400 mb-2 font-mono">
                SELECCIONAR TABLA CONFIGURADA
              </label>
              <select
                className="w-full bg-[#1a1a1a] border border-gray-800 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-purple-500"
                value={selectedArchivedTable}
                onChange={(e) => {
                  setSelectedArchivedTable(e.target.value);
                  setLogsPage(1);
                  setArchivedLogs([]);
                }}
              >
                <option value="" disabled>
                  -- Elige una tabla archivada --
                </option>
                {archivedTables.map((t) => (
                  <option key={t.id} value={t.table_name}>
                    {t.table_name} ({t.total_records_archived} registros)
                  </option>
                ))}
              </select>
            </div>

            {selectedArchivedTable && (
              <div className="w-full md:w-1/2 flex flex-col md:flex-row items-end gap-2">
                <div className="w-full">
                  <label className="block text-xs text-gray-400 mb-2 font-mono">
                    BUSCADOR GENERAL
                  </label>
                  <input
                    type="text"
                    placeholder="Escribe para buscar..."
                    value={logsSearch}
                    className="w-full bg-[#1a1a1a] border border-gray-800 rounded-lg px-3 py-1.5 text-sm text-white focus:outline-none focus:border-purple-500"
                    onChange={(e) => {
                      setLogsPage(1);
                      setLogsSearch(e.target.value);
                    }}
                  />
                </div>

                <button
                  onClick={() => handleRestoreAll(selectedArchivedTable)}
                  disabled={isRestoringAll || archivedLogs.length === 0}
                  className={`w-full md:w-auto h-[34px] px-4 rounded-lg text-xs font-sans font-bold flex items-center justify-center gap-1.5 whitespace-nowrap transition-all ${
                    isRestoringAll
                      ? "bg-amber-500/10 text-amber-400 border border-amber-500/20 animate-pulse cursor-not-allowed"
                      : archivedLogs.length === 0
                        ? "bg-gray-800/50 text-gray-600 border border-gray-800/30 cursor-not-allowed"
                        : "bg-purple-600 hover:bg-purple-700 text-white shadow-lg shadow-purple-600/10 active:scale-95"
                  }`}
                >
                  {isRestoringAll ? "Recuperando lote..." : "Recuperar Todo"}
                </button>
              </div>
            )}

            {selectedArchivedTable && activeTableRule && (
              <div className="md:ml-auto pb-1">
                <span
                  className={`inline-block px-3 py-1.5 rounded-lg text-xs font-mono border ${
                    activeTableRule.toLowerCase().includes("hist")
                      ? "bg-purple-500/10 text-purple-400 border-purple-500/30"
                      : "bg-cyan-500/10 text-cyan-400 border-cyan-500/30"
                  }`}
                >
                  <span className="font-bold uppercase">
                    {activeTableRule.toLowerCase().includes("hist")
                      ? "HISTÓRICO"
                      : "HÍBRIDO"}
                  </span>
                </span>
              </div>
            )}
          </div>

          {/* ESPACIO DE TRABAJO DE LOGS */}
          {!selectedArchivedTable ? (
            <div className="border border-dashed border-gray-800 rounded-lg p-12 text-center text-gray-500">
              Selecciona una tabla del menú desplegable para consultar o
              recuperar los registros que fueron migrados al repositorio
              histórico.
            </div>
          ) : loadingLogs ? (
            <div className="text-center py-12 text-purple-400 font-mono text-sm animate-pulse">
              Consultando logs estructurados en el repositorio...
            </div>
          ) : archivedLogs.length === 0 ? (
            <div className="text-center py-12 text-gray-500 border border-gray-800 rounded-lg bg-[#0e0e0e] flex flex-col items-center justify-center">
              <p>
                No hay registros archivados activos que coincidan con la
                búsqueda.
              </p>
              {logsSearch.trim() !== "" && (
                <button
                  onClick={() => setLogsSearch("")}
                  className="mt-3 text-xs text-purple-400 hover:underline font-mono"
                >
                  [Limpiar filtro de búsqueda]
                </button>
              )}
            </div>
          ) : (
            <div className="overflow-x-auto border border-gray-800 rounded-lg bg-[#0d0d0d]">
              <table className="w-full text-left border-collapse">
                <thead>
                  <tr className="border-b border-gray-800 bg-[#161616] text-xs font-mono text-gray-400">
                    <th className="p-3 w-20">ID LOG</th>
                    <th className="p-3 w-32">RECORD PK</th>
                    <th className="p-3">CONTENIDO DEL REGISTRO</th>
                    <th className="p-3 w-40 text-center">ACCIONES</th>
                  </tr>
                </thead>
                <tbody className="text-xs font-mono">
                  {archivedLogs.map((log) => (
                    <tr
                      key={log.id}
                      className="border-b border-gray-900 hover:bg-[#121212] text-gray-300"
                    >
                      <td className="p-3 text-gray-600">#{log.id}</td>
                      <td className="p-3 font-bold text-purple-400">
                        {log.record_id}
                      </td>
                      <td className="p-3">
                        <JsonDataFormatter data={log.data_content} />
                      </td>
                      <td className="p-3 text-center">
                        <button
                          onClick={() => handleRestore(log.id)}
                          disabled={restoringId !== null}
                          className={`px-3 py-1 rounded font-sans font-bold text-xs transition ${
                            restoringId === log.id
                              ? "bg-amber-500/20 text-amber-400 animate-pulse cursor-not-allowed"
                              : "bg-blue-500/10 text-blue-400 hover:bg-blue-500 hover:text-white border border-blue-500/20"
                          }`}
                        >
                          {restoringId === log.id
                            ? "Recuperando..."
                            : "Recuperar"}
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>

              {logsTotalPages > 1 && (
                <div className="p-3 flex items-center justify-between border-t border-gray-800 bg-[#141414]">
                  <span className="text-xs text-gray-500">
                    Página {logsPage} de {logsTotalPages}
                  </span>
                  <div className="flex gap-2">
                    <button
                      disabled={logsPage === 1}
                      onClick={() => setLogsPage((p) => p - 1)}
                      className="px-2 py-1 rounded bg-[#1f1f1f] text-gray-300 text-xs disabled:opacity-40"
                    >
                      Anterior
                    </button>
                    <button
                      disabled={logsPage === logsTotalPages}
                      onClick={() => setLogsPage((p) => p + 1)}
                      className="px-2 py-1 rounded bg-[#1f1f1f] text-gray-300 text-xs disabled:opacity-40"
                    >
                      Siguiente
                    </button>
                  </div>
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {/* MODAL DETAIL */}
      <TableDetailModal
        table={selectedTable}
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        onUpdate={() => {}}
        syncData={syncData}
      />
    </div>
  );
}
