'use client';

import type { IRoleItem } from 'src/contexts/types/role';
import type {
  GridSlots,
  GridColDef,
  GridRowSelectionModel,
  GridColumnVisibilityModel,
  GridSortModel,
  GridPaginationModel,
} from '@mui/x-data-grid';

import axios from 'axios';
import Link from 'next/link';
import { useState, useEffect, useCallback, useMemo } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEye, faPen, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons';

import Card from '@mui/material/Card';
import Button from '@mui/material/Button';
import { Box, Tooltip, IconButton } from '@mui/material';
import { DataGrid, gridClasses } from '@mui/x-data-grid';

import { paths } from 'src/routes/paths';

import { useBoolean } from 'src/hooks/use-boolean';

import { endpoints } from 'src/utils/axios';

import { GATEWAY_API_URL } from 'src/config-global';
import { SearchRolesParams, useRoleStore } from 'src/shared/api/stores/roleStore';
import { DashboardContent } from 'src/shared/layouts/dashboard';

import { toast } from 'src/shared/components/snackbar';
import { EmptyContent } from 'src/shared/components/empty-content';
import { ConfirmDialog } from 'src/shared/components/custom-dialog';
import { CustomBreadcrumbs } from 'src/shared/components/custom-breadcrumbs';

import CustomToolbar from '../components/CustomToolbar';
import CustomColumnHeader from '../components/CustomColumnHeader';
import { UserRoleDetailsDrawer } from '../user-role-details-view';
import {
  RenderCellName,
  RenderCellCreatedAt,
  RenderCellDescription,
} from '../components/RenderCells';

// ----------------------------------------------------------------------

// Define TABLE_HEAD
const TABLE_HEAD = [
  { id: 'name', label: 'Nom du rôle', width: 180 },
  { id: 'description', label: 'Description', width: 500 },
  { id: 'createdAt', label: 'Date de création', width: 250 },
  { id: 'actions', label: 'Actions', width: 100 },
];

const HIDE_COLUMNS_TOGGLABLE = ['category', 'actions'];

// Debounce hook
function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

// ----------------------------------------------------------------------

export function UserRoleListView() {
  const confirmRows = useBoolean();
  const confirmDelete = useBoolean();
  const roleAssignedWarning = useBoolean();

  const [selectedRowIds, setSelectedRowIds] = useState<GridRowSelectionModel>([]);
  const [filterButtonEl, setFilterButtonEl] = useState<HTMLButtonElement | null>(null);
  const [columnVisibilityModel, setColumnVisibilityModel] = useState<GridColumnVisibilityModel>({});
  const [openDetailsDialog, setOpenDetailsDialog] = useState(false);
  const [selectedRoleDetails, setSelectedRoleDetails] = useState<IRoleItem | null>(null);
  const [roleToDelete, setRoleToDelete] = useState<IRoleItem | null>(null);

  // États pour la pagination
  const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
    page: 0,
    pageSize: 10,
  });

  // État pour le tri - initialiser avec un tri par défaut
  const [sortModel, setSortModel] = useState<GridSortModel>([{ field: 'createdAt', sort: 'desc' }]);

  // États pour les filtres de recherche
  const [searchFilters, setSearchFilters] = useState({
    name: '',
    description: '',
    createdAt: null as Date | null,
  });

  const { getAllRoles, deleteRole, roles, loading, totalElements } = useRoleStore();

  const debouncedSearchFilters = useDebounce(searchFilters, 500);

  const searchParams = useMemo(() => {
    const params: SearchRolesParams = {
      page: paginationModel.page,
      size: paginationModel.pageSize,
    };

    if (debouncedSearchFilters.name.trim()) {
      params.name = debouncedSearchFilters.name.trim();
    }

    if (debouncedSearchFilters.description.trim()) {
      params.description = debouncedSearchFilters.description.trim();
    }

    if (debouncedSearchFilters.createdAt) {
      const date = new Date(debouncedSearchFilters.createdAt);
      if (!Number.isNaN(date.getTime())) {
        params.createdAt = date.toISOString().split('T')[0];
      }
    }

    if (sortModel.length > 0) {
      const sort = sortModel[0];
      params.sortBy = sort.field;
      params.sortDirection = sort.sort === 'asc' ? 'asc' : 'desc';
    }

    return params;
  }, [debouncedSearchFilters, paginationModel, sortModel]);

  const fetchAllData = useCallback(
    async (params: SearchRolesParams) => {
      try {
        await getAllRoles(params);
      } catch (error) {
        console.error('Error fetching data:', error);
        toast.error('Erreur lors du chargement des données');
      }
    },
    [getAllRoles]
  );

  useEffect(() => {
    fetchAllData(searchParams);
  }, [searchParams, fetchAllData]);

  const handleColumnSearch = useCallback((field: keyof IRoleItem, value: string | Date | null) => {
    setSearchFilters((prev) => ({
      ...prev,
      [field]: value || (field === 'createdAt' ? null : ''),
    }));
    setPaginationModel((prev) => ({ ...prev, page: 0 }));
  }, []);

  const handleSortModelChange = useCallback((newSortModel: GridSortModel) => {
    setSortModel(newSortModel);
    setPaginationModel((prev) => ({ ...prev, page: 0 }));
  }, []);

  const handlePaginationModelChange = useCallback((newPaginationModel: GridPaginationModel) => {
    setPaginationModel(newPaginationModel);
  }, []);

  const checkRoleIsAssigned = useCallback(async (id: string) => {
    try {
      const response = await axios({
        method: 'get',
        url: `${GATEWAY_API_URL}${endpoints.role.isAssigned.replace('id', id)}`,
        headers: { 'Content-Type': 'application/json' },
      });
      console.log('i am front isassigned', response.data);
      return response.data;
    } catch (error) {
      console.error('Error checking if role is assigned:', error);
      toast.error('Erreur lors de la vérification du rôle');
      return true;
    }
  }, []);

  const handleDeleteRow = useCallback(
    async (id: number) => {
      const role = roles.find((row) => row.id === id);
      if (role) {
        setRoleToDelete(role);
        try {
          const isAssigned = await checkRoleIsAssigned(id.toString());

          if (isAssigned) {
            roleAssignedWarning.onTrue();
          } else {
            confirmDelete.onTrue();
          }
        } catch (error) {
          console.error('Error:', error);
        }
      }
    },
    [roles, confirmDelete, roleAssignedWarning, checkRoleIsAssigned]
  );

  const deleteRow = useCallback(async () => {
    if (roleToDelete) {
      try {
        await deleteRole(roleToDelete.id);
        toast.success('Rôle supprimé avec succès!');
        fetchAllData(searchParams);
      } catch (error) {
        console.error('Error deleting role:', error);
        toast.error('Erreur lors de la suppression du rôle');
      } finally {
        confirmDelete.onFalse();
        setRoleToDelete(null);
      }
    }
  }, [roleToDelete, deleteRole, confirmDelete, fetchAllData, searchParams]);

  const handleViewRow = useCallback(
    (id: number) => {
      const selectedRole = roles.find((row) => row.id === id);
      if (selectedRole) {
        setSelectedRoleDetails(selectedRole);
        setOpenDetailsDialog(true);
      }
    },
    [roles]
  );

  const handleExportSelectedRows = useCallback(() => {
    const selectedRows = roles.filter((row) => selectedRowIds.includes(row.id));

    const csvContent = `data:text/csv;charset=utf-8,${selectedRows
      .map((row) => Object.values(row).join(','))
      .join('\n')}`;

    const encodedUri = encodeURI(csvContent);
    const link = document.createElement('a');
    link.setAttribute('href', encodedUri);
    link.setAttribute('download', 'rôles_sélectionnées.csv');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    toast.success('Les lignes sélectionnées ont été exportées avec succès!');
  }, [selectedRowIds, roles]);

  const CustomToolbarCallback = useCallback(
    () => <CustomToolbar setFilterButtonEl={setFilterButtonEl} />,
    []
  );

  const columns: GridColDef[] = [
    {
      field: 'name',
      headerName: TABLE_HEAD[0].label,
      width: TABLE_HEAD[0].width,
      hideable: false,
      sortable: true,
      renderHeader: (params) => (
        <CustomColumnHeader
          field="name"
          headerName={TABLE_HEAD[0].label}
          onSearch={handleColumnSearch}
          currentValue={searchFilters.name}
        />
      ),
      renderCell: (params) => (
        <RenderCellName params={params} onViewRow={() => handleViewRow(params.row.id)} />
      ),
    },
    {
      field: 'description',
      headerName: TABLE_HEAD[1].label,
      width: TABLE_HEAD[1].width,
      sortable: true,
      renderHeader: (params) => (
        <CustomColumnHeader
          field="description"
          headerName={TABLE_HEAD[1].label}
          onSearch={handleColumnSearch}
          currentValue={searchFilters.description}
        />
      ),
      renderCell: (params) => <RenderCellDescription params={params} />,
    },
    {
      field: 'createdAt',
      headerName: TABLE_HEAD[2].label,
      width: TABLE_HEAD[2].width,
      sortable: true,
      renderHeader: (params) => (
        <CustomColumnHeader
          field="createdAt"
          headerName={TABLE_HEAD[2].label}
          onSearch={handleColumnSearch}
          isDatePicker
          currentValue={searchFilters.createdAt}
        />
      ),
      renderCell: (params) => <RenderCellCreatedAt params={params} />,
    },
    {
      field: 'actions',
      headerName: TABLE_HEAD[3].label,
      width: TABLE_HEAD[3].width,
      align: 'center',
      headerAlign: 'center',
      sortable: false,
      filterable: false,
      disableColumnMenu: true,
      renderCell: (params) => (
        <Box sx={{ display: 'flex', gap: 1, zIndex: 1, position: 'sticky' }}>
          <Tooltip title="Voir détails">
            <IconButton size="small" onClick={() => handleViewRow(params.row.id)} color="info">
              <FontAwesomeIcon icon={faEye} />
            </IconButton>
          </Tooltip>
          <Tooltip title="Modifier">
            <Link href={paths.dashboard.users.edit(params.row.id)}>
              <IconButton
                size="small"
                onClick={(e) => {
                  e.stopPropagation();
                }}
                color="primary"
              >
                <FontAwesomeIcon icon={faPen} />
              </IconButton>
            </Link>
          </Tooltip>
          <Tooltip title="Supprimer">
            <IconButton
              size="small"
              onClick={() => handleDeleteRow(params.row.id)}
              color="error"
              disabled={loading}
            >
              <FontAwesomeIcon icon={faTrash} />
            </IconButton>
          </Tooltip>
        </Box>
      ),
    },
  ];

  const getTogglableColumns = () =>
    columns
      .filter((column) => !HIDE_COLUMNS_TOGGLABLE.includes(column.field))
      .map((column) => column.field);

  return (
    <>
      <DashboardContent sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column' }}>
        <CustomBreadcrumbs
          heading="Liste des rôles"
          links={[
            { name: 'Tableau de bord', href: paths.dashboard.root },
            { name: 'Utilisateurs', href: paths.dashboard.root },
            { name: 'Gestion des rôles' },
          ]}
          action={
            <Link href={paths.dashboard.users.add}>
              <Button
                variant="contained"
                startIcon={<FontAwesomeIcon icon={faPlus} />}
                sx={{
                  color: 'primary.contrastText',
                  backgroundColor: 'primary.main',
                  '&:hover': {
                    backgroundColor: 'primary.dark',
                  },
                }}
              >
                Ajouter un rôle
              </Button>
            </Link>
          }
          sx={{ mb: { xs: 3, md: 5 } }}
        />

        <Card
          sx={{
            flexGrow: { md: 1 },
            display: { md: 'flex' },
            height: { xs: 800, md: 2 },
            flexDirection: { md: 'column' },
          }}
        >
          <DataGrid
            localeText={{
              toolbarColumns: 'Colonnes',
              toolbarColumnsLabel: 'Sélectionner les colonnes',
              toolbarFilters: '',
              toolbarFiltersLabel: 'Afficher les filtres',
              toolbarFiltersTooltipHide: 'Masquer les filtres',
              toolbarFiltersTooltipShow: 'Afficher les filtres',
              toolbarExport: '',
              toolbarDensity: 'Densité',
              filterPanelOperator: 'Opérateur',
              filterPanelInputLabel: 'Valeur',
              filterOperatorContains: 'Contient',
              filterOperatorEquals: 'Égal à',
              filterOperatorStartsWith: 'Commence par',
              filterOperatorEndsWith: 'Se termine par',
              filterOperatorIsEmpty: 'Est vide',
              filterOperatorIsNotEmpty: "N'est pas vide",
              filterOperatorIsAnyOf: "Est l'un des",
              filterOperatorAfter: 'Après',
              filterOperatorBefore: 'Avant',
              filterOperatorOnOrAfter: 'Le ou après',
              filterOperatorOnOrBefore: 'Le ou avant',
              filterPanelInputPlaceholder: 'Valeur du filtre',
              columnMenuShowColumns: 'Afficher les colonnes',
              columnMenuUnsort: 'Annuler le tri',
              columnMenuSortAsc: 'Trier par ordre croissant',
              columnMenuSortDesc: 'Trier par ordre décroissant',
              filterPanelAddFilter: 'Ajouter un filtre',
              columnMenuFilter: 'Filtrer',
              footerRowSelected: (count) => `${count} ligne(s) sélectionnée(s)`,
              footerTotalRows: 'Total des lignes',
              footerTotalVisibleRows: (visibleCount, totalCounts) =>
                `${visibleCount.toLocaleString()} sur ${totalCounts.toLocaleString()}`,
              noRowsLabel: 'Aucune ligne',
              noResultsOverlayLabel: 'Aucun résultat trouvé',
              toolbarQuickFilterPlaceholder: 'Recherche...',
              toolbarQuickFilterLabel: 'Recherche',
              toolbarQuickFilterDeleteIconLabel: 'Effacer',
              toolbarExportLabel: 'Exporter',
              toolbarExportCSV: 'Télécharger au format CSV',
              toolbarExportExcel: 'Télécharger au format Excel',
              columnsManagementSearchTitle: 'Recherche',
              columnsManagementNoColumns: 'Aucune colonne',
              columnsManagementShowHideAllText: 'Afficher/Masquer tout',
              columnsManagementReset: 'Réinitialiser',
              MuiTablePagination: {
                labelRowsPerPage: 'Lignes par page :',
                labelDisplayedRows: ({ from, to, count }) => `${from}–${to} sur ${count}`,
              },
            }}
            checkboxSelection
            disableRowSelectionOnClick
            rows={roles}
            columns={columns}
            getRowHeight={() => 'auto'}
            // Configuration de la pagination côté serveur
            pagination
            paginationMode="server"
            paginationModel={paginationModel}
            onPaginationModelChange={handlePaginationModelChange}
            pageSizeOptions={[5, 10, 25, 50]}
            rowCount={totalElements || 0}
            // Configuration du tri côté serveur
            sortingMode="server"
            sortModel={sortModel}
            onSortModelChange={handleSortModelChange}
            // État initial avec tri par défaut
            initialState={{
              pagination: { paginationModel: { pageSize: 10 } },
              sorting: {
                sortModel: [{ field: 'createdAt', sort: 'desc' }],
              },
            }}
            onRowSelectionModelChange={(newSelectionModel) => setSelectedRowIds(newSelectionModel)}
            columnVisibilityModel={columnVisibilityModel}
            onColumnVisibilityModelChange={(newModel) => setColumnVisibilityModel(newModel)}
            slots={{
              toolbar: CustomToolbarCallback as GridSlots['toolbar'],
              noRowsOverlay: () => <EmptyContent />,
              noResultsOverlay: () => <EmptyContent title="Aucun résultat trouvé" />,
            }}
            slotProps={{
              panel: { anchorEl: filterButtonEl },
              toolbar: { setFilterButtonEl },
              columnsManagement: { getTogglableColumns },
            }}
            loading={loading}
            sx={{
              [`& .${gridClasses.cell}`]: { alignItems: 'center', display: 'inline-flex' },
              '& .MuiDataGrid-row': {
                paddingBottom: '12px',
              },
            }}
          />
        </Card>
      </DashboardContent>

      <UserRoleDetailsDrawer
        open={openDetailsDialog}
        onClose={() => setOpenDetailsDialog(false)}
        role={selectedRoleDetails}
      />

      <ConfirmDialog
        open={confirmDelete.value}
        onClose={confirmDelete.onFalse}
        title={`Supprimer le rôle : ${roleToDelete?.name || ''}`}
        content="Êtes-vous sûr de vouloir supprimer ce rôle ?"
        action={
          <Button variant="contained" color="error" onClick={deleteRow} disabled={loading}>
            Supprimer
          </Button>
        }
      />

      <ConfirmDialog
        open={roleAssignedWarning.value}
        onClose={roleAssignedWarning.onFalse}
        title="Impossible de supprimer"
        content={
          <>
            Le rôle <strong>{roleToDelete?.name}</strong> est assigné à un ou plusieurs
            utilisateurs.
            <br />
            Veuillez retirer ce rôle des utilisateurs avant de le supprimer.
          </>
        }
        action={
          <Button variant="contained" onClick={roleAssignedWarning.onFalse}>
            Compris
          </Button>
        }
      />
    </>
  );
}
