'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 dynamic from 'next/dynamic';
import { Box, Clock, Filter, Loader2, Plus, Send, Trash2 } from 'lucide-react';
import {
    Alert,
    Badge,
    Button,
    Col,
    DatePicker,
    Form,
    Grid,
    Input,
    Modal,
    Row,
    Segmented,
    Select,
    Space,
    Tag,
    Tooltip,
    Typography,
} from 'antd';
import { ICON_SIZE_MD, iconTokenSize } from '@/components/icons';
import type { ColumnsType } from 'antd/es/table';
import { useParams, usePathname, useSearchParams } from 'next/navigation';
import dayjs from 'dayjs';
import apiClient from '@/lib/api/client';
import { createIdempotencyKey, idempotencyKeyHeaders } from '@/lib/api/idempotencyKey';
import { useQueryCache } from '@/hooks/useQueryCache';
import { useMutationCache } from '@/hooks/useMutationCache';
import {
    mergeWaygestFormModalBodyStyles,
    useWaygestFormModalProps,
    waygestFormModalFooterClassName,
} from '@/hooks/useWaygestFormModalProps';
import { useListingFilteredRowSelection } from '@/hooks/useListingFilteredRowSelection';
import {
    listingSortColumnUi,
    useServerSideListingTableChange,
    type ServerSideSortState,
} from '@/hooks/useServerSideListingTableChange';
import { usePaginatedResponseFallback } from '@/hooks/usePaginatedResponseFallback';
import { queryKeys } from '@/lib/cache/queryKeys';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import { getLaravelApiErrorMessage } from '@/lib/api/laravelApiErrorMessage';
import { formatDate } from '@/lib/utils/export';
import type { PaginatedResponse } from '@/types';
import type { ModalOpcaoAction } from '@/components/ModalOpcoesBase';
import ProjetoLayout from '@/components/layouts/ProjetoLayout';
import MetricsGrid from '@/components/layouts/MetricsGrid';
import MetricCard from '@/components/layouts/MetricCard';
import ContentCard from '@/components/layouts/ContentCard';
import { ButtonHeaderIcon } from '@/components/ui';
import { FormGroup } from '@/components/form';
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 { MobilePageActionBar } from '@/components/filters/MobilePageActionBar';
import { useListingMobileChrome } from '@/components/mobile';
import btnHeaderStyles from '@/components/ui/buttons/ButtonHeaderIcon/ButtonHeaderIcon.module.scss';
import type { EntregasGlobalResumo } from '@/features/projetos/entregas-global';
import { useProjetoWriteGates } from '@/features/projetos/hooks/useProjetoWriteGates';
import {
    CursorModoCronogramaBadge,
    CursorPackPlanejamentoEmptyHint,
} from '@/features/projetos/cursor-pack';
import type { Entrega, EntregaFormValues } from './types';
import {
    PRIORIDADE_OPTIONS_ENTREGA,
    STATUS_OPTIONS_ENTREGA,
    TIPO_OPTIONS_ENTREGA,
    getEntregaPrioridadeColor,
    getEntregaPrioridadeLabel,
    getEntregaStatusColor,
    getEntregaStatusLabel,
} from './entregasPlanejamentoOptions';
import { ENTREGAS_PLANEJAMENTO_LIST_COLUMN_CATALOG } from './utils/entregasPlanejamentoListColumnCatalog';
import {
    ENTREGAS_PLANEJAMENTO_LIST_MODULE_KEY,
    entregasPlanejamentoApplySavedPayload,
} from './utils/entregasPlanejamentoFiltrosPayload';
import {
    ENTREGAS_PLANEJAMENTO_LISTA_URL_DEFAULTS,
    type EntregasPlanejamentoListaFiltrosApi,
    type EntregasPlanejamentoListaUrlSnapshot,
} from './utils/entregasPlanejamentoListaFiltersUrl';
import { useEntregasPlanejamentoListaUrlSync } from './hooks/useEntregasPlanejamentoListaUrlSync';
import { ModalFiltrosEntregasPlanejamento } from './components/ModalFiltrosEntregasPlanejamento';
import { ModalAceiteEntregaUatGate } from './components/ModalAceiteEntregaUatGate';
import { EntregaFichaTarefasPanel } from './components/EntregaFichaTarefasPanel';
import { EntregaFichaMrsPanel } from './components/EntregaFichaMrsPanel';
import { EntregasCronogramaTimeline } from './components/EntregasCronogramaTimeline';
import {
    buildAceiteConfirmacaoUatBody,
    buildAceiteOverrideUatBody,
    extrairContextoEntregaUatGate,
    type EntregaAceiteUatContexto,
} from './utils/entregaAceiteUatGate';
import { projetoPlanejamentoSprintsOpenCreatePath } from '@/features/projetos/sprint-detalhe/sprintDetalhePaths';
import Link from 'next/link';

type EntregasVistaMode = 'lista' | 'cronograma';

const ModalOpcoesEntrega = dynamic(
    () => import('@/features/projetos/desenvolvimento-entregas').then((m) => m.ModalOpcoesEntrega),
    { ssr: false },
);

/** Variáveis do POST aceite — `id` na URL; body via `buildBody` (gate UAT / PSA). */
type AceitarEntregaMutationVars = {
    id: number;
    confirmacao_uat?: boolean;
    override_uat?: boolean;
    motivo_override?: string;
};

const EMPTY_ENTREGAS: Entrega[] = [];

/** Ordenação omissa da API (`prioridade` desc, `codigo` asc). */
const ENTREGAS_PLANEJAMENTO_LIST_DEFAULT_SORT: Exclude<ServerSideSortState, null> = {
    columnKey: 'prioridade',
    order: 'descend',
};

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

const BULK_CONFIRM_OPEN_DELAY_MS = 120;

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 '';
}

function rotuloAriaOpcoesEntrega(record: Entrega): string {
    const rotulo = [record.codigo, record.titulo?.trim()].filter(Boolean).join(' — ');
    return rotulo ? `Opções: ${rotulo}` : `Opções: entrega ${record.id}`;
}

function flagsEntrega(record: Entrega): React.ReactNode[] {
    const tags: React.ReactNode[] = [];
    const fimOk = new Set(['aceita', 'cancelada']);
    if (record.prioridade === 'critica') {
        tags.push(
            <Tag key="pc" color="error">
                Prioridade
            </Tag>,
        );
    }
    if (record.status === 'rejeitada') {
        tags.push(
            <Tag key="rej" color="error">
                Rejeitada
            </Tag>,
        );
    }
    if (record.status === 'entregue') {
        tags.push(
            <Tag key="val" color="warning">
                Validação
            </Tag>,
        );
    }
    if (
        record.data_planejada &&
        !fimOk.has(record.status) &&
        dayjs(record.data_planejada).endOf('day').isBefore(dayjs())
    ) {
        tags.push(
            <Tag key="late" color="error">
                Prazo
            </Tag>,
        );
    }
    return tags;
}

function rowStyleEntrega(record: Entrega): React.CSSProperties {
    const fimOk = new Set(['aceita', 'cancelada']);
    const atraso =
        record.data_planejada &&
        !fimOk.has(record.status) &&
        dayjs(record.data_planejada).endOf('day').isBefore(dayjs());
    if (record.status === 'rejeitada' || record.prioridade === 'critica' || atraso) {
        return { cursor: 'pointer', backgroundColor: 'rgba(255, 77, 79, 0.06)' };
    }
    if (record.status === 'entregue') {
        return { cursor: 'pointer', backgroundColor: 'rgba(250, 173, 20, 0.08)' };
    }
    return { cursor: 'pointer' };
}

export function ProjetoPlanejamentoEntregasScreen() {
    const params = useParams();
    const pathname = usePathname() ?? '';
    const searchParams = useSearchParams();
    const screens = Grid.useBreakpoint();
    const { isMobile } = useListingMobileChrome();
    const { canEditar, permsLoading } = useProjetoWriteGates();
    const projetoId = routeSegmentId(params);

    const [currentPage, setCurrentPage] = useState(ENTREGAS_PLANEJAMENTO_LISTA_URL_DEFAULTS.page);
    const [pageSize, setPageSize] = useState(ENTREGAS_PLANEJAMENTO_LISTA_URL_DEFAULTS.perPage);
    const [tableSort, setTableSort] = useState<ServerSideSortState>(ENTREGAS_PLANEJAMENTO_LIST_DEFAULT_SORT);
    const [filtros, setFiltros] = useState<EntregasPlanejamentoListaFiltrosApi>({});
    const [filtrosModalOpen, setFiltrosModalOpen] = useState(false);
    const [modalFiltrosDraft, setModalFiltrosDraft] = useState<EntregasPlanejamentoListaFiltrosApi>({});
    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<Entrega | null>(null);
    const [modalOpen, setModalOpen] = useState(false);
    const [editingEntrega, setEditingEntrega] = useState<Entrega | null>(null);
    const [vistaMode, setVistaMode] = useState<EntregasVistaMode>('lista');
    /** Gate UAT (422 ENTREGA_UAT_GATE_REQUIRED) — modal contextual em vez de aceite cego. */
    const [uatGateState, setUatGateState] = useState<{
        entregaId: number;
        contexto: EntregaAceiteUatContexto;
    } | null>(null);
    const [form] = Form.useForm<EntregaFormValues>();
    const tipoWatch = Form.useWatch('tipo', form) as string | undefined;
    const sprintIdWatch = Form.useWatch('sprint_id', form) as number | undefined;
    const formModalLayout = useWaygestFormModalProps();
    const filtrosModalLayout = useWaygestFormModalProps();

    const { visibleKeys: visibleColumnKeys, columnOrder, setVisibleKeys: setVisibleColumnKeys } =
        useListingVisibleColumns(ENTREGAS_PLANEJAMENTO_LIST_MODULE_KEY, ENTREGAS_PLANEJAMENTO_LIST_COLUMN_CATALOG);

    const { data: sprintsProjetoData } = useQueryCache<{
        data: Array<{ id: number; nome: string }>;
    }>({
        queryKey: queryKeys.desenvolvimento.sprintsPlanejamentoEntregas(projetoId),
        endpoint: API_ENDPOINTS.desenvolvimento.sprints.index,
        params: { projeto_id: projetoId, per_page: 500, page: 1 },
        enabled: Boolean(projetoId) && modalOpen,
        staleTime: 60 * 1000,
    });
    const sprintsProjeto = sprintsProjetoData?.data ?? [];

    const { data: requisitosProjetoData } = useQueryCache<
        PaginatedResponse<{ id: number; codigo?: string | null; titulo?: string | null }>
    >({
        queryKey: queryKeys.desenvolvimento.requisitosPlanejamentoEntregas(projetoId),
        endpoint: API_ENDPOINTS.desenvolvimento.requisitos.index,
        params: { projeto_id: projetoId, per_page: 500, page: 1 },
        enabled: Boolean(projetoId) && modalOpen,
        staleTime: 60 * 1000,
    });
    const requisitosProjeto = requisitosProjetoData?.data ?? [];

    const listParams = useMemo(() => {
        const sortColumn = tableSort?.columnKey ?? ENTREGAS_PLANEJAMENTO_LIST_DEFAULT_SORT.columnKey;
        const sortDirection =
            (tableSort?.order ?? ENTREGAS_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.tipo && { tipo: filtros.tipo }),
            ...(filtros.search?.trim() && { search: filtros.search.trim() }),
        };
    }, [projetoId, currentPage, pageSize, tableSort, filtros]);

    const resumoParams = useMemo(
        () => ({
            projeto_id: projetoId,
            ...(filtros.status && { status: filtros.status }),
            ...(filtros.tipo && { tipo: filtros.tipo }),
            ...(filtros.search?.trim() && { search: filtros.search.trim() }),
        }),
        [projetoId, filtros],
    );

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

    const { data: resumo, isLoading: resumoLoading } = useQueryCache<EntregasGlobalResumo>({
        queryKey: queryKeys.entregas.planejamentoResumo(projetoId, resumoParams),
        endpoint: API_ENDPOINTS.entregas.resumo,
        params: resumoParams,
        staleTime: 60 * 1000,
        gcTime: 5 * 60 * 1000,
        enabled: !!projetoId,
    });

    const paginatedData = usePaginatedResponseFallback(entregasPage, pageSize, EMPTY_ENTREGAS);
    const entregas = paginatedData.data;
    const total = paginatedData.meta.total ?? 0;

    const storeMutation = useMutationCache<Entrega, Record<string, unknown>>({
        endpoint: API_ENDPOINTS.entregas.store,
        method: 'POST',
        invalidateQueries: [queryKeys.entregas.lists()],
        onSuccess: () => {
            message.success('Entrega criada com sucesso!');
            setModalOpen(false);
            form.resetFields();
            refetch();
        },
        onError: (err: unknown) => {
            message.error(getLaravelApiErrorMessage(err, 'Erro ao criar entrega'));
        },
    });

    const updateMutation = useMutationCache<Entrega, { id: number } & Record<string, unknown>>({
        endpoint: (vars) => API_ENDPOINTS.entregas.update(vars.id),
        method: 'PUT',
        invalidateQueries: [queryKeys.entregas.lists()],
        onSuccess: () => {
            message.success('Entrega atualizada com sucesso!');
            setModalOpen(false);
            setEditingEntrega(null);
            form.resetFields();
            refetch();
        },
        onError: (err: unknown) => {
            message.error(getLaravelApiErrorMessage(err, 'Erro ao atualizar entrega'));
        },
    });

    const entregarMutation = useMutationCache<unknown, number>({
        endpoint: (id) => API_ENDPOINTS.entregas.entregar(id),
        method: 'POST',
        invalidateQueries: [queryKeys.entregas.lists()],
        onSuccess: () => {
            message.success('Entrega marcada como entregue!');
            refetch();
        },
    });

    // TASK-PSC-042 — key estável até sucesso (retry UAT gate reutiliza a mesma key)
    const aceitarIdempotencyKeyRef = useRef(createIdempotencyKey());

    const aceitarMutation = useMutationCache<unknown, AceitarEntregaMutationVars>({
        endpoint: (vars) => API_ENDPOINTS.entregas.aceitar(vars.id),
        method: 'POST',
        buildBody: (vars) => {
            if (vars.confirmacao_uat === true) {
                return buildAceiteConfirmacaoUatBody();
            }
            if (vars.override_uat === true && vars.motivo_override) {
                return { override_uat: true as const, motivo_override: vars.motivo_override };
            }
            return {};
        },
        config: () => ({ headers: idempotencyKeyHeaders(aceitarIdempotencyKeyRef.current) }),
        invalidateQueries: [queryKeys.entregas.lists()],
        onSuccess: () => {
            message.success('Entrega aceita!');
            setUatGateState(null);
            aceitarIdempotencyKeyRef.current = createIdempotencyKey();
            refetch();
        },
        onError: (err, variables) => {
            const jaComConfirmacao =
                variables.confirmacao_uat === true || variables.override_uat === true;
            const contexto = extrairContextoEntregaUatGate(err);
            if (contexto && !jaComConfirmacao) {
                setUatGateState({
                    entregaId: variables.id,
                    contexto: {
                        ...contexto,
                        entrega_id: contexto.entrega_id ?? variables.id,
                    },
                });
                return;
            }
            message.error(getLaravelApiErrorMessage(err, 'Erro ao aceitar entrega'));
        },
    });

    const rejeitarMutation = useMutationCache<unknown, number>({
        endpoint: (id) => API_ENDPOINTS.entregas.rejeitar(id),
        method: 'POST',
        invalidateQueries: [queryKeys.entregas.lists()],
        onSuccess: () => {
            message.success('Entrega rejeitada');
            refetch();
        },
    });

    const destroyMutation = useMutationCache<void, number>({
        endpoint: (id) => API_ENDPOINTS.entregas.destroy(id),
        method: 'DELETE',
        invalidateQueries: [queryKeys.entregas.lists()],
        onSuccess: () => {
            message.success('Entrega excluída com sucesso!');
            refetch();
        },
        onError: (err: unknown) => {
            message.error(getLaravelApiErrorMessage(err, 'Erro ao excluir entrega'));
        },
    });

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

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

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

    const onHydrateFromUrl = useCallback((snapshot: EntregasPlanejamentoListaUrlSnapshot) => {
        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;
    }, []);

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

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

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

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

    const sortColumnUi = listingSortColumnUi(tableSort, ENTREGAS_PLANEJAMENTO_LIST_DEFAULT_SORT);

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

    const openCreate = () => {
        setEditingEntrega(null);
        form.setFieldsValue({
            titulo: '',
            descricao: undefined,
            tipo: 'funcionalidade',
            status: 'planejada',
            prioridade: 'media',
            data_planejada: null,
            data_inicio_planejada: null,
            sprint_id: undefined,
            requisito_id: undefined,
        });
        setModalOpen(true);
    };

    const openEdit = (record: Entrega) => {
        setEditingEntrega(record);
        form.setFieldsValue({
            titulo: record.titulo,
            descricao: record.descricao || undefined,
            tipo: record.tipo || undefined,
            status: record.status || 'planejada',
            prioridade: record.prioridade || undefined,
            data_planejada: record.data_planejada ? dayjs(record.data_planejada) : null,
            data_inicio_planejada: record.data_inicio_planejada
                ? dayjs(record.data_inicio_planejada)
                : null,
            responsavel_id: record.responsavel_id,
            sprint_id: record.sprint_id,
            requisito_id: record.requisito_id ?? undefined,
        });
        setModalOpen(true);
    };

    const handleSubmit = () => {
        form.validateFields().then((values) => {
            const payload: Record<string, unknown> = {
                projeto_id: Number(projetoId),
                titulo: values.titulo,
                descricao: values.descricao || null,
                tipo: values.tipo || null,
                status: values.status || 'planejada',
                prioridade: values.prioridade || null,
                data_planejada: values.data_planejada
                    ? values.data_planejada.format('YYYY-MM-DD')
                    : null,
                data_inicio_planejada: values.data_inicio_planejada
                    ? values.data_inicio_planejada.format('YYYY-MM-DD')
                    : null,
                responsavel_id: values.responsavel_id || null,
                sprint_id: values.sprint_id || null,
                requisito_id: values.requisito_id || null,
            };
            if (editingEntrega) {
                updateMutation.mutate({ id: editingEntrega.id, ...payload });
            } else {
                storeMutation.mutate(payload);
            }
        });
    };

    const handleEntregar = (id: number) => {
        confirmDialog({
            title: 'Marcar como entregue',
            content: 'Deseja marcar esta entrega como entregue?',
            okText: 'Entregar',
            cancelText: 'Cancelar',
            onOk: () => entregarMutation.mutate(id),
        });
    };

    /**
     * Aceite: POST sem body (PSA OK). Em SC/UAT a API devolve 422 gate → modal contextual
     * (confirmação UAT ou override auditado) — sem Modal.confirm cego como único caminho.
     */
    const handleAceitar = (id: number) => {
        aceitarMutation.mutate({ id });
    };

    const handleConfirmacaoUatGate = () => {
        if (!uatGateState) return;
        aceitarMutation.mutate({
            id: uatGateState.entregaId,
            ...buildAceiteConfirmacaoUatBody(),
        });
    };

    const handleOverrideUatGate = (motivo: string) => {
        if (!uatGateState) return;
        const body = buildAceiteOverrideUatBody(motivo);
        if (!body) {
            message.error(`Informe um motivo entre 10 e 500 caracteres.`);
            return;
        }
        aceitarMutation.mutate({
            id: uatGateState.entregaId,
            ...body,
        });
    };

    const handleRejeitar = (id: number) => {
        confirmDialog({
            title: 'Rejeitar entrega',
            content: 'Deseja rejeitar esta entrega?',
            okText: 'Rejeitar',
            cancelText: 'Cancelar',
            okType: 'danger',
            onOk: () => rejeitarMutation.mutate(id),
        });
    };

    const resolveEntregaFromOpcoes = useCallback(
        (item: { id: number }) => entregas.find((e) => e.id === item.id),
        [entregas],
    );

    const handleExcluirEntrega = (record: Entrega) => {
        confirmDialog({
            title: 'Excluir entrega',
            content: `Deseja realmente excluir "${record.titulo}"? Esta ação não pode ser desfeita.`,
            okText: 'Excluir',
            cancelText: 'Cancelar',
            okType: 'danger',
            onOk: () => destroyMutation.mutate(record.id),
        });
    };

    const execBulkEntregar = useCallback(async () => {
        if (selectedIds.length === 0) return;
        setBulkBusy(true);
        try {
            const results = await Promise.allSettled(
                selectedIds.map((id) => apiClient.post(API_ENDPOINTS.entregas.entregar(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 ? 'Entrega marcada como entregue.' : `${ok} entregas marcadas como entregues.`);
                return;
            }
            if (ok > 0 && fail > 0) {
                message.warning(`${ok} entregue(s), ${fail} falharam (status ou permissão).`);
                return;
            }
            message.error('Não foi possível marcar as entregas selecionadas como entregues.');
        } finally {
            setBulkBusy(false);
        }
    }, [selectedIds, clearSelection, refetch]);

    const execBulkExcluir = useCallback(async () => {
        if (selectedIds.length === 0) return;
        setBulkBusy(true);
        try {
            const results = await Promise.allSettled(
                selectedIds.map((id) => apiClient.delete(API_ENDPOINTS.entregas.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 ? 'Entrega excluída.' : `${ok} entregas 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 entregas selecionadas.');
        } finally {
            setBulkBusy(false);
        }
    }, [selectedIds, clearSelection, refetch]);

    const promptBulkEntregar = useCallback(() => {
        const n = selectedIds.length;
        if (n === 0) {
            message.warning('Selecione pelo menos uma entrega.');
            return;
        }
        confirmDialog({
            title: 'Marcar entregas selecionadas como entregues',
            content: `Confirma marcar ${n} entrega(s) como entregue(s)?`,
            okText: 'Entregar',
            cancelText: 'Cancelar',
            onOk: () => execBulkEntregar(),
        });
    }, [selectedIds.length, execBulkEntregar]);

    const promptBulkExcluir = useCallback(() => {
        const n = selectedIds.length;
        if (n === 0) {
            message.warning('Selecione pelo menos uma entrega.');
            return;
        }
        confirmDialog({
            title: 'Excluir entregas selecionadas',
            content: `Excluir permanentemente ${n} entrega(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: 'entregar',
                label: `Marcar como entregue${n > 0 ? ` (${n})` : ''}`,
                icon: <Send size={ICON_SIZE_MD} aria-hidden />,
                primary: true,
                disabled: bulkBusy || n === 0,
                onClick: () => {
                    setModalAcoesMassaOpen(false);
                    window.setTimeout(() => promptBulkEntregar(), BULK_CONFIRM_OPEN_DELAY_MS);
                },
            },
            {
                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, promptBulkEntregar, promptBulkExcluir]);

    const abrirOpcoesEntrega = useCallback((record: Entrega) => {
        setOpcoesItem(record);
    }, []);

    const handleEntregaRowProps = useCallback(
        (record: Entrega) => {
            const base = buildListingRowInteractiveProps(record, {
                onAtivate: abrirOpcoesEntrega,
                getRowSummary: (row) =>
                    [row.codigo, row.titulo?.trim()].filter(Boolean).join(' — ') || `ID ${row.id}`,
                ariaLabelWithSummary: (summary) =>
                    `Entrega: ${summary}. Enter ou espaço abre o menu de opções.`,
                ariaLabelFallback: 'Entrega. Enter ou espaço abre o menu de opções.',
            });
            return {
                ...base,
                style: { ...base.style, ...rowStyleEntrega(record) },
            };
        },
        [abrirOpcoesEntrega],
    );

    const filtrosAtivosCount = useMemo(() => {
        let n = 0;
        if (filtros.status) n += 1;
        if (filtros.tipo) 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: ${STATUS_OPTIONS_ENTREGA.find((o) => o.value === filtros.status)?.label ?? filtros.status}`,
            );
        }
        if (filtros.tipo) {
            partes.push(`Tipo: ${TIPO_OPTIONS_ENTREGA.find((o) => o.value === filtros.tipo)?.label ?? filtros.tipo}`);
        }
        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 limparRascunhoFiltros = useCallback(() => {
        setModalFiltrosDraft({});
    }, []);

    const aplicarFiltrosModal = useCallback(() => {
        setFiltros({
            status: modalFiltrosDraft.status,
            tipo: modalFiltrosDraft.tipo,
            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 = entregasPlanejamentoApplySavedPayload(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 entregasExportRows = useMemo(
        () =>
            entregas.map((e) => ({
                codigo: e.codigo ?? '',
                titulo: e.titulo,
                status: getEntregaStatusLabel(e.status),
                tipo: e.tipo ?? '',
                prioridade: e.prioridade ?? '',
                responsavel: e.responsavel?.nome ?? '',
                sprint: e.sprint?.nome ?? '',
                data_planejada: e.data_planejada ? formatDate(e.data_planejada) : '',
            })),
        [entregas],
    );

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

    const metricTotal = resumo?.total ?? total;
    const metricPlanejadas = resumo?.planejadas ?? 0;
    const metricEmPreparacao = resumo?.em_preparacao ?? 0;
    const metricasLoading = (resumoLoading && resumo === undefined) || (isLoading && entregas.length === 0);

    const columns: ColumnsType<Entrega> = useMemo(() => {
        const allColumns: ColumnsType<Entrega> = [
            {
                title: '',
                key: 'menu',
                width: 52,
                align: 'center',
                fixed: 'left',
                onCell: () => ({ onClick: (e: React.MouseEvent) => e.stopPropagation() }),
                render: (_: unknown, record: Entrega) => (
                    <ListingActionsColumnCell
                        ariaLabel={rotuloAriaOpcoesEntrega(record)}
                        onOpen={() => setOpcoesItem(record)}
                        data-testid={`planejamento-entregas-opcoes-${record.id}`}
                    />
                ),
            },
            {
                title: 'Código',
                dataIndex: 'codigo',
                key: 'codigo',
                width: 100,
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'codigo' ? sortColumnUi.order : undefined,
                render: (c: string) => (c ? <Tag>{c}</Tag> : '-'),
            },
            {
                title: 'Título',
                dataIndex: 'titulo',
                key: 'titulo',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'titulo' ? sortColumnUi.order : undefined,
                render: (text: string) => (
                    <span style={{ fontWeight: 600, color: '#2c3e50' }}>{text}</span>
                ),
            },
            {
                title: 'Sprint',
                dataIndex: ['sprint', 'nome'],
                key: 'sprint',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'sprint' ? sortColumnUi.order : undefined,
                render: (t: string) => t || '-',
            },
            {
                title: 'Status',
                dataIndex: 'status',
                key: 'status',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'status' ? sortColumnUi.order : undefined,
                render: (s: string) => (
                    <Tag color={getEntregaStatusColor(s)}>{getEntregaStatusLabel(s)}</Tag>
                ),
            },
            {
                title: 'Prioridade',
                dataIndex: 'prioridade',
                key: 'prioridade',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'prioridade' ? sortColumnUi.order : undefined,
                render: (p: string) =>
                    p ? (
                        <Tag color={getEntregaPrioridadeColor(p)}>{getEntregaPrioridadeLabel(p)}</Tag>
                    ) : (
                        '-'
                    ),
            },
            {
                title: 'Atenção',
                key: 'risco',
                width: 130,
                render: (_: unknown, record: Entrega) => {
                    const tags = flagsEntrega(record);
                    return tags.length ? (
                        <Space size={4} wrap>
                            {tags}
                        </Space>
                    ) : (
                        <span style={{ color: '#bfbfbf' }}>—</span>
                    );
                },
            },
            {
                title: 'Data planejada',
                dataIndex: 'data_planejada',
                key: 'data_planejada',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'data_planejada' ? sortColumnUi.order : undefined,
                render: (d: string) => (d ? dayjs(d).format('DD/MM/YYYY') : '-'),
            },
            {
                title: 'Responsável',
                dataIndex: ['responsavel', 'nome'],
                key: 'responsavel',
                sorter: listingServerSortNoOp,
                sortOrder: sortColumnUi.columnKey === 'responsavel' ? sortColumnUi.order : undefined,
                render: (t: string) => t || '-',
            },
        ];

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

    const entregasHeaderActions = (
        <Space wrap size={8} align="center">
            <Segmented
                value={vistaMode}
                onChange={(v) => setVistaMode(v as EntregasVistaMode)}
                options={[
                    { label: 'Lista', value: 'lista' },
                    { label: 'Cronograma', value: 'cronograma' },
                ]}
                data-testid="planejamento-entregas-vista-mode"
            />
            {!permsLoading && canEditar ? (
                screens.lg ? (
                    <Button
                        type="primary"
                        size="large"
                        icon={<Plus size={ICON_SIZE_MD} aria-hidden />}
                        onClick={openCreate}
                        data-testid="planejamento-entregas-header-novo"
                    >
                        Nova entrega
                    </Button>
                ) : (
                    <Tooltip title="Nova entrega">
                        <span style={{ display: 'inline-block' }}>
                            <ButtonHeaderIcon
                                data-testid="planejamento-entregas-header-novo"
                                icon={<Plus size={ICON_SIZE_MD} aria-hidden />}
                                title="Nova entrega"
                                aria-label="Nova entrega"
                                onClick={openCreate}
                                className={btnHeaderStyles.btnHeaderIcon}
                            />
                        </span>
                    </Tooltip>
                )
            ) : null}
            <ListingPageOptionsButton
                data-testid="planejamento-entregas-lista-mais-opcoes"
                expanded={listaMaisOpcoesOpen}
                ariaLabel="Opções"
                tooltipTitle="Colunas visíveis da listagem"
                onClick={() => setListaMaisOpcoesOpen(true)}
            />
            {!isMobile ? (
            <Tooltip
                title={
                    filtrosComAlgumAtivo
                        ? `Filtros ativos (${filtrosAtivosCount}) — sincronizam com a URL`
                        : 'Definir status, tipo e pesquisa na listagem'
                }
            >
                <span style={{ display: 'inline-block' }}>
                    <Badge dot={filtrosComAlgumAtivo} color="geekblue">
                        <ButtonHeaderIcon
                            data-testid="planejamento-entregas-abrir-filtros"
                            icon={<Filter size={ICON_SIZE_MD} aria-hidden />}
                            title={filtrosAtivosCount > 0 ? `Filtros (${filtrosAtivosCount})` : 'Filtros'}
                            aria-label="Abrir filtros de entregas"
                            aria-expanded={filtrosModalOpen}
                            aria-haspopup="dialog"
                            onClick={abrirModalFiltros}
                            className={btnHeaderStyles.btnHeaderIcon}
                        />
                    </Badge>
                </span>
            </Tooltip>
            ) : null}
            {!isMobile ? (
            <Tooltip title={EXPORT_HELP}>
                <span style={{ display: 'inline-block' }}>
                    <LazyExportButton
                        data={entregasExportRows as unknown as Record<string, unknown>[]}
                        columns={[
                            { key: 'codigo', label: 'Código' },
                            { key: 'titulo', label: 'Título' },
                            { key: 'status', label: 'Status' },
                            { key: 'tipo', label: 'Tipo' },
                            { key: 'prioridade', label: 'Prioridade' },
                            { key: 'responsavel', label: 'Responsável' },
                            { key: 'sprint', label: 'Sprint' },
                            { key: 'data_planejada', label: 'Data planejada' },
                        ]}
                        filename={`projeto-${projetoId}-entregas-planejamento`}
                        title="Exportar entregas"
                        iconOnly
                        size="large"
                        exportMenuMode="modal"
                        exportHelpText={EXPORT_HELP}
                        className={btnHeaderStyles.btnHeaderIcon}
                    />
                </span>
            </Tooltip>
            ) : null}
        </Space>
    );

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

    return (
        <>
            <ProjetoLayout
                projetoId={projetoId}
                pageTitle="Entregas"
                showPageTitleIcon={false}
                titleSection="Entregas"
                headerAction={
                    <Space wrap size={8} align="center">
                        <CursorModoCronogramaBadge projetoId={projetoId} />
                        {filtroSalvoAtivo ? (
                            <SavedFilterActiveTag
                                nome={filtroSalvoAtivo.nome}
                                dataTestId="planejamento-entregas-filtro-salvo-ativo"
                            />
                        ) : null}
                        {entregasHeaderActions}
                    </Space>
                }
            >
                <MetricsGrid columns={3} style={{ marginBottom: 15, gap: 15 }}>
                    <MetricCard
                        icon={<Box size={ICON_SIZE_MD} aria-hidden />}
                        label="Total"
                        value={String(metricTotal)}
                        loading={metricasLoading}
                        variant="projetos"
                    />
                    <MetricCard
                        icon={<Clock size={ICON_SIZE_MD} aria-hidden />}
                        label="Planejadas"
                        value={String(metricPlanejadas)}
                        loading={metricasLoading}
                        variant="emAndamento"
                    />
                    <MetricCard
                        icon={<Loader2 size={ICON_SIZE_MD} className="animate-spin" aria-hidden />}
                        label="Em Preparação"
                        value={String(metricEmPreparacao)}
                        loading={metricasLoading}
                        variant="emAndamento"
                    />
                </MetricsGrid>

                <ModalFiltrosEntregasPlanejamento
                    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 entregas"
                        description={listagemErroMsg}
                        onRetry={() => void refetch()}
                        data-testid="planejamento-entregas-lista-retry"
                    />
                ) : null}

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

                {showTableBlock && vistaMode === 'lista' ? (
                    <TableScrollWrapper hint={entregasTabelaScrollHint}>
                        <LazyDataTable
                            rowKey="id"
                            columns={columns}
                            data={entregas}
                            paginatedData={paginatedData}
                            loading={isLoading}
                            fetching={isFetching}
                            onRefresh={refetch}
                            rowSelection={rowSelection}
                            onChange={handleTableChange}
                            onRow={handleEntregaRowProps}
                            autoMobileFromColumns={{
                                testIdPrefix: 'planejamento-entregas',
                                listHeading: 'Lista de entregas',
                                getFallbackTitle: (record: any) =>
                                    [record.codigo, record.titulo?.trim()].filter(Boolean).join(' — ') ||
                                    `Entrega ${record.id}`,
                                getSubtitle: (record: any) => {
                                    const status = getEntregaStatusLabel(record.status);
                                    const prio = record.prioridade
                                        ? getEntregaPrioridadeLabel(record.prioridade)
                                        : null;
                                    return [status, prio].filter(Boolean).join(' · ') || undefined;
                                },
                                excludeFieldKeys: ['codigo', 'titulo', 'status', 'menu', 'acoes'],
                                onCardClick: (item) => setOpcoesItem(item),
                                onOpenOptions: (item) => setOpcoesItem(item),
                            }}
                        />
                    </TableScrollWrapper>
                ) : null}

                {showTableBlock && vistaMode === 'cronograma' ? (
                    <ContentCard
                        title="Cronograma de entregas"
                        style={{ marginBottom: 16 }}
                        className="planejamento-entregas-cronograma-card"
                    >
                        {isLoading ? (
                            <Typography.Text type="secondary">Carregando cronograma…</Typography.Text>
                        ) : (
                            <EntregasCronogramaTimeline
                                entregas={entregas}
                                onSelect={(record) => {
                                    if (canEditar) {
                                        openEdit(record);
                                    } else {
                                        setOpcoesItem(record);
                                    }
                                }}
                            />
                        )}
                    </ContentCard>
                ) : null}

                <Modal
                    title={editingEntrega ? 'Editar entrega' : 'Nova entrega'}
                    open={modalOpen}
                    onCancel={() => {
                        setModalOpen(false);
                        setEditingEntrega(null);
                        form.resetFields();
                    }}
                    footer={
                        <div className={waygestFormModalFooterClassName}>
                            <Button
                                onClick={() => {
                                    setModalOpen(false);
                                    setEditingEntrega(null);
                                    form.resetFields();
                                }}
                            >
                                Cancelar
                            </Button>
                            <Button
                                type="primary"
                                loading={storeMutation.isPending || updateMutation.isPending}
                                onClick={() => form.submit()}
                            >
                                {editingEntrega ? 'Salvar' : 'Criar'}
                            </Button>
                        </div>
                    }
                    width={formModalLayout.width ?? (editingEntrega ? 720 : 560)}
                    centered={formModalLayout.centered ?? true}
                    className={formModalLayout.className}
                    styles={formModalLayout.styles ?? {}}
                    destroyOnHidden
                    keyboard
                    focusTriggerAfterClose
                    data-testid="projeto-planejamento-entregas-form-modal"
                >
                    <Form form={form} layout="vertical" onFinish={handleSubmit}>
                        <FormGroup>
                            <Form.Item
                                name="titulo"
                                label="Título"
                                rules={[{ required: true, message: 'Informe o título' }]}
                            >
                                <Input placeholder="Título da entrega" />
                            </Form.Item>
                        </FormGroup>
                        <FormGroup>
                            <Form.Item name="descricao" label="Descrição">
                                <Input.TextArea rows={3} placeholder="Descrição" />
                            </Form.Item>
                        </FormGroup>
                        <Row gutter={16}>
                            <Col xs={24} sm={12}>
                                <Form.Item name="tipo" label="Tipo">
                                    <Select placeholder="Tipo" allowClear options={TIPO_OPTIONS_ENTREGA} />
                                </Form.Item>
                            </Col>
                            <Col xs={24} sm={12}>
                                <Form.Item name="status" label="Status">
                                    <Select placeholder="Status" options={STATUS_OPTIONS_ENTREGA} />
                                </Form.Item>
                            </Col>
                        </Row>
                        {tipoWatch === 'sprint' ? (
                            <Alert
                                type="info"
                                showIcon
                                style={{ marginBottom: 16 }}
                                message="Entrega do tipo sprint"
                                description={
                                    <span>
                                        Opcional: vincule uma sprint existente no campo abaixo. Para
                                        criar uma sprint nova, use{' '}
                                        <Link href={projetoPlanejamentoSprintsOpenCreatePath(projetoId)}>
                                            Planejamento → Sprints
                                        </Link>
                                        .
                                    </span>
                                }
                                data-testid="entrega-form-hint-tipo-sprint"
                            />
                        ) : null}
                        <Row gutter={16}>
                            <Col xs={24} sm={12}>
                                <Form.Item name="prioridade" label="Prioridade">
                                    <Select
                                        placeholder="Prioridade"
                                        allowClear
                                        options={PRIORIDADE_OPTIONS_ENTREGA}
                                    />
                                </Form.Item>
                            </Col>
                            <Col xs={24} sm={12}>
                                <Form.Item
                                    name="sprint_id"
                                    label="Sprint (opcional)"
                                    extra="Ligação principal entrega ↔ sprint."
                                >
                                    <Select
                                        placeholder="Selecione a sprint"
                                        allowClear
                                        showSearch
                                        optionFilterProp="label"
                                        options={sprintsProjeto.map((s) => ({
                                            label: s.nome,
                                            value: s.id,
                                        }))}
                                    />
                                </Form.Item>
                            </Col>
                        </Row>
                        <Form.Item
                            name="requisito_id"
                            label="Requisito (rastreio)"
                            extra="Liga a entrega ao requisito de software para a matriz PMO."
                        >
                            <Select
                                placeholder="Selecione o requisito"
                                allowClear
                                showSearch
                                optionFilterProp="label"
                                options={requisitosProjeto.map((r: any) => ({
                                    value: r.id,
                                    label: [r.codigo, r.titulo?.trim()].filter(Boolean).join(' — ') || `Req. ${r.id}`,
                                }))}
                            />
                        </Form.Item>
                        <Row gutter={16}>
                            <Col xs={24} sm={12}>
                                <Form.Item name="data_inicio_planejada" label="Início planejado">
                                    <DatePicker style={{ width: '100%' }} format="DD/MM/YYYY" />
                                </Form.Item>
                            </Col>
                            <Col xs={24} sm={12}>
                                <Form.Item name="data_planejada" label="Fim planejado">
                                    <DatePicker style={{ width: '100%' }} format="DD/MM/YYYY" />
                                </Form.Item>
                            </Col>
                        </Row>
                        {editingEntrega ? (
                            <>
                                <EntregaFichaTarefasPanel
                                    entregaId={editingEntrega.id}
                                    projetoId={projetoId}
                                    sprintId={sprintIdWatch ?? editingEntrega.sprint_id}
                                    sprintNome={
                                        sprintsProjeto.find(
                                            (s) =>
                                                s.id ===
                                                (sprintIdWatch ?? editingEntrega.sprint_id),
                                        )?.nome ?? editingEntrega.sprint?.nome
                                    }
                                />
                                <EntregaFichaMrsPanel entregaId={editingEntrega.id} />
                            </>
                        ) : null}
                    </Form>
                </Modal>

                <ModalOpcoesEntrega
                    open={opcoesItem !== null}
                    onClose={() => setOpcoesItem(null)}
                    item={opcoesItem}
                    onVer={(item) => {
                        setOpcoesItem(null);
                        const full = resolveEntregaFromOpcoes(item);
                        if (full) openEdit(full);
                    }}
                    onEditar={(item) => {
                        setOpcoesItem(null);
                        const full = resolveEntregaFromOpcoes(item);
                        if (full) openEdit(full);
                    }}
                    onExcluir={(item) => {
                        setOpcoesItem(null);
                        const full = resolveEntregaFromOpcoes(item);
                        if (full) handleExcluirEntrega(full);
                    }}
                    onEntregar={(item) => {
                        setOpcoesItem(null);
                        handleEntregar(item.id);
                    }}
                    onAceitar={(item) => {
                        setOpcoesItem(null);
                        handleAceitar(item.id);
                    }}
                    onRejeitar={(item) => {
                        setOpcoesItem(null);
                        handleRejeitar(item.id);
                    }}
                />

                <ModalAceiteEntregaUatGate
                    open={uatGateState !== null}
                    contexto={uatGateState?.contexto ?? null}
                    confirmLoading={aceitarMutation.isPending}
                    onCancel={() => setUatGateState(null)}
                    onConfirmacaoUat={handleConfirmacaoUatGate}
                    onOverrideUat={handleOverrideUatGate}
                />
            </ProjetoLayout>

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

            <ListingColumnCustomizeModal
                open={colunasVisiveisModalOpen}
                onClose={() => setColunasVisiveisModalOpen(false)}
                catalog={ENTREGAS_PLANEJAMENTO_LIST_COLUMN_CATALOG}
                value={visibleColumnKeys}
                order={columnOrder}
                onApply={setVisibleColumnKeys}
                data-testid="planejamento-entregas-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} entrega(s) selecionada(s)`}
                actions={acoesMassaModal}
                fabAriaLabel={`Ações em massa — ${selectedRowKeys.length} entrega(s) selecionada(s)`}
                data-testid-fab="planejamento-entregas-fab-selecao-acoes"
                data-testid-modal="planejamento-entregas-modal-acoes-massa"
            />

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

            {isMobile ? (
                <MobilePageActionBar
                    onOpenFilters={abrirModalFiltros}
                    activeFiltersCount={filtrosAtivosCount}
                    filterButtonLabel="Filtros"
                    onRefresh={() => void refetch()}
                    refreshLoading={isFetching}
                    hideOpcoes
                />
            ) : null}
        </>
    );
}
