'use client';

/**
 * Módulos do sistema — listagem operacional (padrão guia-listagens).
 * @route /projetos/[id]/estrutura/modulos
 */
import React, { useCallback, useMemo, useState } from 'react';
import { useParams, usePathname, useRouter, useSearchParams } from 'next/navigation';
import {
    Alert,
    Badge,
    Button,
    Form,
    Input,
    Modal,
    Select,
    Space,
    Tag,
    Tooltip,
    Typography,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { Box, CheckCircle2, Filter, Pencil, Plus, Trash2, Upload } from 'lucide-react';
import { keepPreviousData } from '@tanstack/react-query';
import { ICON_SIZE_MD, iconTokenSize } from '@/components/icons';
import ProjetoLayout from '@/components/layouts/ProjetoLayout';
import { ButtonHeaderIcon } from '@/components/ui';
import MetricsGrid from '@/components/layouts/MetricsGrid';
import MetricCard from '@/components/layouts/MetricCard';
import { ListPageLayout } from '@/components/layouts/ListPageLayout';
import {
    FILTROS_MODAL_TAB_KEY,
    FiltrosModalFooterPadrao,
    FiltrosModalTabsTitulo,
    ListPageCreateFloatButton,
    ListagemEmptyState,
    ListagemListaError,
    ListingActionsColumnCell,
    ListingBulkFabModal,
    ListingColumnCustomizeModal,
    ListingFiltersTab,
    ListingPageOptionsButton,
    ListingPageOptionsModal,
    ListingSavedFiltersSection,
    SavedFilterActiveTag,
    buildListingRowInteractiveProps,
    listingServerSortNoOp,
    useListingMobileScrollHint,
    useListingVisibleColumns,
    type FiltrosModalTabsTituloActiveKey,
    type ListingColumnCatalogEntry,
} from '@/components/listings';
import { ModuleRelatedLinksPanel } from '@/components/navigation/ModuleRelatedLinksPanel';
import { TableScrollWrapper } from '@/components/tables/TableScrollWrapper';
import { LazyDataTable, LazyExportButton } from '@/components/lazy';
import { confirmDialog } from '@/lib/feedback/confirmDialog';
import { message } from '@/lib/feedback/message';
import { useQueryCache } from '@/hooks/useQueryCache';
import { useMutationCache } from '@/hooks/useMutationCache';
import { useProjetoWriteGates } from '@/features/projetos/hooks/useProjetoWriteGates';
import { ProjetoEntidadeImportCsvModal } from '@/features/projetos/importacao-csv';
import { useListingFilteredRowSelection } from '@/hooks/useListingFilteredRowSelection';
import { useListingBulkActionsModal } from '@/hooks/useListingBulkActionsModal';
import { usePaginatedResponseFallback } from '@/hooks/usePaginatedResponseFallback';
import {
    listingSortColumnUi,
    useServerSideListingTableChange,
    type ServerSideSortState,
} from '@/hooks/useServerSideListingTableChange';
import { useDebouncedValue } from '@/hooks/useDebouncedValue';
import { useIsMobile } from '@/hooks/useIsMobile';
import { useModuleRelatedLinks } from '@/hooks/useModuleRelatedLinks';
import { useWaygestFormModalProps } from '@/hooks/useWaygestFormModalProps';
import { queryKeys } from '@/lib/cache/queryKeys';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import apiClient from '@/lib/api/client';
import { getLaravelApiErrorMessage } from '@/lib/api/laravelApiErrorMessage';
import { detailPageQueryErrorSubTitle } from '@/lib/utils/detailPageQueryErrorSubTitle';
import { projetosProjetoCanonical } from '@/lib/routes/projetosProjetoCanonical';
import headerIconStyles from '@/components/ui/buttons/ButtonHeaderIcon/ButtonHeaderIcon.module.scss';
import type { ExportColumn } from '@/lib/utils/export';
import { STATUS_OPCOES } from './constants';
import { getModuloStatusColor, getModuloStatusLabel, hasModuloStatus } from './moduloDisplay';
import { ModuloFormModal } from './ModuloFormModal';
import type { ProjetoModulo, ProjetoModuloFormValues, ProjetoModuloListResponse } from './types';
import {
    PROJETOS_ESTRUTURA_MODULOS_LIST_MODULE_KEY,
    PROJETOS_ESTRUTURA_MODULOS_RELATED_SURFACE,
    estruturaModulosFiltrosFromPayload,
    estruturaModulosFiltrosToPayload,
} from './utils/estruturaModulosFiltrosPayload';
import {
    ESTRUTURA_MODULOS_LISTA_URL_DEFAULTS,
    ESTRUTURA_MODULOS_PER_PAGE_DEFAULT,
    type EstruturaModulosListaUrlSnapshot,
} from './utils/estruturaModulosListaFiltersUrl';
import { useEstruturaModulosListaUrlSync } from './hooks/useEstruturaModulosListaUrlSync';

const EXPORT_HELP =
    'Exporta apenas os registros visíveis nesta página (respeita filtros e paginação da listagem). Escolha o formato no passo seguinte.';

const EMPTY_MODULOS: ProjetoModulo[] = [];

const DEFAULT_SORT: Exclude<ServerSideSortState, null> = {
    columnKey: 'ordem',
    order: 'ascend',
};

const COLUMN_CATALOG: ListingColumnCatalogEntry[] = [
    { key: 'nome', label: 'Nome', ordem: 1, obrigatoria: true },
    { key: 'codigo', label: 'Código', ordem: 2, visivel_padrao: true },
    { key: 'status', label: 'Status', ordem: 3, visivel_padrao: true },
    { key: 'pai', label: 'Módulo pai', ordem: 4, visivel_padrao: true },
    { key: 'story_points', label: 'Story points', ordem: 5, visivel_padrao: false },
    { key: 'ordem', label: 'Ordem', ordem: 6, visivel_padrao: true },
];

function modulosListErrorDescription(queryError: unknown): string {
    const raw = detailPageQueryErrorSubTitle(queryError);
    if (/SQLSTATE|Unknown column|modulo_pai_id|QueryException/i.test(raw)) {
        return 'A base de dados ainda não tem a estrutura de módulos atualizada (hierarquia/documentação). Peça ao administrador para aplicar a migration do addon e tente novamente.';
    }
    return raw;
}

function routeSegmentId(params: ReturnType<typeof useParams>): string {
    const raw = params?.id;
    if (typeof raw === 'string') return raw;
    if (Array.isArray(raw)) return raw[0] ?? '';
    return '';
}

export interface ProjetoEstruturaModulosScreenProps {
    projetoId?: string;
}

export function ProjetoEstruturaModulosScreen({ projetoId: projetoIdProp }: ProjetoEstruturaModulosScreenProps = {}) {
    const params = useParams();
    const router = useRouter();
    const pathname = usePathname() ?? '';
    const searchParams = useSearchParams();
    const projetoId = projetoIdProp?.trim() || routeSegmentId(params);
    const isMobile = useIsMobile();
    const { canEditar, tooltipSemPermissao } = useProjetoWriteGates();
    const filtrosModalLayout = useWaygestFormModalProps();

    const [page, setPage] = useState(1);
    const [perPage, setPerPage] = useState(ESTRUTURA_MODULOS_PER_PAGE_DEFAULT);
    const [appliedBusca, setAppliedBusca] = useState('');
    const [appliedStatus, setAppliedStatus] = useState('');
    const [tableSort, setTableSort] = useState<ServerSideSortState>(null);
    const [filtrosModalOpen, setFiltrosModalOpen] = useState(false);
    const [filtrosModalTab, setFiltrosModalTab] = useState<FiltrosModalTabsTituloActiveKey>(
        FILTROS_MODAL_TAB_KEY.filtrar,
    );
    const [draftBusca, setDraftBusca] = useState('');
    const [draftStatus, setDraftStatus] = useState('');
    const [formModalOpen, setFormModalOpen] = useState(false);
    const [editingModulo, setEditingModulo] = useState<ProjetoModulo | null>(null);
    const [importCsvOpen, setImportCsvOpen] = useState(false);
    const [opcoesItem, setOpcoesItem] = useState<ProjetoModulo | null>(null);
    const [listaMaisOpcoesOpen, setListaMaisOpcoesOpen] = useState(false);
    const [colunasVisiveisModalOpen, setColunasVisiveisModalOpen] = useState(false);
    const [filtroSalvoAtivo, setFiltroSalvoAtivo] = useState<string | null>(null);
    const [bulkBusy, setBulkBusy] = useState(false);

    const debouncedBusca = useDebouncedValue(appliedBusca, 320);
    const { visibleKeys, columnOrder, setVisibleKeys } = useListingVisibleColumns(
        PROJETOS_ESTRUTURA_MODULOS_LIST_MODULE_KEY,
        COLUMN_CATALOG,
    );

    const snapshot: EstruturaModulosListaUrlSnapshot = useMemo(
        () => ({
            page,
            perPage,
            busca: appliedBusca,
            status: appliedStatus,
            tableSort,
        }),
        [page, perPage, appliedBusca, appliedStatus, tableSort],
    );

    const onHydrateFromUrl = useCallback((values: EstruturaModulosListaUrlSnapshot) => {
        setPage(values.page);
        setPerPage(values.perPage);
        setAppliedBusca(values.busca);
        setAppliedStatus(values.status);
        setTableSort(values.tableSort);
        setFiltroSalvoAtivo(null);
    }, []);

    useEstruturaModulosListaUrlSync({
        pathname,
        searchParams,
        snapshot,
        onHydrateFromUrl,
    });

    const apiSortBy = tableSort?.columnKey ?? DEFAULT_SORT.columnKey;
    const apiSortDir = (tableSort?.order ?? DEFAULT_SORT.order) === 'descend' ? 'desc' : 'asc';

    const listParams = useMemo(
        () => ({
            page,
            per_page: perPage,
            ...(debouncedBusca.trim() ? { busca: debouncedBusca.trim() } : {}),
            ...(appliedStatus ? { status: appliedStatus } : {}),
            sort_by: apiSortBy,
            sort_direction: apiSortDir,
        }),
        [page, perPage, debouncedBusca, appliedStatus, apiSortBy, apiSortDir],
    );

    const {
        data: modulosResponse,
        isLoading,
        isFetching,
        isError,
        error: queryError,
        refetch,
    } = useQueryCache<ProjetoModuloListResponse>({
        queryKey: queryKeys.projetos.modulosList(projetoId, listParams),
        endpoint: API_ENDPOINTS.projetos.modulos.index(projetoId),
        params: listParams,
        enabled: !!projetoId,
        staleTime: 1 * 60 * 1000,
        gcTime: 5 * 60 * 1000,
        placeholderData: keepPreviousData,
    });

    const paginatedData = usePaginatedResponseFallback<ProjetoModulo>(
        modulosResponse,
        perPage,
        EMPTY_MODULOS,
    );
    const listRows = paginatedData.data;
    const sortColumnUi = listingSortColumnUi(tableSort, DEFAULT_SORT);
    const handleTableChange = useServerSideListingTableChange({
        sortState: tableSort,
        setSortState: setTableSort,
        setPage,
        setPerPage,
    });

    const { rowSelection, selectedRowKeys, clearSelection } = useListingFilteredRowSelection(
        listRows,
        listRows.map((r: any) => r.id),
        bulkBusy,
        { serverPaginated: true },
    );

    const selectedIds = useMemo(
        () => selectedRowKeys.map((k) => Number(k)).filter((n) => Number.isFinite(n)),
        [selectedRowKeys],
    );

    const {
        modalOpen: modalAcoesMassaOpen,
        openModal: openModalAcoesMassa,
        closeModal: closeModalAcoesMassa,
        scheduleAfterClose: scheduleAfterMassModalClose,
    } = useListingBulkActionsModal({ selectedCount: selectedIds.length });

    const { modalActions: relatedNavActions } = useModuleRelatedLinks({
        surfaceKey: PROJETOS_ESTRUTURA_MODULOS_RELATED_SURFACE,
        pagePrefix: 'estrutura-modulos',
        modalOnClose: () => setListaMaisOpcoesOpen(false),
        projetoId,
    });

    const handleEditar = useCallback((item: ProjetoModulo) => {
        setEditingModulo(item);
        setFormModalOpen(true);
        setOpcoesItem(null);
    }, []);

    const handleGerenciar = useCallback(
        (item: ProjetoModulo) => {
            router.push(projetosProjetoCanonical.estruturaModulo(projetoId, item.id));
        },
        [router, projetoId],
    );

    const handleExcluir = useCallback(
        (item: ProjetoModulo) => {
            confirmDialog({
                title: 'Excluir módulo',
                content: `Deseja realmente excluir o módulo "${item.nome}"? Esta ação não pode ser desfeita.`,
                okText: 'Excluir',
                okType: 'danger',
                cancelText: 'Cancelar',
                onOk: async () => {
                    await apiClient.delete(API_ENDPOINTS.projetos.modulos.destroy(projetoId, item.id));
                    message.success('Módulo excluído com sucesso.');
                    setOpcoesItem(null);
                    clearSelection();
                    void refetch();
                },
            });
        },
        [projetoId, refetch, clearSelection],
    );

    const execBulkExcluir = useCallback(async () => {
        if (selectedIds.length === 0) return;
        setBulkBusy(true);
        try {
            const results = await Promise.allSettled(
                selectedIds.map((id) => apiClient.delete(API_ENDPOINTS.projetos.modulos.destroy(projetoId, id))),
            );
            const ok = results.filter((r: any) => r.status === 'fulfilled').length;
            const fail = results.length - ok;
            clearSelection();
            await refetch();
            if (ok > 0 && fail === 0) {
                message.success(ok === 1 ? 'Módulo excluído.' : `${ok} módulos excluídos.`);
                return;
            }
            if (ok > 0 && fail > 0) {
                message.warning(`${ok} excluído(s), ${fail} falharam.`);
                return;
            }
            message.error('Não foi possível excluir os módulos selecionados.');
        } finally {
            setBulkBusy(false);
        }
    }, [selectedIds, projetoId, clearSelection, refetch]);

    const saveMutation = useMutationCache({
        endpoint: editingModulo
            ? API_ENDPOINTS.projetos.modulos.update(projetoId, editingModulo.id)
            : API_ENDPOINTS.projetos.modulos.store(projetoId),
        method: editingModulo ? 'PUT' : 'POST',
        invalidateQueries: [queryKeys.projetos.modulos(projetoId)],
        onSuccess: () => {
            message.success(
                editingModulo ? 'Módulo atualizado com sucesso!' : 'Módulo cadastrado com sucesso!',
            );
            setFormModalOpen(false);
            setEditingModulo(null);
            void refetch();
        },
        onError: (error: unknown) => {
            message.error(getLaravelApiErrorMessage(error, 'Erro ao salvar módulo'));
        },
    });

    const handleNovoModulo = () => {
        if (!canEditar) {
            message.warning(tooltipSemPermissao || 'Sem permissão para cadastrar módulos');
            return;
        }
        setEditingModulo(null);
        setFormModalOpen(true);
    };

    const filtrosAtivosCount = (appliedBusca.trim() ? 1 : 0) + (appliedStatus ? 1 : 0);
    const filtrosComAlgumAtivo = filtrosAtivosCount > 0;

    const abrirModalFiltros = () => {
        setDraftBusca(appliedBusca);
        setDraftStatus(appliedStatus);
        setFiltrosModalTab(FILTROS_MODAL_TAB_KEY.filtrar);
        setFiltrosModalOpen(true);
    };

    const aplicarFiltrosModal = () => {
        setAppliedBusca(draftBusca);
        setAppliedStatus(draftStatus);
        setPage(1);
        setFiltrosModalOpen(false);
        setFiltroSalvoAtivo(null);
    };

    const limparTodosFiltros = () => {
        setAppliedBusca('');
        setAppliedStatus('');
        setDraftBusca('');
        setDraftStatus('');
        setPage(1);
        setTableSort(null);
        setFiltroSalvoAtivo(null);
        setFiltrosModalOpen(false);
    };

    const visibleSet = useMemo(() => new Set(visibleKeys), [visibleKeys]);
    const columns = useMemo((): ColumnsType<ProjetoModulo> => {
        const cols: ColumnsType<ProjetoModulo> = [
            {
                key: 'opcoes',
                title: '',
                width: 48,
                fixed: 'left',
                render: (_: unknown, record) => (
                    <ListingActionsColumnCell
                        ariaLabel={`Opções do módulo ${record.nome}`}
                        onOpen={(e) => {
                            e.stopPropagation();
                            setOpcoesItem(record);
                        }}
                    />
                ),
            },
        ];
        if (visibleSet.has('nome')) {
            cols.push({
                key: 'nome',
                dataIndex: 'nome',
                title: 'Nome',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'nome' ? sortColumnUi.order : undefined,
                render: (nome: string, record) => (
                    <Typography.Link onClick={() => handleGerenciar(record)}>{nome}</Typography.Link>
                ),
            });
        }
        if (visibleSet.has('codigo')) {
            cols.push({
                key: 'codigo',
                dataIndex: 'codigo',
                title: 'Código',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'codigo' ? sortColumnUi.order : undefined,
                render: (v: string | null) => v || '—',
            });
        }
        if (visibleSet.has('status')) {
            cols.push({
                key: 'status',
                dataIndex: 'status',
                title: 'Status',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'status' ? sortColumnUi.order : undefined,
                render: (status: string | null) =>
                    hasModuloStatus(status) ? (
                        <Tag color={getModuloStatusColor(status)}>{getModuloStatusLabel(status)}</Tag>
                    ) : (
                        '—'
                    ),
            });
        }
        if (visibleSet.has('pai')) {
            cols.push({
                key: 'pai',
                title: 'Módulo pai',
                render: (_: unknown, record) => record.pai?.nome || '—',
            });
        }
        if (visibleSet.has('story_points')) {
            cols.push({
                key: 'story_points',
                dataIndex: 'story_points',
                title: 'SP',
                align: 'right',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'story_points' ? sortColumnUi.order : undefined,
                render: (v: number | null) => (v != null ? v : '—'),
            });
        }
        if (visibleSet.has('ordem')) {
            cols.push({
                key: 'ordem',
                dataIndex: 'ordem',
                title: 'Ordem',
                align: 'right',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'ordem' ? sortColumnUi.order : undefined,
                render: (v: number | null) => (v != null ? v : '—'),
            });
        }
        return cols;
    }, [visibleSet, sortColumnUi, handleGerenciar]);

    const exportColumns: ExportColumn[] = [
        { key: 'nome', label: 'Nome' },
        { key: 'codigo', label: 'Código' },
        { key: 'status', label: 'Status' },
        { key: 'ordem', label: 'Ordem' },
    ];

    const total = paginatedData.meta?.total ?? listRows.length;
    const emDesenvolvimento = listRows.filter((m) => m.status === 'em_desenvolvimento').length;
    const concluidos = listRows.filter((m) => m.status === 'concluido').length;
    const showEmpty = !isLoading && !isError && total === 0;
    const tabelaScrollHint = useListingMobileScrollHint(
        'Deslize horizontalmente para ver todas as colunas.',
    );

    if (!projetoId) return null;

    const listingToolbar = (
        <Space wrap size={8} align="center">
            <ListingPageOptionsButton
                data-testid="estrutura-modulos-lista-mais-opcoes"
                expanded={listaMaisOpcoesOpen}
                onClick={() => setListaMaisOpcoesOpen(true)}
            />
            <Tooltip
                title={
                    filtrosComAlgumAtivo
                        ? 'Há filtros ativos — abra para alterar busca ou status.'
                        : 'Filtrar por nome e status'
                }
            >
                <span style={{ display: 'inline-block' }}>
                    <Badge dot={filtrosComAlgumAtivo} color="geekblue">
                        <ButtonHeaderIcon
                            icon={<Filter size={ICON_SIZE_MD} aria-hidden />}
                            aria-label="Abrir filtros"
                            data-testid="estrutura-modulos-abrir-filtros"
                            title={
                                filtrosAtivosCount > 0
                                    ? `Filtros (${filtrosAtivosCount})`
                                    : 'Filtros'
                            }
                            onClick={abrirModalFiltros}
                            className={headerIconStyles.btnHeaderIcon}
                        />
                    </Badge>
                </span>
            </Tooltip>
            <Tooltip title={EXPORT_HELP}>
                <span style={{ display: 'inline-block' }} data-testid="estrutura-modulos-exportar">
                    <LazyExportButton
                        data={listRows as unknown as Record<string, unknown>[]}
                        columns={exportColumns}
                        filename={`modulos-projeto-${projetoId}-pagina-${page}`}
                        title="Exportar"
                        iconOnly
                        size="large"
                        exportMenuMode="modal"
                        helpTooltip={EXPORT_HELP}
                        className={headerIconStyles.btnHeaderIcon}
                    />
                </span>
            </Tooltip>
            {canEditar ? (
                <Tooltip title="Importar módulos a partir de arquivo CSV (UTF-8)">
                    <span style={{ display: 'inline-block' }}>
                        <ButtonHeaderIcon
                            data-testid="estrutura-modulos-importar-csv"
                            icon={<Upload size={ICON_SIZE_MD} aria-hidden />}
                            title="Importar CSV"
                            aria-label="Importar módulos via CSV"
                            onClick={() => setImportCsvOpen(true)}
                            className={headerIconStyles.btnHeaderIcon}
                        />
                    </span>
                </Tooltip>
            ) : null}
        </Space>
    );

    return (
        <ProjetoLayout
            projetoId={projetoId}
            pageTitle="Módulos do sistema"
            showPageTitleIcon={false}
            titleSection="Módulos"
            breadcrumbItems={[
                { title: 'Projeto', path: `/projetos/${projetoId}` },
                { title: 'Desenvolvimento', path: `/projetos/${projetoId}/estrutura/modulos` },
                { title: 'Módulos' },
            ]}
            headerAction={!isMobile ? listingToolbar : undefined}
        >
            <ListPageLayout
                suppressPageHeader
                header={{ title: '' }}
                mobileInlineActions={isMobile ? listingToolbar : undefined}
                metrics={
                    <MetricsGrid columns={3} style={{ width: '100%', gap: 15, marginBottom: 0 }}>
                        <MetricCard
                            icon={<Box size={ICON_SIZE_MD} aria-hidden />}
                            label="Total"
                            value={isLoading ? '—' : total}
                            variant="projetos"
                            loading={isLoading}
                        />
                        <MetricCard
                            icon={<Pencil size={ICON_SIZE_MD} aria-hidden />}
                            label="Em desenvolvimento (página)"
                            value={isLoading ? '—' : emDesenvolvimento}
                            variant="projetos"
                            loading={isLoading}
                        />
                        <MetricCard
                            icon={<CheckCircle2 size={ICON_SIZE_MD} aria-hidden />}
                            label="Concluídos (página)"
                            value={isLoading ? '—' : concluidos}
                            variant="projetos"
                            loading={isLoading}
                        />
                    </MetricsGrid>
                }
                metricsWrapperStyle={{ marginBottom: 15 }}
                loading={isLoading && !modulosResponse}
                loadingTip="Carregando listagem…"
                onRefresh={() => void refetch()}
                refreshLoading={isFetching && !isLoading}
                mobileOnOpenFilters={abrirModalFiltros}
                onResetFilters={limparTodosFiltros}
                activeFiltersCount={filtrosAtivosCount}
                belowContent={
                    <ModuleRelatedLinksPanel
                        surfaceKey={PROJETOS_ESTRUTURA_MODULOS_RELATED_SURFACE}
                        variant="inline"
                        listPlacement="after"
                        pagePrefix="estrutura-modulos"
                        projetoId={projetoId}
                    />
                }
                content={
                    <>
                        {filtroSalvoAtivo ? (
                            <SavedFilterActiveTag nome={filtroSalvoAtivo} withLeadingBreak={false} />
                        ) : null}
                        {isError ? (
                            <ListagemListaError
                                message="Não foi possível carregar os módulos"
                                description={modulosListErrorDescription(queryError)}
                                onRetry={() => void refetch()}
                                data-testid="estrutura-modulos-lista-retry"
                            />
                        ) : null}
                        {filtrosComAlgumAtivo && !isError ? (
                            <Alert
                                type="info"
                                showIcon
                                style={{ marginBottom: 15 }}
                                message="Filtros ativos"
                                description={
                                    <Button type="link" onClick={limparTodosFiltros}>
                                        Limpar filtros
                                    </Button>
                                }
                            />
                        ) : null}
                        {showEmpty ? (
                            <ListagemEmptyState
                                type={filtrosComAlgumAtivo ? 'warning' : 'info'}
                                icon={<Box size={iconTokenSize.xl} aria-hidden />}
                                message={
                                    filtrosComAlgumAtivo
                                        ? 'Nenhum resultado para os filtros'
                                        : 'Nenhum módulo cadastrado'
                                }
                                description={
                                    filtrosComAlgumAtivo
                                        ? 'Ajuste os critérios ou limpe os filtros.'
                                        : canEditar
                                          ? 'Cadastre o primeiro módulo da arquitetura ou importe um arquivo CSV.'
                                          : 'Ainda não há módulos nesta arquitetura. Quem tiver permissão de edição pode cadastrar o primeiro ou importar CSV.'
                                }
                                {...(filtrosComAlgumAtivo
                                    ? {
                                          ctaLabel: 'Limpar filtros',
                                          onCta: limparTodosFiltros,
                                      }
                                    : canEditar
                                      ? {
                                            ctaLabel: 'Cadastrar módulo',
                                            onCta: handleNovoModulo,
                                        }
                                      : {})}
                                data-testid="estrutura-modulos-lista-empty"
                            />
                        ) : null}
                        {!isError && !showEmpty ? (
                            <TableScrollWrapper hint={tabelaScrollHint}>
                                <LazyDataTable
                                    ariaRegionLabel="Tabela de módulos do sistema"
                                    rowKey="id"
                                    columns={columns}
                                    paginatedData={paginatedData}
                                    loading={isLoading}
                                    fetching={isFetching}
                                    showRefresh={false}
                                    onChange={handleTableChange}
                                    onPageChange={(p: number, ps?: number) => {
                                        setPage(p);
                                        if (ps) setPerPage(ps);
                                    }}
                                    scroll={{ x: 'max-content' }}
                                    rowSelection={rowSelection}
                                    onRow={(record: ProjetoModulo) =>
                                        buildListingRowInteractiveProps(record, {
                                            onAtivate: (r) => handleGerenciar(r),
                                            getRowSummary: (r) => r.nome,
                                            ariaLabelWithSummary: (summary) =>
                                                `Módulo: ${summary}. Enter abre a gestão.`,
                                            ariaLabelFallback: 'Módulo. Enter abre a gestão.',
                                        })
                                    }
                                    autoMobileFromColumns={{
                                        testIdPrefix: 'estrutura-modulos',
                                        listHeading: 'Lista de módulos',
                                        getFallbackTitle: (record: any) => record.nome,
                                        onCardClick: handleGerenciar,
                                        onOpenOptions: (item) => setOpcoesItem(item),
                                    }}
                                />
                            </TableScrollWrapper>
                        ) : null}
                    </>
                }
            />

            {selectedRowKeys.length > 0 ? (
                <ListingBulkFabModal
                    showFab
                    modalOpen={modalAcoesMassaOpen}
                    onOpenModal={openModalAcoesMassa}
                    onCloseModal={closeModalAcoesMassa}
                    busy={bulkBusy}
                    modalTitle="Ações em massa"
                    fabAriaLabel="Ações em massa nos módulos selecionados"
                    actions={[
                        {
                            key: 'excluir',
                            label: 'Excluir selecionados',
                            danger: true,
                            disabled: !canEditar,
                            onClick: () =>
                                scheduleAfterMassModalClose(() => {
                                    confirmDialog({
                                        title: 'Excluir módulos selecionados',
                                        content: `Excluir ${selectedIds.length} módulo(s)? Esta ação não pode ser desfeita.`,
                                        okText: 'Excluir',
                                        okType: 'danger',
                                        cancelText: 'Cancelar',
                                        onOk: () => execBulkExcluir(),
                                    });
                                }),
                        },
                    ]}
                />
            ) : canEditar ? (
                <ListPageCreateFloatButton
                    title="Novo módulo"
                    aria-label="Novo módulo"
                    onClick={handleNovoModulo}
                />
            ) : null}

            <ListingPageOptionsModal
                open={listaMaisOpcoesOpen}
                onClose={() => setListaMaisOpcoesOpen(false)}
                subtitle="Módulos do sistema"
                onColunasVisiveis={() => {
                    setListaMaisOpcoesOpen(false);
                    setColunasVisiveisModalOpen(true);
                }}
                navigationActions={relatedNavActions}
                extraActions={
                    canEditar
                        ? [
                              {
                                  key: 'novo',
                                  label: 'Novo módulo',
                                  icon: <Plus size={ICON_SIZE_MD} aria-hidden />,
                                  onClick: () => {
                                      setListaMaisOpcoesOpen(false);
                                      handleNovoModulo();
                                  },
                              },
                          ]
                        : []
                }
                data-testid="estrutura-modulos-lista-opcoes-pagina-modal"
            />

            <ListingColumnCustomizeModal
                open={colunasVisiveisModalOpen}
                onClose={() => setColunasVisiveisModalOpen(false)}
                catalog={COLUMN_CATALOG}
                value={visibleKeys}
                order={columnOrder}
                onApply={setVisibleKeys}
                data-testid="estrutura-modulos-customizar-colunas-modal"
            />

            <Modal
                {...filtrosModalLayout}
                title={
                    <FiltrosModalTabsTitulo
                        activeKey={filtrosModalTab}
                        onChange={setFiltrosModalTab}
                    />
                }
                open={filtrosModalOpen}
                onCancel={() => setFiltrosModalOpen(false)}
                footer={
                    <FiltrosModalFooterPadrao
                        onLimparTodos={limparTodosFiltros}
                        onFechar={() => setFiltrosModalOpen(false)}
                        showFiltrarPrimary={filtrosModalTab === FILTROS_MODAL_TAB_KEY.filtrar}
                        onFiltrar={aplicarFiltrosModal}
                    />
                }
                data-testid="estrutura-modulos-filtros-modal"
            >
                {filtrosModalTab === FILTROS_MODAL_TAB_KEY.filtrar ? (
                    <Form layout="vertical">
                        <Form.Item label="Busca">
                            <Input
                                allowClear
                                value={draftBusca}
                                onChange={(e) => setDraftBusca(e.target.value)}
                                placeholder="Nome do módulo"
                            />
                        </Form.Item>
                        <Form.Item label="Status">
                            <Select
                                allowClear
                                placeholder="Todos"
                                value={draftStatus || undefined}
                                onChange={(v) => setDraftStatus(v ?? '')}
                                options={STATUS_OPCOES}
                            />
                        </Form.Item>
                        <ListingSavedFiltersSection
                            moduleKey={PROJETOS_ESTRUTURA_MODULOS_LIST_MODULE_KEY}
                            enabled
                            snapshotKey={`${draftBusca}|${draftStatus}`}
                            buildPayload={() =>
                                estruturaModulosFiltrosToPayload({
                                    busca: draftBusca,
                                    status: draftStatus,
                                })
                            }
                            dataTestIdPrefix="estrutura-modulos"
                        />
                    </Form>
                ) : (
                    <ListingFiltersTab
                        moduleKey={PROJETOS_ESTRUTURA_MODULOS_LIST_MODULE_KEY}
                        enabled
                        onApplySaved={(payload, meta) => {
                            const next = estruturaModulosFiltrosFromPayload(payload);
                            setAppliedBusca(next.busca);
                            setAppliedStatus(next.status);
                            setPage(1);
                            setFiltrosModalOpen(false);
                            setFiltroSalvoAtivo(meta.nome);
                        }}
                        dataTestId="estrutura-modulos-filtros-meus-filtros-tab"
                    />
                )}
            </Modal>

            <Modal
                title={opcoesItem ? `Opções — ${opcoesItem.nome}` : 'Opções'}
                open={!!opcoesItem}
                onCancel={() => setOpcoesItem(null)}
                footer={null}
                data-testid="estrutura-modulos-row-opcoes-modal"
            >
                {opcoesItem ? (
                    <Space direction="vertical" style={{ width: '100%' }}>
                        <Button block onClick={() => handleGerenciar(opcoesItem)}>
                            Abrir gestão
                        </Button>
                        <Button
                            block
                            disabled={!canEditar}
                            onClick={() => handleEditar(opcoesItem)}
                        >
                            Editar
                        </Button>
                        <Button
                            block
                            danger
                            disabled={!canEditar}
                            onClick={() => handleExcluir(opcoesItem)}
                        >
                            Excluir
                        </Button>
                    </Space>
                ) : null}
            </Modal>

            <ModuloFormModal
                open={formModalOpen}
                onClose={() => {
                    setFormModalOpen(false);
                    setEditingModulo(null);
                }}
                onSubmit={(values: ProjetoModuloFormValues) => saveMutation.mutate(values)}
                loading={saveMutation.isPending}
                modulo={editingModulo}
                modulos={listRows}
            />

            <ProjetoEntidadeImportCsvModal
                open={importCsvOpen}
                onClose={() => setImportCsvOpen(false)}
                onSuccess={() => {
                    void refetch();
                }}
                projetoId={projetoId}
                kind="modulos"
            />
        </ProjetoLayout>
    );
}
