// frontend/src/components/SimpleTable.tsx
import React, { useEffect, useState } from 'react';
import {
  useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel,
  getPaginationRowModel, flexRender, type CellContext,
  type ColumnDef
} from '@tanstack/react-table';
import { Tooltip } from 'react-tooltip';
import toast from 'react-hot-toast';
import type { Equipo, Sector, Usuario, UsuarioEquipoDetalle } from '../types/interfaces';
import styles from './SimpleTable.module.css';

import { equipoService, sectorService, usuarioService } from '../services/apiService';

import ModalAnadirEquipo from './ModalAnadirEquipo';
import ModalEditarSector from './ModalEditarSector';
import ModalCambiarClave from './ModalCambiarClave';
import ModalDetallesEquipo from './ModalDetallesEquipo';
import ModalAnadirDisco from './ModalAnadirDisco';
import ModalAnadirRam from './ModalAnadirRam';
import ModalAnadirUsuario from './ModalAnadirUsuario';

const SimpleTable = () => {
  const [data, setData] = useState<Equipo[]>([]);
  const [filteredData, setFilteredData] = useState<Equipo[]>([]);
  const [globalFilter, setGlobalFilter] = useState('');
  const [selectedSector, setSelectedSector] = useState('Todos');
  const [modalData, setModalData] = useState<Equipo | null>(null);
  const [sectores, setSectores] = useState<Sector[]>([]);
  const [modalPasswordData, setModalPasswordData] = useState<Usuario | null>(null);
  const [showScrollButton, setShowScrollButton] = useState(false);
  const [selectedEquipo, setSelectedEquipo] = useState<Equipo | null>(null);
  const [historial, setHistorial] = useState<any[]>([]);
  const [isOnline, setIsOnline] = useState(false);
  const [isAddModalOpen, setIsAddModalOpen] = useState(false);
  const [addingComponent, setAddingComponent] = useState<'disco' | 'ram' | 'usuario' | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  const refreshHistory = async (hostname: string) => {
    try {
      const data = await equipoService.getHistory(hostname);
      setHistorial(data.historial);
    } catch (error) {
      console.error('Error refreshing history:', error);
    }
  };

  useEffect(() => {
    const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
    if (selectedEquipo || modalData || modalPasswordData || isAddModalOpen) {
      document.body.classList.add('scroll-lock');
      document.body.style.paddingRight = `${scrollBarWidth}px`;
    } else {
      document.body.classList.remove('scroll-lock');
      document.body.style.paddingRight = '0';
    }
    return () => {
      document.body.classList.remove('scroll-lock');
      document.body.style.paddingRight = '0';
    };
  }, [selectedEquipo, modalData, modalPasswordData, isAddModalOpen]);

  useEffect(() => {
    if (!selectedEquipo) return;
    let isMounted = true;
    const checkPing = async () => {
      if (!selectedEquipo.ip) return;
      try {
        const data = await equipoService.ping(selectedEquipo.ip);
        if (isMounted) setIsOnline(data.isAlive);
      } catch (error) {
        if (isMounted) setIsOnline(false);
        console.error('Error checking ping:', error);
      }
    };
    checkPing();
    const interval = setInterval(checkPing, 10000);
    return () => { isMounted = false; clearInterval(interval); setIsOnline(false); };
  }, [selectedEquipo]);

  const handleCloseModal = () => {
    if (addingComponent) {
      toast.error("Debes cerrar la ventana de añadir componente primero.");
      return;
    }
    setSelectedEquipo(null);
    setIsOnline(false);
  };

  useEffect(() => {
    if (selectedEquipo) {
      equipoService.getHistory(selectedEquipo.hostname)
        .then(data => setHistorial(data.historial))
        .catch(error => console.error('Error fetching history:', error));
    }
  }, [selectedEquipo]);

  useEffect(() => {
    const handleScroll = () => setShowScrollButton(window.scrollY > 200);
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  useEffect(() => {
    setIsLoading(true);
    Promise.all([
      equipoService.getAll(),
      sectorService.getAll()
    ]).then(([equiposData, sectoresData]) => {
      setData(equiposData);
      setFilteredData(equiposData);
      const sectoresOrdenados = [...sectoresData].sort((a, b) => a.nombre.localeCompare(b.nombre, 'es', { sensitivity: 'base' }));
      setSectores(sectoresOrdenados);
    }).catch(error => {
      toast.error("No se pudieron cargar los datos iniciales.");
      console.error("Error al cargar datos:", error);
    }).finally(() => setIsLoading(false));
  }, []);

  const handleSectorChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    const value = e.target.value;
    setSelectedSector(value);
    if (value === 'Todos') setFilteredData(data);
    else if (value === 'Asignar') setFilteredData(data.filter(i => !i.sector));
    else setFilteredData(data.filter(i => i.sector?.nombre === value));
  };

  const handleSave = async () => {
    if (!modalData) return;
    const toastId = toast.loading('Guardando...');
    try {
      const sectorId = modalData.sector?.id ?? 0;
      await equipoService.updateSector(modalData.id, sectorId);
      const equipoActualizado = { ...modalData, sector_id: modalData.sector?.id };
      const updateFunc = (prev: Equipo[]) => prev.map(e => e.id === modalData.id ? equipoActualizado : e);
      setData(updateFunc);
      setFilteredData(updateFunc);
      if (selectedEquipo && selectedEquipo.id === modalData.id) {
        setSelectedEquipo(equipoActualizado);
      }
      toast.success('Sector actualizado.', { id: toastId });
      setModalData(null);
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
    }
  };

  const handleSavePassword = async (password: string) => {
    if (!modalPasswordData) return;
    const toastId = toast.loading('Actualizando...');
    try {
      await usuarioService.updatePassword(modalPasswordData.id, password);
      
      const usernameToUpdate = modalPasswordData.username;

      const newData = data.map(equipo => {
        if (!equipo.usuarios.some(u => u.username === usernameToUpdate)) {
          return equipo;
        }
        const updatedUsers = equipo.usuarios.map(user => 
          user.username === usernameToUpdate ? { ...user, password: password } : user
        );
        return { ...equipo, usuarios: updatedUsers };
      });
      setData(newData);
      if (selectedSector === 'Todos') setFilteredData(newData);
      else if (selectedSector === 'Asignar') setFilteredData(newData.filter(i => !i.sector));
      else setFilteredData(newData.filter(i => i.sector?.nombre === selectedSector));
      if (selectedEquipo) {
        const updatedSelectedEquipo = newData.find(e => e.id === selectedEquipo.id);
        if (updatedSelectedEquipo) {
          setSelectedEquipo(updatedSelectedEquipo);
        }
      }

      toast.success(`Contraseña para '${usernameToUpdate}' actualizada en todos sus equipos.`, { id: toastId });
      setModalPasswordData(null);

    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
    }
  };


  const handleRemoveUser = async (hostname: string, username: string) => {
    if (!window.confirm(`¿Quitar a ${username} de este equipo?`)) return;
    const toastId = toast.loading(`Quitando a ${username}...`);
    try {
      await usuarioService.removeUserFromEquipo(hostname, username);
      let equipoActualizado: Equipo | undefined;
      const updateFunc = (prev: Equipo[]) => prev.map(e => {
        if (e.hostname === hostname) {
          equipoActualizado = { ...e, usuarios: e.usuarios.filter(u => u.username !== username) };
          return equipoActualizado;
        }
        return e;
      });
      setData(updateFunc);
      setFilteredData(updateFunc);
      if (selectedEquipo && equipoActualizado && selectedEquipo.id === equipoActualizado.id) {
        setSelectedEquipo(equipoActualizado);
      }
      toast.success(`${username} quitado.`, { id: toastId });
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
    }
  };

  const handleDelete = async (id: number) => {
    if (!window.confirm('¿Eliminar este equipo y sus relaciones?')) return false;
    const toastId = toast.loading('Eliminando equipo...');
    try {
      await equipoService.deleteManual(id);
      setData(prev => prev.filter(e => e.id !== id));
      setFilteredData(prev => prev.filter(e => e.id !== id));
      toast.success('Equipo eliminado.', { id: toastId });
      return true;
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
      return false;
    }
  };

  const handleRemoveAssociation = async (type: 'disco' | 'ram' | 'usuario', associationId: number | { equipoId: number, usuarioId: number }) => {
    if (!window.confirm('¿Estás seguro de que quieres eliminar esta asociación manual?')) return;
    const toastId = toast.loading('Eliminando asociación...');
    try {
      let successMessage = '';
      if (type === 'disco' && typeof associationId === 'number') {
        await equipoService.removeDiscoAssociation(associationId);
        successMessage = 'Disco desasociado del equipo.';
      } else if (type === 'ram' && typeof associationId === 'number') {
        await equipoService.removeRamAssociation(associationId);
        successMessage = 'Módulo de RAM desasociado.';
      } else if (type === 'usuario' && typeof associationId === 'object') {
        await equipoService.removeUserAssociation(associationId.equipoId, associationId.usuarioId);
        successMessage = 'Usuario desasociado del equipo.';
      } else {
        throw new Error('Tipo de asociación no válido');
      }
      const updateState = (prevEquipos: Equipo[]) => prevEquipos.map(equipo => {
        if (equipo.id !== selectedEquipo?.id) return equipo;
        let updatedEquipo = { ...equipo };
        if (type === 'disco' && typeof associationId === 'number') {
          updatedEquipo.discos = equipo.discos.filter(d => d.equipoDiscoId !== associationId);
        } else if (type === 'ram' && typeof associationId === 'number') {
          updatedEquipo.memoriasRam = equipo.memoriasRam.filter(m => m.equipoMemoriaRamId !== associationId);
        } else if (type === 'usuario' && typeof associationId === 'object') {
          updatedEquipo.usuarios = equipo.usuarios.filter(u => u.id !== associationId.usuarioId);
        }
        return updatedEquipo;
      });
      setData(updateState);
      setFilteredData(updateState);
      setSelectedEquipo(prev => prev ? updateState([prev])[0] : null);
      if (selectedEquipo) {
        await refreshHistory(selectedEquipo.hostname);
      }
      toast.success(successMessage, { id: toastId });
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
    }
  };

  const handleCreateEquipo = async (nuevoEquipo: Omit<Equipo, 'id' | 'created_at' | 'updated_at'>) => {
    const toastId = toast.loading('Creando nuevo equipo...');
    try {
      const equipoCreado = await equipoService.createManual(nuevoEquipo);
      setData(prev => [...prev, equipoCreado]);
      setFilteredData(prev => [...prev, equipoCreado]);
      toast.success(`Equipo '${equipoCreado.hostname}' creado.`, { id: toastId });
      setIsAddModalOpen(false);
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
    }
  };

  const handleEditEquipo = async (id: number, equipoEditado: any) => {
    const toastId = toast.loading('Guardando cambios...');
    try {
      const equipoActualizadoDesdeBackend = await equipoService.updateManual(id, equipoEditado);
      const updateState = (prev: Equipo[]) => prev.map(e => e.id === id ? equipoActualizadoDesdeBackend : e);
      setData(updateState);
      setFilteredData(updateState);
      setSelectedEquipo(equipoActualizadoDesdeBackend);
      toast.success('Equipo actualizado.', { id: toastId });
      return true;
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
      return false;
    }
  };

  const handleAddComponent = async (type: 'disco' | 'ram' | 'usuario', componentData: any) => {
    if (!selectedEquipo) return;
    const toastId = toast.loading(`Añadiendo ${type}...`);
    try {
      let serviceCall;
      switch (type) {
        case 'disco': serviceCall = equipoService.addDisco(selectedEquipo.id, componentData); break;
        case 'ram': serviceCall = equipoService.addRam(selectedEquipo.id, componentData); break;
        case 'usuario': serviceCall = equipoService.addUsuario(selectedEquipo.id, componentData); break;
        default: throw new Error('Tipo de componente no válido');
      }
      await serviceCall;
      const refreshedEquipo = await equipoService.getAll().then(equipos => equipos.find(e => e.id === selectedEquipo.id));
      if (!refreshedEquipo) throw new Error("No se pudo recargar el equipo");
      const updateState = (prev: Equipo[]) => prev.map(e => e.id === selectedEquipo.id ? refreshedEquipo : e);
      setData(updateState);
      setFilteredData(updateState);
      setSelectedEquipo(refreshedEquipo);
      await refreshHistory(selectedEquipo.hostname);
      toast.success(`${type.charAt(0).toUpperCase() + type.slice(1)} añadido.`, { id: toastId });
      setAddingComponent(null);
    } catch (error) {
      if (error instanceof Error) toast.error(error.message, { id: toastId });
    }
  };
  
  // --- DEFINICIÓN DE COLUMNAS CORREGIDA ---
  const columns: ColumnDef<Equipo>[] = [
    { header: "ID", accessorKey: "id", enableHiding: true },
    {
      header: "Nombre", accessorKey: "hostname",
      cell: (info: CellContext<Equipo, any>) => (<button onClick={() => setSelectedEquipo(info.row.original)} className={styles.hostnameButton}>{info.row.original.hostname}</button>)
    },
    { header: "IP", accessorKey: "ip" },
    { header: "MAC", accessorKey: "mac", enableHiding: true },
    { header: "Motherboard", accessorKey: "motherboard" },
    { header: "CPU", accessorKey: "cpu" },
    { header: "RAM", accessorKey: "ram_installed" },
    { header: "Discos", accessorFn: (row: Equipo) => row.discos?.map(d => `${d.mediatype} ${d.size}GB`).join(" | ") || "Sin discos" },
    { header: "OS", accessorKey: "os" },
    { header: "Arquitectura", accessorKey: "architecture" },
    {
      header: "Usuarios y Claves",
      cell: (info: CellContext<Equipo, any>) => {
        const { row } = info;
        const usuarios = row.original.usuarios || [];
        return (
          <div className={styles.userList}>
            {usuarios.map((u: UsuarioEquipoDetalle) => (
              <div key={u.id} className={styles.userItem}>
                <span className={styles.userInfo}>
                  U: {u.username} - C: {u.password || 'N/A'}
                </span>

                <div className={styles.userActions}>
                  <button
                    onClick={() => setModalPasswordData(u)}
                    className={styles.tableButton}
                    data-tooltip-id={`edit-${u.id}`}
                  >
                    ✏️
                    <Tooltip id={`edit-${u.id}`} className={styles.tooltip} place="top">Cambiar Clave</Tooltip>
                  </button>

                  <button
                    onClick={() => handleRemoveUser(row.original.hostname, u.username)}
                    className={styles.deleteUserButton}
                    data-tooltip-id={`remove-${u.id}`}
                  >
                    🗑️
                    <Tooltip id={`remove-${u.id}`} className={styles.tooltip} place="top">Eliminar Usuario</Tooltip>
                  </button>
                </div>
              </div>
            ))}
          </div>
        );
      }
    },
    {
      header: "Sector", id: 'sector', accessorFn: (row: Equipo) => row.sector?.nombre || 'Asignar',
      cell: (info: CellContext<Equipo, any>) => {
        const { row } = info;
        const sector = row.original.sector;
        return (
          <div className={styles.sectorContainer}>
            <span className={`${styles.sectorName} ${sector ? styles.sectorNameAssigned : styles.sectorNameUnassigned}`}>{sector?.nombre || 'Asignar'}</span>
            <button onClick={() => setModalData(row.original)} className={styles.tableButton} data-tooltip-id={`editSector-${row.original.id}`}>✏️<Tooltip id={`editSector-${row.original.id}`} className={styles.tooltip} place="top">Cambiar Sector</Tooltip></button>
          </div>
        );
      }
    }
  ];

  const table = useReactTable({
    data: filteredData,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    initialState: {
      sorting: [
        { id: 'sector', desc: false },
        { id: 'hostname', desc: false }
      ],
      columnVisibility: { id: false, mac: false },
      pagination: {
        pageSize: 15,
      },
    },
    state: {
      globalFilter,
    },
    onGlobalFilterChange: setGlobalFilter,
  });

  if (isLoading) {
    return (
      <div style={{ padding: '2rem', textAlign: 'center' }}>
        <h2>Cargando Equipos...</h2>
      </div>
    );
  }

  const PaginacionControles = (
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '1rem 0' }}>
      <div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
        <button onClick={() => table.setPageIndex(0)} disabled={!table.getCanPreviousPage()} className={styles.tableButton}>
          {'<<'}
        </button>
        <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()} className={styles.tableButton}>
          {'<'}
        </button>
        <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()} className={styles.tableButton}>
          {'>'}
        </button>
        <button onClick={() => table.setPageIndex(table.getPageCount() - 1)} disabled={!table.getCanNextPage()} className={styles.tableButton}>
          {'>>'}
        </button>
      </div>
      <span>
        Página{' '}
        <strong>
          {table.getState().pagination.pageIndex + 1} de {table.getPageCount()}
        </strong>
      </span>
      <div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
        <span>| Ir a pág:</span>
        <input
          type="number"
          defaultValue={table.getState().pagination.pageIndex + 1}
          onChange={e => {
            const page = e.target.value ? Number(e.target.value) - 1 : 0;
            table.setPageIndex(page);
          }}
          style={{ width: '60px' }}
          className={styles.searchInput}
        />
        <select
          value={table.getState().pagination.pageSize}
          onChange={e => {
            table.setPageSize(Number(e.target.value));
          }}
          className={styles.sectorSelect}
        >
          {[10, 15, 25, 50, 100].map(pageSize => (
            <option key={pageSize} value={pageSize}>
              Mostrar {pageSize}
            </option>
          ))}
        </select>
      </div>
    </div>
  );

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <h2>Equipos ({table.getFilteredRowModel().rows.length})</h2>
        <button
          className={`${styles.btn} ${styles.btnPrimary}`}
          onClick={() => setIsAddModalOpen(true)}
        >
          + Añadir Equipo
        </button>
      </div>
      <div className={styles.controlsContainer}>
        <input type="text" placeholder="Buscar en todos los campos..." value={globalFilter} onChange={(e) => setGlobalFilter(e.target.value)} className={styles.searchInput} style={{ width: '300px' }} />
        <b>Sector:</b>
        <select value={selectedSector} onChange={handleSectorChange} className={styles.sectorSelect}>
          <option value="Todos">-Todos-</option>
          <option value="Asignar">-Asignar-</option>
          {sectores.map(s => (<option key={s.id} value={s.nombre}>{s.nombre}</option>))}
        </select>
      </div>
      <div><p style={{ fontSize: '12px', fontWeight: 'bold' }}>** La Tabla permite ordenar por multiple columnas manteniendo shift al hacer click en la cabecera. **</p></div>

      {PaginacionControles}
      <div style={{ overflowX: 'auto', maxHeight: '70vh', border: '1px solid #dee2e6', borderRadius: '8px' }}>
        <table className={styles.table}>
          <thead>
            {table.getHeaderGroups().map(hg => (
              <tr key={hg.id}>
                {hg.headers.map(h => (
                  <th key={h.id} className={styles.th} onClick={h.column.getToggleSortingHandler()}>
                    {flexRender(h.column.columnDef.header, h.getContext())}
                    {h.column.getIsSorted() && (<span className={styles.sortIndicator}>{h.column.getIsSorted() === 'asc' ? '⇑' : '⇓'}</span>)}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.map(row => (
              <tr key={row.id} className={styles.tr}>
                {row.getVisibleCells().map(cell => (
                  <td key={cell.id} className={styles.td}>
                    {flexRender(cell.column.columnDef.cell, cell.getContext())}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {PaginacionControles}

      {showScrollButton && (<button onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} className={styles.scrollToTop} title="Volver arriba">↑</button>)}

      {modalData && <ModalEditarSector modalData={modalData} setModalData={setModalData} sectores={sectores} onClose={() => setModalData(null)} onSave={handleSave} />}

      {modalPasswordData && <ModalCambiarClave usuario={modalPasswordData} onClose={() => setModalPasswordData(null)} onSave={handleSavePassword} />}

      {selectedEquipo && (
        <ModalDetallesEquipo
          equipo={selectedEquipo}
          isOnline={isOnline}
          historial={historial}
          onClose={handleCloseModal}
          onDelete={handleDelete}
          onRemoveAssociation={handleRemoveAssociation}
          onEdit={handleEditEquipo}
          sectores={sectores}
          onAddComponent={type => setAddingComponent(type)}
          isChildModalOpen={addingComponent !== null}
        />
      )}

      {isAddModalOpen && <ModalAnadirEquipo sectores={sectores} onClose={() => setIsAddModalOpen(false)} onSave={handleCreateEquipo} />}

      {addingComponent === 'disco' && <ModalAnadirDisco onClose={() => setAddingComponent(null)} onSave={(data: { mediatype: string, size: number }) => handleAddComponent('disco', data)} />}

      {addingComponent === 'ram' && <ModalAnadirRam onClose={() => setAddingComponent(null)} onSave={(data: { slot: string, tamano: number, fabricante?: string, velocidad?: number }) => handleAddComponent('ram', data)} />}

      {addingComponent === 'usuario' && <ModalAnadirUsuario onClose={() => setAddingComponent(null)} onSave={(data: { username: string }) => handleAddComponent('usuario', data)} />}
    </div>
  );
};

export default SimpleTable;