'use client';

import { confirmDialog } from '@/lib/feedback/confirmDialog';
import { message } from '@/lib/feedback/message';
import { keepPreviousData } from '@tanstack/react-query';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useParams, usePathname, useRouter, useSearchParams } from 'next/navigation';
import { CheckCircle2, CirclePlay, Filter, Plus, Rocket, Trash2 } from 'lucide-react';
import { Alert, Badge, Button, Grid, Space, Tooltip, Typography } from 'antd';
import { ICON_SIZE_MD, iconTokenSize } from '@/components/icons';
import type { ColumnsType } from 'antd/es/table';
import type { ModalOpcaoAction } from '@/components/ModalOpcoesBase';
import { useQueryCache } from '@/hooks/useQueryCache';
import { useMutationCache } from '@/hooks/useMutationCache';
import {
    mergeWaygestFormModalBodyStyles,
    useWaygestFormModalProps,
} from '@/hooks/useWaygestFormModalProps';
import { useListingFilteredRowSelection } from '@/hooks/useListingFilteredRowSelection';
import {
    listingSortColumnUi,
    useServerSideListingTableChange,
    type ServerSideSortState,
} from '@/hooks/useServerSideListingTableChange';
import { usePaginatedResponseFallback } from '@/hooks/usePaginatedResponseFallback';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import { queryKeys } from '@/lib/cache/queryKeys';
import apiClient from '@/lib/api/client';
import { getLaravelApiErrorMessage } from '@/lib/api/laravelApiErrorMessage';
import { formatDate } from '@/lib/utils/export';
import type { PaginatedResponse, Sprint } from '@/types';
import ProjetoLayout from '@/components/layouts/ProjetoLayout';
import MetricsGrid from '@/components/layouts/MetricsGrid';
import MetricCard from '@/components/layouts/MetricCard';
import { ButtonHeaderIcon } from '@/components/ui';
import {
    ListPageCreateFloatButton,
    ListagemEmptyState,
    ListagemListaError,
    ListingActionsColumnCell,
    ListingBulkFabModal,
    ListingColumnCustomizeModal,
    ListingPageOptionsButton,
    ListingPageOptionsModal,
    SavedFilterActiveTag,
    buildListingRowInteractiveProps,
    filterTableColumnsByVisibleKeys,
    listingServerSortNoOp,
    useListingVisibleColumns,
    useListingMobileScrollHint,
} from '@/components/listings';
import { LazyDataTable, LazyExportButton } from '@/components/lazy';
import { TableScrollWrapper } from '@/components/tables/TableScrollWrapper';
import btnHeaderStyles from '@/components/ui/buttons/ButtonHeaderIcon/ButtonHeaderIcon.module.scss';
import {
    projetoPlanejamentoSprintDetalhePath,
    projetoPlanejamentoSprintsPath,
} from '../sprint-detalhe/sprintDetalhePaths';
import { getSprintStatusLabel, renderSprintHealthTag, renderSprintStatusTag } from '../sprint-status';
import { routeProjetoId } from '@/features/projetos/feira-list';
import { useProjetoWriteGates } from '@/features/projetos/hooks/useProjetoWriteGates';
import {
    CursorModoCronogramaBadge,
    CursorPackPlanejamentoEmptyHint,
} from '@/features/projetos/cursor-pack';
import { useRecordWebsiteOnboardingVisit } from '@/features/projetos/website-personalizado-onboarding';
import {
    ProjetoSprintPinBar,
    ProjetosShortcutsHelp,
    PROJETOS_SPRINTS_LIST_SHORTCUT_ITEMS,
    useProjetoOperacaoHotkeys,
    useProjetoSprintPin,
} from '@/features/projetos/projeto-sprint-pin';
import { ModalOpcoesSprint } from './ModalOpcoesSprint';
import { ModalSprintForm } from './ModalSprintForm';
import { ModalFiltrosSprintsPlanejamento } from './components/ModalFiltrosSprintsPlanejamento';
import { useSprintsPlanejamentoListaUrlSync } from './hooks/useSprintsPlanejamentoListaUrlSync';
import { SPRINT_STATUS_OPTIONS } from './sprintsPlanejamentoOptions';
import { SPRINTS_PLANEJAMENTO_LIST_COLUMN_CATALOG } from './utils/sprintsPlanejamentoListColumnCatalog';
import {
    SPRINTS_PLANEJAMENTO_LIST_MODULE_KEY,
    sprintsPlanejamentoApplySavedPayload,
} from './utils/sprintsPlanejamentoFiltrosPayload';
import {
    SPRINTS_PLANEJAMENTO_LISTA_URL_DEFAULTS,
    type SprintsPlanejamentoListaFiltrosApi,
    type SprintsPlanejamentoListaUrlSnapshot,
} from './utils/sprintsPlanejamentoListaFiltersUrl';

const EMPTY_SPRINTS: Sprint[] = [];

const SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT: Exclude<ServerSideSortState, null> = {
    columnKey: 'data_inicio',
    order: 'descend',
};

const EXPORT_HELP =
    'Exporta apenas as sprints visíveis nesta página (listagem paginada no servidor).';

const BULK_CONFIRM_OPEN_DELAY_MS = 120;

function rotuloAriaOpcoesSprint(record: Sprint): string {
    const rotulo = record.nome?.trim();
    return rotulo ? `Opções: ${rotulo}` : `Opções: sprint ${record.id}`;
}

export function ProjetoPlanejamentoSprintsListaScreen() {
    const params = useParams();
    const pathname = usePathname() ?? '';
    const searchParams = useSearchParams();
    const router = useRouter();
    const screens = Grid.useBreakpoint();
    const { canEditar, permsLoading } = useProjetoWriteGates();
    const projetoId = routeProjetoId(params);
    useRecordWebsiteOnboardingVisit(projetoId, 'sprint');
    const { togglePin, isPinned } = useProjetoSprintPin(projetoId);

    const [currentPage, setCurrentPage] = useState(SPRINTS_PLANEJAMENTO_LISTA_URL_DEFAULTS.page);
    const [pageSize, setPageSize] = useState(SPRINTS_PLANEJAMENTO_LISTA_URL_DEFAULTS.perPage);
    const [tableSort, setTableSort] = useState<ServerSideSortState>(SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT);
    const [filtros, setFiltros] = useState<SprintsPlanejamentoListaFiltrosApi>({});
    const [filtrosModalOpen, setFiltrosModalOpen] = useState(false);
    const [modalFiltrosDraft, setModalFiltrosDraft] = useState<SprintsPlanejamentoListaFiltrosApi>({});
    const [filtroSalvoAtivo, setFiltroSalvoAtivo] = useState<{ nome: string } | null>(null);
    const skipClearFiltroSalvoOnNextUrlHydrateRef = useRef(false);
    const [listaMaisOpcoesOpen, setListaMaisOpcoesOpen] = useState(false);
    const [colunasVisiveisModalOpen, setColunasVisiveisModalOpen] = useState(false);
    const [modalAcoesMassaOpen, setModalAcoesMassaOpen] = useState(false);
    const [bulkBusy, setBulkBusy] = useState(false);
    const [opcoesItem, setOpcoesItem] = useState<Sprint | null>(null);
    const [modalSprintOpen, setModalSprintOpen] = useState(false);
    const [sprintToEdit, setSprintToEdit] = useState<Sprint | null>(null);
    const [shortcutsHelpOpen, setShortcutsHelpOpen] = useState(false);
    const focusBuscaFromHotkeyRef = useRef(false);
    const filtrosModalLayout = useWaygestFormModalProps();

    const { visibleKeys: visibleColumnKeys, columnOrder, setVisibleKeys: setVisibleColumnKeys } =
        useListingVisibleColumns(SPRINTS_PLANEJAMENTO_LIST_MODULE_KEY, SPRINTS_PLANEJAMENTO_LIST_COLUMN_CATALOG);

    useEffect(() => {
        if (searchParams?.get('openModal') === 'create') {
            setSprintToEdit(null);
            setModalSprintOpen(true);
            router.replace(projetoPlanejamentoSprintsPath(projetoId), { scroll: false });
        }
    }, [searchParams, projetoId, router]);

    const listParams = useMemo(() => {
        const sortColumn = tableSort?.columnKey ?? SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT.columnKey;
        const sortDirection =
            (tableSort?.order ?? SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT.order) === 'descend'
                ? 'desc'
                : 'asc';

        return {
            projeto_id: projetoId,
            page: currentPage,
            per_page: pageSize,
            sort_by: sortColumn,
            sort_direction: sortDirection,
            ...(filtros.status && { status: filtros.status }),
            ...(filtros.search?.trim() && { search: filtros.search.trim() }),
        };
    }, [projetoId, currentPage, pageSize, tableSort, filtros]);

    const metricParamsBase = useMemo(
        () => ({
            projeto_id: projetoId,
            per_page: 1,
            page: 1,
            ...(filtros.search?.trim() && { search: filtros.search.trim() }),
        }),
        [projetoId, filtros.search],
    );

    const {
        data: sprintsPage,
        isLoading,
        isFetching,
        isError,
        error: queryError,
        refetch,
    } = useQueryCache<PaginatedResponse<Sprint>>({
        queryKey: queryKeys.desenvolvimento.sprints.planejamentoList(projetoId, listParams),
        endpoint: API_ENDPOINTS.desenvolvimento.sprints.index,
        params: listParams,
        enabled: !!projetoId,
        staleTime: 1 * 60 * 1000,
        gcTime: 5 * 60 * 1000,
        placeholderData: keepPreviousData,
    });

    const { data: ativasPage, isLoading: ativasLoading } = useQueryCache<PaginatedResponse<Sprint>>({
        queryKey: queryKeys.desenvolvimento.sprints.planejamentoMetricAtivas(projetoId, metricParamsBase),
        endpoint: API_ENDPOINTS.desenvolvimento.sprints.index,
        params: { ...metricParamsBase, status: 'ativa' },
        enabled: !!projetoId,
        staleTime: 1 * 60 * 1000,
    });

    const { data: concluidasPage, isLoading: concluidasLoading } = useQueryCache<PaginatedResponse<Sprint>>({
        queryKey: queryKeys.desenvolvimento.sprints.planejamentoMetricConcluidas(projetoId, metricParamsBase),
        endpoint: API_ENDPOINTS.desenvolvimento.sprints.index,
        params: { ...metricParamsBase, status: 'concluida' },
        enabled: !!projetoId,
        staleTime: 1 * 60 * 1000,
    });

    const paginatedData = usePaginatedResponseFallback(sprintsPage, pageSize, EMPTY_SPRINTS);
    const sprintRows = paginatedData.data;
    const total = paginatedData.meta.total ?? 0;

    const paginatedAtivas = usePaginatedResponseFallback(ativasPage, 1, EMPTY_SPRINTS);
    const paginatedConcluidas = usePaginatedResponseFallback(concluidasPage, 1, EMPTY_SPRINTS);

    const deleteMutation = useMutationCache<void, number>({
        endpoint: (sprintId) => API_ENDPOINTS.desenvolvimento.sprints.destroy(sprintId),
        method: 'DELETE',
        invalidateQueries: [['desenvolvimento', 'sprints']],
        onSuccess: () => {
            message.success('Sprint excluída com sucesso!');
            refetch();
        },
        onError: (err: unknown) => {
            message.error(getLaravelApiErrorMessage(err, 'Erro ao excluir sprint'));
        },
    });

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

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

    const urlSnapshot = useMemo(
        (): SprintsPlanejamentoListaUrlSnapshot => ({
            page: currentPage,
            perPage: pageSize,
            filtros,
            sortColumn:
                (tableSort?.columnKey as SprintsPlanejamentoListaUrlSnapshot['sortColumn']) ??
                SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT.columnKey,
            sortDesc:
                (tableSort?.order ?? SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT.order) === 'descend',
        }),
        [currentPage, pageSize, filtros, tableSort],
    );

    const onHydrateFromUrl = useCallback((snapshot: SprintsPlanejamentoListaUrlSnapshot) => {
        setCurrentPage(snapshot.page);
        setPageSize(snapshot.perPage);
        setFiltros(snapshot.filtros);
        setTableSort({
            columnKey: snapshot.sortColumn,
            order: snapshot.sortDesc ? 'descend' : 'ascend',
        });
        if (!skipClearFiltroSalvoOnNextUrlHydrateRef.current) {
            setFiltroSalvoAtivo(null);
        }
        skipClearFiltroSalvoOnNextUrlHydrateRef.current = false;
    }, []);

    useSprintsPlanejamentoListaUrlSync({
        pathname,
        searchParams,
        snapshot: urlSnapshot,
        onHydrateFromUrl,
    });

    useEffect(() => {
        clearSelection();
    }, [filtros, clearSelection]);

    useEffect(() => {
        if (selectedRowKeys.length === 0) {
            setModalAcoesMassaOpen(false);
        }
    }, [selectedRowKeys.length]);

    const handleTableChange = useServerSideListingTableChange<Sprint>({
        sortState: tableSort,
        setSortState: setTableSort,
        setPage: setCurrentPage,
        setPerPage: setPageSize,
    });

    const sortColumnUi = listingSortColumnUi(tableSort, SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT);

    const limparTodosFiltros = useCallback(() => {
        setFiltros({});
        setFiltroSalvoAtivo(null);
        setCurrentPage(1);
        setPageSize(SPRINTS_PLANEJAMENTO_LISTA_URL_DEFAULTS.perPage);
        setTableSort(SPRINTS_PLANEJAMENTO_LIST_DEFAULT_SORT);
        setFiltrosModalOpen(false);
        clearSelection();
    }, [clearSelection]);

    const openCreate = useCallback(() => {
        setSprintToEdit(null);
        setModalSprintOpen(true);
    }, []);

    const handleDelete = useCallback(
        (id: number, nome?: string) => {
            confirmDialog({
                title: 'Confirmar exclusão',
                content: nome
                    ? `Deseja realmente excluir a sprint "${nome}"?`
                    : 'Deseja realmente excluir esta sprint?',
                okText: 'Excluir',
                okType: 'danger',
                cancelText: 'Cancelar',
                onOk: () => deleteMutation.mutate(id),
            });
        },
        [deleteMutation],
    );

    const execBulkExcluir = useCallback(async () => {
        if (selectedIds.length === 0) return;
        setBulkBusy(true);
        try {
            const results = await Promise.allSettled(
                selectedIds.map((id) => apiClient.delete(API_ENDPOINTS.desenvolvimento.sprints.destroy(id))),
            );
            const ok = results.filter((r: any) => r.status === 'fulfilled').length;
            const fail = results.length - ok;
            clearSelection();
            setOpcoesItem(null);
            await refetch();
            if (ok > 0 && fail === 0) {
                message.success(ok === 1 ? 'Sprint excluída.' : `${ok} sprints excluídas.`);
                return;
            }
            if (ok > 0 && fail > 0) {
                message.warning(`${ok} excluída(s), ${fail} falharam (permissão ou vínculos).`);
                return;
            }
            message.error('Não foi possível excluir as sprints selecionadas.');
        } finally {
            setBulkBusy(false);
        }
    }, [selectedIds, clearSelection, refetch]);

    const promptBulkExcluir = useCallback(() => {
        const n = selectedIds.length;
        if (n === 0) {
            message.warning('Selecione pelo menos uma sprint.');
            return;
        }
        confirmDialog({
            title: 'Excluir sprints selecionadas',
            content: `Excluir permanentemente ${n} sprint(s)? Esta ação não pode ser desfeita.`,
            okText: 'Excluir',
            cancelText: 'Cancelar',
            okButtonProps: { danger: true },
            onOk: () => execBulkExcluir(),
        });
    }, [selectedIds.length, execBulkExcluir]);

    const acoesMassaModal = useMemo((): ModalOpcaoAction[] => {
        const n = selectedIds.length;
        return [
            {
                key: 'excluir',
                label: `Excluir selecionadas${n > 0 ? ` (${n})` : ''}`,
                icon: <Trash2 size={ICON_SIZE_MD} aria-hidden />,
                danger: true,
                disabled: bulkBusy || n === 0,
                onClick: () => {
                    setModalAcoesMassaOpen(false);
                    window.setTimeout(() => promptBulkExcluir(), BULK_CONFIRM_OPEN_DELAY_MS);
                },
            },
        ];
    }, [bulkBusy, selectedIds.length, promptBulkExcluir]);

    const abrirOpcoesSprint = useCallback((record: Sprint) => {
        setOpcoesItem(record);
    }, []);

    const handleSprintRowProps = useCallback(
        (record: Sprint) =>
            buildListingRowInteractiveProps(record, {
                onAtivate: abrirOpcoesSprint,
                getRowSummary: (row) => row.nome?.trim() || `Sprint ${row.id}`,
                ariaLabelWithSummary: (summary) =>
                    `Sprint: ${summary}. Enter ou espaço abre o menu de opções.`,
                ariaLabelFallback: 'Sprint. Enter ou espaço abre o menu de opções.',
            }),
        [abrirOpcoesSprint],
    );

    const filtrosAtivosCount = useMemo(() => {
        let n = 0;
        if (filtros.status) n += 1;
        if (filtros.search?.trim()) n += 1;
        return n;
    }, [filtros]);
    const filtrosComAlgumAtivo = filtrosAtivosCount > 0;

    const resumoFiltrosAplicados = useMemo(() => {
        const partes: string[] = [];
        if (filtros.status) {
            partes.push(
                `Status: ${SPRINT_STATUS_OPTIONS.find((o) => o.value === filtros.status)?.label ?? filtros.status}`,
            );
        }
        const q = filtros.search?.trim();
        if (q) partes.push(`Pesquisa: "${q}"`);
        return partes.length ? partes.join(' · ') : '';
    }, [filtros]);

    const abrirModalFiltros = useCallback(() => {
        setModalFiltrosDraft({ ...filtros });
        setFiltrosModalOpen(true);
    }, [filtros]);

    const focusSprintsBusca = useCallback(() => {
        focusBuscaFromHotkeyRef.current = true;
        abrirModalFiltros();
    }, [abrirModalFiltros]);

    useEffect(() => {
        if (!filtrosModalOpen || !focusBuscaFromHotkeyRef.current) {
            return undefined;
        }
        focusBuscaFromHotkeyRef.current = false;
        const timer = window.setTimeout(() => {
            document
                .querySelector<HTMLInputElement>(
                    '[data-testid="sprints-planejamento-filtros-busca-input"] input, [data-testid="sprints-planejamento-filtros-busca-input"]',
                )
                ?.focus();
        }, 80);
        return () => window.clearTimeout(timer);
    }, [filtrosModalOpen]);

    useProjetoOperacaoHotkeys({
        enabled: Boolean(projetoId) && !shortcutsHelpOpen,
        onFocusSearch: focusSprintsBusca,
        onOpenHelp: () => setShortcutsHelpOpen(true),
    });

    const limparRascunhoFiltros = useCallback(() => {
        setModalFiltrosDraft({});
    }, []);

    const aplicarFiltrosModal = useCallback(() => {
        setFiltros({
            status: modalFiltrosDraft.status,
            search: modalFiltrosDraft.search?.trim() || undefined,
        });
        setFiltroSalvoAtivo(null);
        setCurrentPage(1);
        clearSelection();
        setFiltrosModalOpen(false);
    }, [modalFiltrosDraft, clearSelection]);

    const handleApplySavedFilter = useCallback(
        (payload: unknown, meta: { nome: string; id: number }) => {
            const parsed = sprintsPlanejamentoApplySavedPayload(payload);
            if (!parsed) {
                message.error('Não foi possível aplicar o filtro salvo.');
                return;
            }
            setFiltros(parsed);
            setModalFiltrosDraft(parsed);
            setFiltroSalvoAtivo({ nome: meta.nome });
            setCurrentPage(1);
            clearSelection();
            setFiltrosModalOpen(false);
            skipClearFiltroSalvoOnNextUrlHydrateRef.current = true;
        },
        [clearSelection],
    );

    const sprintsExportRows = useMemo(
        () =>
            sprintRows.map((s) => ({
                nome: s.nome ?? '',
                projeto: (s.projeto as { nome?: string } | undefined)?.nome ?? '',
                status: getSprintStatusLabel(s.status),
                data_inicio: s.data_inicio ? formatDate(s.data_inicio) : '',
                data_fim: s.data_fim ? formatDate(s.data_fim) : '',
                capacidade_planejada: s.capacidade_planejada ?? '',
                capacidade_realizada: s.capacidade_realizada ?? '',
            })),
        [sprintRows],
    );

    const listagemErroMsg = getLaravelApiErrorMessage(
        queryError,
        'Não foi possível carregar as sprints. Verifique a conexão e tente novamente.',
    );
    const showEmptyState = !isError && total === 0 && !isLoading;
    const showTableBlock = !isError && !showEmptyState;
    const sprintsTabelaScrollHint = useListingMobileScrollHint(
        'Deslize horizontalmente para ver todas as colunas.',
    );

    const metricTotal = total;
    const metricAtivas = paginatedAtivas.meta.total ?? 0;
    const metricConcluidas = paginatedConcluidas.meta.total ?? 0;
    const metricasLoading =
        (isLoading && sprintRows.length === 0) || ativasLoading || concluidasLoading;

    const columns: ColumnsType<Sprint> = useMemo(() => {
        const allColumns: ColumnsType<Sprint> = [
            {
                title: '',
                key: 'menu',
                width: 52,
                align: 'center',
                fixed: 'left',
                onCell: () => ({ onClick: (e: React.MouseEvent) => e.stopPropagation() }),
                render: (_: unknown, record: Sprint) => (
                    <ListingActionsColumnCell
                        ariaLabel={rotuloAriaOpcoesSprint(record)}
                        onOpen={() => setOpcoesItem(record)}
                    />
                ),
            },
            {
                title: 'Nome',
                dataIndex: 'nome',
                key: 'nome',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'nome' ? sortColumnUi.order : undefined,
                render: (text: string) => (
                    <span style={{ fontWeight: 600, color: '#2c3e50' }}>{text}</span>
                ),
            },
            {
                title: 'Status',
                dataIndex: 'status',
                key: 'status',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'status' ? sortColumnUi.order : undefined,
                render: (s: string) => renderSprintStatusTag(s),
            },
            {
                title: 'Data início',
                dataIndex: 'data_inicio',
                key: 'data_inicio',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'data_inicio' ? sortColumnUi.order : undefined,
                render: (d: string) => (d ? formatDate(d) : '-'),
            },
            {
                title: 'Data fim',
                dataIndex: 'data_fim',
                key: 'data_fim',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'data_fim' ? sortColumnUi.order : undefined,
                render: (d: string) => (d ? formatDate(d) : '-'),
            },
            {
                title: 'Capacidade (plan. / real)',
                key: 'capacidade_planejada',
                width: 160,
                sorter: listingServerSortNoOp,
                sortOrder:
                    sortColumnUi.columnKey === 'capacidade_planejada' ? sortColumnUi.order : undefined,
                render: (_: unknown, s: Sprint) => {
                    if (s.capacidade_planejada == null && s.capacidade_realizada == null) {
                        return <span style={{ color: '#999' }}>—</span>;
                    }
                    return (
                        <span style={{ fontSize: 13 }}>
                            {s.capacidade_planejada ?? '—'} / {s.capacidade_realizada ?? '—'}
                        </span>
                    );
                },
            },
            {
                title: 'Saúde',
                key: 'saude',
                width: 120,
                render: (_: unknown, s: Sprint) => renderSprintHealthTag(s),
            },
        ];

        return filterTableColumnsByVisibleKeys(allColumns, visibleColumnKeys, ['menu']);
    }, [sortColumnUi, visibleColumnKeys]);

    const sprintsHeaderActions = (
        <Space wrap size={8} align="center">
            <CursorModoCronogramaBadge projetoId={projetoId} />
            {!permsLoading && canEditar ? (
                screens.lg ? (
                    <Button
                        type="primary"
                        size="large"
                        icon={<Plus size={ICON_SIZE_MD} aria-hidden />}
                        onClick={openCreate}
                        data-testid="planejamento-sprints-header-novo"
                    >
                        Nova sprint
                    </Button>
                ) : (
                    <Tooltip title="Nova sprint">
                        <span style={{ display: 'inline-block' }}>
                            <ButtonHeaderIcon
                                data-testid="planejamento-sprints-header-novo"
                                icon={<Plus size={ICON_SIZE_MD} aria-hidden />}
                                title="Nova sprint"
                                aria-label="Nova sprint"
                                onClick={openCreate}
                                className={btnHeaderStyles.btnHeaderIcon}
                            />
                        </span>
                    </Tooltip>
                )
            ) : null}
            <ProjetosShortcutsHelp
                items={PROJETOS_SPRINTS_LIST_SHORTCUT_ITEMS}
                open={shortcutsHelpOpen}
                onOpenChange={setShortcutsHelpOpen}
                title="Atalhos — sprints do projeto"
            />
            {filtroSalvoAtivo ? (
                <SavedFilterActiveTag
                    nome={filtroSalvoAtivo.nome}
                    dataTestId="planejamento-sprints-filtro-salvo-ativo"
                />
            ) : null}
            <ListingPageOptionsButton
                data-testid="planejamento-sprints-lista-mais-opcoes"
                expanded={listaMaisOpcoesOpen}
                ariaLabel="Opções"
                tooltipTitle="Colunas visíveis da listagem"
                onClick={() => setListaMaisOpcoesOpen(true)}
            />
            <Tooltip
                title={
                    filtrosComAlgumAtivo
                        ? `Filtros ativos (${filtrosAtivosCount}) — sincronizam com a URL`
                        : 'Filtrar sprints por status ou nome'
                }
            >
                <span style={{ display: 'inline-block' }}>
                    <Badge dot={filtrosComAlgumAtivo} color="geekblue">
                        <ButtonHeaderIcon
                            data-testid="planejamento-sprints-abrir-filtros"
                            icon={<Filter size={ICON_SIZE_MD} aria-hidden />}
                            title={filtrosAtivosCount > 0 ? `Filtros (${filtrosAtivosCount})` : 'Filtros'}
                            aria-label="Abrir filtros de sprints"
                            aria-expanded={filtrosModalOpen}
                            aria-haspopup="dialog"
                            onClick={abrirModalFiltros}
                            className={btnHeaderStyles.btnHeaderIcon}
                        />
                    </Badge>
                </span>
            </Tooltip>
            <Tooltip title={EXPORT_HELP}>
                <span style={{ display: 'inline-block' }}>
                    <LazyExportButton
                        data={sprintsExportRows as unknown as Record<string, unknown>[]}
                        columns={[
                            { key: 'nome', label: 'Nome' },
                            { key: 'projeto', label: 'Projeto' },
                            { key: 'status', label: 'Status' },
                            { key: 'data_inicio', label: 'Data início' },
                            { key: 'data_fim', label: 'Data fim' },
                            { key: 'capacidade_planejada', label: 'Capacidade planejada' },
                            { key: 'capacidade_realizada', label: 'Capacidade realizada' },
                        ]}
                        filename={`projeto-${projetoId}-sprints-planejamento`}
                        title="Exportar sprints"
                        iconOnly
                        size="large"
                        exportMenuMode="modal"
                        exportHelpText={EXPORT_HELP}
                        className={btnHeaderStyles.btnHeaderIcon}
                    />
                </span>
            </Tooltip>
        </Space>
    );

    if (!projetoId) {
        return (
            <ProjetoLayout projetoId="" pageTitle="Sprints" showPageTitleIcon={false} titleSection="Sprints">
                <Typography.Text type="secondary">Projeto inválido.</Typography.Text>
            </ProjetoLayout>
        );
    }

    return (
        <>
            <ProjetoLayout
                projetoId={projetoId}
                pageTitle="Sprints"
                pageIcon="rocket"
                showPageTitleIcon={false}
                titleSection="Sprints"
                headerAction={sprintsHeaderActions}
            >
                <ProjetoSprintPinBar projetoId={projetoId} />
                <MetricsGrid columns={3} style={{ marginBottom: 15, gap: 15 }}>
                    <MetricCard
                        icon={<Rocket size={ICON_SIZE_MD} aria-hidden />}
                        label="Total de sprints"
                        value={String(metricTotal)}
                        loading={metricasLoading}
                        variant="projetos"
                    />
                    <MetricCard
                        icon={<CirclePlay size={ICON_SIZE_MD} aria-hidden />}
                        label="Ativas"
                        value={String(metricAtivas)}
                        loading={metricasLoading}
                        variant="emAndamento"
                    />
                    <MetricCard
                        icon={<CheckCircle2 size={ICON_SIZE_MD} aria-hidden />}
                        label="Concluídas"
                        value={String(metricConcluidas)}
                        loading={metricasLoading}
                        variant="concluidos"
                    />
                </MetricsGrid>

                <ModalFiltrosSprintsPlanejamento
                    open={filtrosModalOpen}
                    onClose={() => setFiltrosModalOpen(false)}
                    draft={modalFiltrosDraft}
                    onDraftChange={setModalFiltrosDraft}
                    onAplicar={aplicarFiltrosModal}
                    onLimparRascunho={limparRascunhoFiltros}
                    onLimparTodosFiltros={limparTodosFiltros}
                    onApplySaved={handleApplySavedFilter}
                    modalWidth={filtrosModalLayout.width ?? 640}
                    modalCentered={filtrosModalLayout.centered ?? true}
                    modalClassName={filtrosModalLayout.className}
                    modalZIndex={filtrosModalLayout.zIndex}
                    modalStyles={mergeWaygestFormModalBodyStyles(filtrosModalLayout, {
                        body: { maxHeight: 'min(70vh, calc(100vh - 200px))' },
                    })}
                />

                {filtrosComAlgumAtivo && showTableBlock ? (
                    <Alert
                        type="info"
                        showIcon
                        style={{ marginBottom: 16 }}
                        message={`Filtros aplicados (${filtrosAtivosCount})`}
                        description={
                            <>
                                {resumoFiltrosAplicados}
                                <Button type="link" onClick={limparTodosFiltros} style={{ paddingLeft: 8 }}>
                                    Limpar filtros
                                </Button>
                            </>
                        }
                    />
                ) : null}

                {isError ? (
                    <ListagemListaError
                        message="Falha ao carregar sprints"
                        description={listagemErroMsg}
                        onRetry={() => void refetch()}
                        data-testid="planejamento-sprints-lista-retry"
                    />
                ) : null}

                {showEmptyState ? (
                    <ListagemEmptyState
                        type={filtrosComAlgumAtivo ? 'warning' : 'info'}
                        icon={<Rocket size={iconTokenSize.xl} aria-hidden />}
                        message={
                            filtrosComAlgumAtivo
                                ? 'Nenhum resultado para os filtros'
                                : 'Nenhuma sprint cadastrada'
                        }
                        description={
                            filtrosComAlgumAtivo
                                ? 'Ajuste os critérios ou limpe os filtros para voltar a ver sprints deste projeto.'
                                : permsLoading || canEditar
                                  ? (
                                        <>
                                            Cadastre a primeira sprint para organizar entregas e acompanhar o ritmo
                                            do planejamento.
                                            <CursorPackPlanejamentoEmptyHint
                                                projetoId={projetoId}
                                                showCursorHint={!filtrosComAlgumAtivo}
                                            />
                                        </>
                                    )
                                  : 'Não há sprints nesta listagem. Peça acesso para cadastrar se precisar incluir um registro.'
                        }
                        ctaLabel={
                            filtrosComAlgumAtivo
                                ? 'Limpar filtros'
                                : !permsLoading && canEditar
                                  ? 'Nova sprint'
                                  : undefined
                        }
                        onCta={
                            filtrosComAlgumAtivo
                                ? limparTodosFiltros
                                : !permsLoading && canEditar
                                  ? openCreate
                                  : undefined
                        }
                        data-testid="planejamento-sprints-lista-empty"
                    />
                ) : null}

                {showTableBlock ? (
                    <TableScrollWrapper hint={sprintsTabelaScrollHint}>
                        <LazyDataTable
                            rowKey="id"
                            columns={columns}
                            data={sprintRows}
                            paginatedData={paginatedData}
                            loading={isLoading}
                            fetching={isFetching}
                            onRefresh={refetch}
                            rowSelection={rowSelection}
                            onChange={handleTableChange}
                            onRow={handleSprintRowProps}
                            autoMobileFromColumns={{
                                testIdPrefix: 'planejamento-sprints',
                                listHeading: 'Lista de sprints',
                                getFallbackTitle: (record: any) =>
                                    record.nome?.trim() || `Sprint ${record.id}`,
                                onCardClick: (record: any) =>
                                    router.push(projetoPlanejamentoSprintDetalhePath(projetoId, record.id)),
                                onOpenOptions: (item) => setOpcoesItem(item),
                            }}
                        />
                    </TableScrollWrapper>
                ) : null}

                <ModalOpcoesSprint
                    open={opcoesItem !== null}
                    onClose={() => setOpcoesItem(null)}
                    item={opcoesItem}
                    isPinned={opcoesItem ? isPinned(opcoesItem.id) : false}
                    onTogglePin={(item) => {
                        const next = togglePin({ id: item.id, nome: item.nome });
                        message.success(
                            next
                                ? `Sprint "${next.sprintNome}" fixada — acesse pelo atalho no topo.`
                                : 'Sprint desafixada.',
                        );
                    }}
                    onVer={(item) => {
                        setOpcoesItem(null);
                        router.push(projetoPlanejamentoSprintDetalhePath(projetoId, item.id));
                    }}
                    onEditar={(item) => {
                        setOpcoesItem(null);
                        setSprintToEdit(item);
                        setModalSprintOpen(true);
                    }}
                    onExcluir={(item) => {
                        setOpcoesItem(null);
                        handleDelete(item.id, item.nome);
                    }}
                />

                <ModalSprintForm
                    open={modalSprintOpen}
                    onClose={() => {
                        setModalSprintOpen(false);
                        setSprintToEdit(null);
                    }}
                    projetoId={projetoId}
                    sprint={sprintToEdit}
                    onSuccess={() => refetch()}
                />
            </ProjetoLayout>

            <ListingPageOptionsModal
                open={listaMaisOpcoesOpen}
                onClose={() => setListaMaisOpcoesOpen(false)}
                subtitle="Sprints do planejamento"
                onColunasVisiveis={() => setColunasVisiveisModalOpen(true)}
                data-testid="planejamento-sprints-opcoes-pagina-modal"
                aria-label="Opções da listagem de sprints"
            />

            <ListingColumnCustomizeModal
                open={colunasVisiveisModalOpen}
                onClose={() => setColunasVisiveisModalOpen(false)}
                catalog={SPRINTS_PLANEJAMENTO_LIST_COLUMN_CATALOG}
                value={visibleColumnKeys}
                order={columnOrder}
                onApply={setVisibleColumnKeys}
                data-testid="planejamento-sprints-lista-customizar-colunas-modal"
            />

            <ListingBulkFabModal
                showFab={selectedRowKeys.length > 0}
                modalOpen={modalAcoesMassaOpen}
                onOpenModal={() => setModalAcoesMassaOpen(true)}
                onCloseModal={() => setModalAcoesMassaOpen(false)}
                busy={bulkBusy}
                modalTitle="Ações em massa"
                modalSubtitle={`${selectedRowKeys.length} sprint(s) selecionada(s)`}
                actions={acoesMassaModal}
                fabAriaLabel={`Ações em massa — ${selectedRowKeys.length} sprint(s) selecionada(s)`}
                data-testid-fab="planejamento-sprints-fab-selecao-acoes"
                data-testid-modal="planejamento-sprints-modal-acoes-massa"
            />

            {selectedRowKeys.length === 0 && !permsLoading && canEditar ? (
                <ListPageCreateFloatButton
                    data-testid="projeto-planejamento-sprints-fab-nova"
                    tooltip={{
                        title: 'Nova sprint — refine a listagem com Filtros no cabeçalho',
                    }}
                    onClick={openCreate}
                />
            ) : null}
        </>
    );
}
