'use client';

/**
 * Stack tecnológica do projeto (`/projetos/[id]/software/stack`).
 * Seleção visual de stacks pré-cadastradas com resumo lateral e métricas.
 */

import {
    Boxes,
    CheckCircle2,
    ExternalLink,
    Layers3,
    MinusCircle,
    Save,
} from 'lucide-react';
import { ICON_SIZE_MD } from '@/components/icons';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import Link from 'next/link';
import { useParams } from 'next/navigation';
import { Alert, Button, Spin, Tag, Tooltip, Typography, Space } from 'antd';
import { message } from '@/lib/feedback/message';
import { notifyApiError } from '@/lib/feedback/notifyApiError';
import { useQueryCache } from '@/hooks/useQueryCache';
import { useMutationCache } from '@/hooks/useMutationCache';
import { PermissionGuard } from '@/components/permissions';
import { useProjetoWriteGates } from '@/features/projetos/hooks/useProjetoWriteGates';
import { queryKeys } from '@/lib/cache/queryKeys';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import { Projeto } from '@/types';
import ProjetoLayout from '@/components/layouts/ProjetoLayout';
import ContentCard from '@/components/layouts/ContentCard';
import MetricsGrid from '@/components/layouts/MetricsGrid';
import MetricCard from '@/components/layouts/MetricCard';
import { EmptyState } from '@/components/empty';
import { ModuleRelatedLinksPanel } from '@/components/navigation/ModuleRelatedLinksPanel';
import { MobilePageActionBar } from '@/components/filters/MobilePageActionBar';
import { useIsMobile } from '@/hooks/useIsMobile';
import { projetosParametrosPaths } from '@/lib/routes/projetosParametrosPaths';
import { projetosProjetoCanonical } from '@/lib/routes/projetosProjetoCanonical';
import { routeProjetoId } from '@/features/projetos/feira-list';
import { isAplicacaoReactTipologia } from '@/features/projetos/lib/resolveAplicacaoReactTipologiaCopy';
import { AplicacaoReactExportCsvButton } from '@/features/projetos/aplicacao-react-export';
import { recordReactModuleSectionOpened } from '@/lib/telemetry/aplicacaoReactTelemetry';
import { PROJETOS_SOFTWARE_STACK_RELATED_SURFACE } from './constants';
import styles from './projetoSoftwareStackScreen.module.scss';
import {
    ProjetoTipologicoSyncBanner,
    TIPOLOGICO_EMPTY_DOMAIN,
} from '@/features/projetos/projeto-tipologico-empty-state';

const TOOLTIP_SEM_PERMISSAO_STACK =
    'Sem permissão para salvar o catálogo nesta tela. Sincronize a stack pelo Cursor Pack ou peça a permissão de edição a um administrador.';

const { Text } = Typography;

export interface StackOption {
    id: number;
    nome: string;
    tipo_projeto_id: number | null;
    tipo_projeto?: { id: number; nome: string; codigo?: string } | null;
    tipoProjeto?: { id: number; nome: string; codigo?: string } | null;
    tipos_projeto?: { id: number; nome: string; codigo?: string }[];
    tecnologias?: { id: number; nome: string; categoria?: string }[];
}

function stackCompativelComTipo(stack: StackOption, tipoId: number): boolean {
    const tipos = stack.tipos_projeto ?? [];
    if (tipos.some((t) => t.id === tipoId)) {
        return true;
    }
    return stack.tipo_projeto_id === tipoId;
}

interface StacksResponse {
    data: StackOption[];
    meta?: { total: number; current_page: number; last_page: number };
}

type StackSelection = number | null | 'none';

const TECH_CATEGORY_COLORS: Record<string, string> = {
    backend: 'geekblue',
    frontend: 'purple',
    database: 'green',
    devops: 'orange',
    mobile: 'magenta',
    linguagem: 'cyan',
    framework: 'blue',
};

function resolveTipoProjeto(stack: StackOption) {
    return stack.tipo_projeto ?? stack.tipoProjeto ?? null;
}

function techTagColor(categoria?: string): string {
    if (!categoria) return 'default';
    const key = categoria.toLowerCase().trim();
    return TECH_CATEGORY_COLORS[key] ?? 'default';
}

interface StackOptionCardProps {
    stack: StackOption;
    selected: boolean;
    compatible: boolean;
    disabled?: boolean;
    onSelect: () => void;
}

function StackOptionCard({ stack, selected, compatible, disabled, onSelect }: StackOptionCardProps) {
    const tipos =
        stack.tipos_projeto && stack.tipos_projeto.length > 0
            ? stack.tipos_projeto
            : (() => {
                  const unico = resolveTipoProjeto(stack);
                  return unico ? [unico] : [];
              })();
    const tecnologias = stack.tecnologias ?? [];
    const visibleTechs = tecnologias.slice(0, 5);
    const overflow = tecnologias.length - visibleTechs.length;
    const tiposLabel = tipos.map((tipo) => tipo.nome).join(' · ');

    return (
        <button
            type="button"
            className={[styles.stackCard, selected ? styles.stackCardSelected : ''].filter(Boolean).join(' ')}
            onClick={disabled ? undefined : onSelect}
            disabled={disabled}
            aria-pressed={selected}
            aria-disabled={disabled || undefined}
            data-testid={`projeto-stack-option-${stack.id}`}
        >
            {selected ? (
                <span className={styles.stackCardSelectedMark} aria-hidden>
                    <CheckCircle2 size={16} />
                </span>
            ) : null}
            <div className={styles.stackCardHeader}>
                <span className={styles.stackCardIcon} aria-hidden>
                    <Boxes size={ICON_SIZE_MD} />
                </span>
                <div className={styles.stackCardTitleBlock}>
                    <div className={styles.stackCardTitleRow}>
                        <p className={styles.stackCardTitle}>{stack.nome}</p>
                        <span className={styles.stackCardCount}>
                            {tecnologias.length} tech{tecnologias.length === 1 ? '' : 's'}
                        </span>
                    </div>
                    {tiposLabel ? (
                        <p
                            className={[
                                styles.stackCardTipo,
                                compatible ? styles.stackCardTipoCompat : '',
                            ]
                                .filter(Boolean)
                                .join(' ')}
                        >
                            {tiposLabel}
                        </p>
                    ) : (
                        <p className={styles.stackCardTipo}>Sem tipo associado</p>
                    )}
                </div>
            </div>
            <div className={styles.stackCardFooter}>
                {visibleTechs.length > 0 ? (
                    <div className={styles.stackCardTechs}>
                        {visibleTechs.map((tech) => (
                            <Tag
                                key={tech.id}
                                color={techTagColor(tech.categoria)}
                                className={styles.techTag}
                            >
                                {tech.nome}
                            </Tag>
                        ))}
                        {overflow > 0 ? (
                            <Tag className={styles.techOverflow}>+{overflow}</Tag>
                        ) : null}
                    </div>
                ) : (
                    <p className={styles.stackCardEmptyTechs}>Sem tecnologias no catálogo</p>
                )}
            </div>
        </button>
    );
}

export function ProjetoSoftwareStackScreen() {
    const params = useParams();
    const id = routeProjetoId(params);
    const isMobile = useIsMobile();
    const { canEditar, permsLoading } = useProjetoWriteGates();
    const [selectedStackId, setSelectedStackId] = useState<StackSelection | undefined>(undefined);
    const resolverAttemptedRef = useRef(false);

    const { data: projetoResponse, isLoading: loadingProjeto } = useQueryCache<
        Projeto | { projeto?: Projeto; metricas?: unknown }
    >({
        queryKey: queryKeys.projetos.detail(id),
        endpoint: API_ENDPOINTS.projetos.show(id),
        enabled: !!id,
        staleTime: 1 * 60 * 1000,
        gcTime: 5 * 60 * 1000,
    });

    const projeto =
        projetoResponse && typeof projetoResponse === 'object' && 'projeto' in projetoResponse
            ? (projetoResponse as { projeto?: Projeto }).projeto
            : (projetoResponse as Projeto | undefined);

    const isAplicacaoReact = isAplicacaoReactTipologia(projeto?.categoria_projeto?.codigo);

    // TASK-APR-047 — telemetria secção Stack
    useEffect(() => {
        if (!isAplicacaoReact) return;
        const n = Number(id);
        if (!Number.isFinite(n)) return;
        recordReactModuleSectionOpened({ projeto_id: n, section: 'stack' });
    }, [isAplicacaoReact, id]);

    const { data: stacksResponse, isLoading: loadingStacks } = useQueryCache<StacksResponse>({
        queryKey: queryKeys.stacks.listsAll(),
        endpoint: API_ENDPOINTS.stacks.index,
        params: { per_page: 200, page: 1 },
        enabled: true,
    });

    const updateMutation = useMutationCache({
        endpoint: API_ENDPOINTS.projetos.update(id),
        method: 'PUT',
        invalidateQueries: [queryKeys.projetos.detail(id), queryKeys.projetos.lists()],
        onSuccess: () => {
            message.success('Stack do projeto salva com sucesso.');
        },
        onError: (error: unknown) => {
            notifyApiError(error, 'Erro ao salvar a stack do projeto.', 'stack');
        },
    });

    const resolverMutation = useMutationCache({
        endpoint: API_ENDPOINTS.projetos.software.stackResolver(id),
        method: 'POST',
        invalidateQueries: [queryKeys.projetos.detail(id), [...queryKeys.stacks.lists(), 'all']],
        onSuccess: (response: unknown) => {
            const payload =
                response && typeof response === 'object' && 'data' in response
                    ? (response as { data?: { status?: string; stack_nome?: string } }).data
                    : undefined;
            const status = payload?.status;
            if (status === 'cadastrado_e_vinculado') {
                message.success(
                    payload?.stack_nome
                        ? `Stack "${payload.stack_nome}" cadastrada e vinculada ao projeto.`
                        : 'Stack cadastrada e vinculada ao projeto.',
                );
            } else if (status === 'vinculado_existente') {
                message.success(
                    payload?.stack_nome
                        ? `Stack "${payload.stack_nome}" vinculada ao projeto.`
                        : 'Stack existente vinculada ao projeto.',
                );
            }
        },
        onError: (error: unknown) => {
            notifyApiError(error, 'Não foi possível resolver a stack automaticamente.', 'stack-resolver');
        },
    });
    const { mutate: resolverStack, isPending: resolvingStack } = resolverMutation;

    const stacks = useMemo(
        () => (Array.isArray(stacksResponse?.data) ? stacksResponse.data : []),
        [stacksResponse?.data],
    );

    const categoriaProjetoId = projeto?.categoria_projeto?.id;
    const categoriaNome = projeto?.categoria_projeto?.nome;

    const { stacksCompat, stacksOutras } = useMemo(() => {
        if (!categoriaProjetoId) {
            return { stacksCompat: stacks, stacksOutras: [] as StackOption[] };
        }
        return {
            stacksCompat: stacks.filter((s) => stackCompativelComTipo(s, categoriaProjetoId)),
            stacksOutras: stacks.filter((s) => !stackCompativelComTipo(s, categoriaProjetoId)),
        };
    }, [stacks, categoriaProjetoId]);

    const currentStackId = projeto?.stack_id ?? null;

    useEffect(() => {
        if (!id || permsLoading || loadingProjeto || !canEditar) {
            return;
        }
        if (currentStackId != null || resolverAttemptedRef.current) {
            return;
        }
        resolverAttemptedRef.current = true;
        resolverStack({});
    }, [id, permsLoading, loadingProjeto, canEditar, currentStackId, resolverStack]);

    const selectedId: StackSelection =
        selectedStackId !== undefined
            ? selectedStackId
            : currentStackId === null
              ? 'none'
              : currentStackId;

    const stackAtual = useMemo(() => {
        const sid = projeto?.stack_id;
        if (sid == null) return null;
        return stacks.find((s) => s.id === sid) ?? null;
    }, [stacks, projeto?.stack_id]);

    const stackSelecionada = useMemo(() => {
        if (selectedId === 'none' || selectedId === null) return null;
        return stacks.find((s) => s.id === selectedId) ?? null;
    }, [stacks, selectedId]);

    const dirty =
        (selectedId === 'none' || selectedId === null ? null : selectedId) !== (projeto?.stack_id ?? null);

    const handleSave = () => {
        const stackId = selectedId === 'none' || selectedId === null ? null : selectedId;
        updateMutation.mutate({ stack_id: stackId });
    };

    if (loadingProjeto && !projeto) {
        return (
            <ProjetoLayout projetoId={id} pageTitle="Stack" pageIcon="cubes" titleSection="Stack">
                <div className={styles.loadingWrap}>
                    <Spin size="large" />
                    <Text type="secondary">Carregando projeto…</Text>
                </div>
            </ProjetoLayout>
        );
    }

    const somenteLeitura = !canEditar && !permsLoading;

    const renderStackSection = (items: StackOption[], compatible: boolean, title: string) => {
        if (items.length === 0) return null;
        return (
            <section className={styles.sectionBlock} aria-label={title}>
                <div className={styles.sectionHeader}>
                    <h3 className={styles.sectionTitle}>{title}</h3>
                    <Tag>{items.length}</Tag>
                </div>
                <div className={styles.stackGrid}>
                    {items.map((stack) => (
                        <StackOptionCard
                            key={stack.id}
                            stack={stack}
                            selected={selectedId === stack.id}
                            compatible={compatible}
                            disabled={somenteLeitura}
                            onSelect={() => setSelectedStackId(stack.id)}
                        />
                    ))}
                </div>
            </section>
        );
    };

    return (
        <ProjetoLayout
            projetoId={id}
            pageTitle="Stack"
            pageIcon="cubes"
            titleSection="Stack"
            breadcrumbItems={[
                { title: 'PROJETO' },
                { title: projeto?.nome || 'Projeto' },
                { title: 'Stack' },
            ]}
            headerAction={
                isAplicacaoReact ? (
                    <Space wrap size={8} align="center">
                        <AplicacaoReactExportCsvButton projetoId={id} kind="stack" />
                    </Space>
                ) : undefined
            }
        >
            <div className={styles.page} data-testid="projeto-software-stack-screen">
                {!currentStackId ? (
                    <ProjetoTipologicoSyncBanner
                        projetoId={id}
                        title="Stack do catálogo não vinculada"
                        domainDescription={
                            resolvingStack
                                ? 'Verificando STACK.md e catálogo de stacks…'
                                : TIPOLOGICO_EMPTY_DOMAIN.stack
                        }
                        data-testid="projeto-stack-sync-banner"
                    />
                ) : null}

                <section className={styles.hero} aria-labelledby="stack-hero-title">
                    <div className={styles.heroTop}>
                        <div className={styles.heroCopy}>
                            <Typography.Title level={4} id="stack-hero-title" className={styles.heroTitle}>
                                Defina a stack tecnológica do projeto
                            </Typography.Title>
                            <p className={styles.heroDescription}>
                                Escolha um conjunto pré-configurado de tecnologias alinhado ao tipo de
                                projeto. A decisão orienta arquitetura, deploy e expectativas com o
                                cliente. A análise do repositório (package.json, composer.json, STACK.md)
                                também entra pelo Cursor Pack, na sincronização com o Waygest.
                            </p>
                        </div>
                        <div className={styles.heroLinks}>
                            <Link href={projetosParametrosPaths.stacks}>
                                <Button type="link" size="small" icon={<ExternalLink size={14} aria-hidden />}>
                                    Gerenciar catálogo de stacks
                                </Button>
                            </Link>
                            <Link href={projetosProjetoCanonical.projetoConectar(id)}>
                                <Button type="link" size="small" icon={<ExternalLink size={14} aria-hidden />}>
                                    Conectar e sincronizar (Cursor)
                                </Button>
                            </Link>
                        </div>
                    </div>
                    <MetricsGrid columns={3} mobileCompactCollapsible>
                        <MetricCard
                            icon={<Layers3 size={ICON_SIZE_MD} aria-hidden />}
                            label="Stack atual"
                            value={stackAtual?.nome ?? 'Não definida'}
                            subvalue={
                                stackAtual
                                    ? `${stackAtual.tecnologias?.length ?? 0} tecnologias`
                                    : 'Selecione uma opção abaixo'
                            }
                            variant={stackAtual ? 'ativos' : 'planejamento'}
                        />
                        <MetricCard
                            icon={<Boxes size={ICON_SIZE_MD} aria-hidden />}
                            label="Techs do catálogo"
                            value={stackAtual?.tecnologias?.length ?? 0}
                            subvalue="Do stack_id — distinto do inventário sync"
                            variant="projetos"
                        />
                        <MetricCard
                            icon={<CheckCircle2 size={ICON_SIZE_MD} aria-hidden />}
                            label="Disponíveis"
                            value={stacks.length}
                            subvalue={
                                categoriaNome
                                    ? `${stacksCompat.length} compatíveis com ${categoriaNome}`
                                    : 'Stacks no catálogo'
                            }
                            variant="sprints"
                        />
                    </MetricsGrid>
                </section>

                {somenteLeitura ? (
                    <Alert
                        type="info"
                        showIcon
                        data-testid="projeto-stack-somente-leitura"
                        message="Como atualizar a stack sem permissão de edição"
                        description={
                            <span>
                                O botão Salvar permanece desativado porque esta tela altera o vínculo com um
                                conjunto do catálogo (permissão projetos.editar). A stack detectada no código
                                continua sendo enviada pelo Cursor: sincronize o projeto no IDE e confira
                                Tecnologias e Contexto. Se precisar escolher um conjunto do catálogo aqui,
                                peça acesso a um administrador.
                            </span>
                        }
                        action={
                            <Space direction="vertical" size={4}>
                                <Link href={projetosProjetoCanonical.projetoConectar(id)}>
                                    <Button size="small">Conectar projeto</Button>
                                </Link>
                                <Link href={projetosProjetoCanonical.desenvolvimentoGuiaCursorPack(id)}>
                                    <Button size="small">Guia Cursor Pack</Button>
                                </Link>
                                <Link href={projetosProjetoCanonical.projetoTecnologias(id)}>
                                    <Button size="small">Ver tecnologias</Button>
                                </Link>
                            </Space>
                        }
                    />
                ) : null}

                <div className={styles.workspace}>
                    {isMobile ? (
                        <aside className={styles.summaryPanel} aria-label="Resumo da seleção">
                            <ContentCard title="Resumo da seleção" flexColumn>
                                <div className={styles.summaryCard}>
                                    <div className={styles.summaryStatus}>
                                        <span className={styles.summaryStatusLabel}>Seleção atual</span>
                                        <p className={styles.summaryStatusValue}>
                                            {stackSelecionada?.nome ?? 'Nenhuma stack'}
                                        </p>
                                    </div>

                                    {stackSelecionada?.tecnologias &&
                                    stackSelecionada.tecnologias.length > 0 ? (
                                        <div>
                                            <span className={styles.summaryStatusLabel}>
                                                Tecnologias incluídas
                                            </span>
                                            <div className={styles.summaryTechList}>
                                                {stackSelecionada.tecnologias.map((tech) => (
                                                    <Tag
                                                        key={tech.id}
                                                        color={techTagColor(tech.categoria)}
                                                        className={styles.techTag}
                                                    >
                                                        {tech.nome}
                                                    </Tag>
                                                ))}
                                            </div>
                                        </div>
                                    ) : (
                                        <p className={styles.summaryHint}>
                                            {selectedId === 'none'
                                                ? 'O projeto ficará sem stack vinculada até escolher uma opção.'
                                                : 'Selecione uma stack para ver o detalhe das tecnologias.'}
                                        </p>
                                    )}

                                    {somenteLeitura ? (
                                        <p className={styles.summaryHint}>
                                            Consulta apenas. Para gravar tecnologias a partir do repositório,
                                            use a sincronização Cursor (Conectar projeto).
                                        </p>
                                    ) : null}

                                    {dirty && !somenteLeitura ? (
                                        <p className={styles.summaryHint}>
                                            <strong>Alteração pendente.</strong> Use Salvar na barra inferior.
                                        </p>
                                    ) : null}
                                </div>
                            </ContentCard>
                        </aside>
                    ) : null}

                    <div className={styles.selectionPanel}>
                        <ContentCard
                            title="Escolha a stack"
                            icon={<Boxes size={ICON_SIZE_MD} aria-hidden />}
                            loading={loadingStacks}
                        >
                            {loadingStacks ? (
                                <div className={styles.loadingWrap}>
                                    <Spin size="large" />
                                </div>
                            ) : stacks.length === 0 ? (
                                <EmptyState
                                    icon={<Boxes size={40} aria-hidden />}
                                    title="Nenhuma stack cadastrada"
                                    description="Crie stacks em Configurações → Projetos para disponibilizar opções neste projeto."
                                    action={
                                        <Link href={projetosParametrosPaths.stacks}>
                                            <Button type="primary">Cadastrar stacks</Button>
                                        </Link>
                                    }
                                />
                            ) : (
                                <>
                                    <button
                                        type="button"
                                        className={[
                                            styles.stackCard,
                                            styles.stackCardNone,
                                            selectedId === 'none' ? styles.stackCardSelected : '',
                                        ]
                                            .filter(Boolean)
                                            .join(' ')}
                                        onClick={somenteLeitura ? undefined : () => setSelectedStackId('none')}
                                        disabled={somenteLeitura}
                                        aria-pressed={selectedId === 'none'}
                                        aria-disabled={somenteLeitura || undefined}
                                        data-testid="projeto-stack-option-none"
                                    >
                                        <div className={styles.stackCardHeader}>
                                            <span className={styles.stackCardIcon} aria-hidden>
                                                <MinusCircle size={ICON_SIZE_MD} />
                                            </span>
                                            <div className={styles.stackCardTitleBlock}>
                                                <p className={styles.stackCardTitle}>Nenhuma stack</p>
                                                <p className={styles.stackCardTipo}>
                                                    Não vincular stack a este projeto
                                                </p>
                                            </div>
                                        </div>
                                    </button>

                                    {renderStackSection(
                                        stacksCompat,
                                        true,
                                        categoriaNome
                                            ? `Compatíveis com ${categoriaNome}`
                                            : 'Stacks disponíveis',
                                    )}
                                    {renderStackSection(stacksOutras, false, 'Outras stacks')}
                                </>
                            )}
                        </ContentCard>
                    </div>

                    {!isMobile ? (
                        <aside className={styles.summaryPanel} aria-label="Resumo da seleção">
                        <ContentCard title="Resumo da seleção" flexColumn>
                            <div className={styles.summaryCard}>
                                <div className={styles.summaryStatus}>
                                    <span className={styles.summaryStatusLabel}>Seleção atual</span>
                                    <p className={styles.summaryStatusValue}>
                                        {stackSelecionada?.nome ?? 'Nenhuma stack'}
                                    </p>
                                </div>

                                {stackSelecionada?.tecnologias && stackSelecionada.tecnologias.length > 0 ? (
                                    <div>
                                        <span className={styles.summaryStatusLabel}>Tecnologias incluídas</span>
                                        <div className={styles.summaryTechList}>
                                            {stackSelecionada.tecnologias.map((tech) => (
                                                <Tag
                                                    key={tech.id}
                                                    color={techTagColor(tech.categoria)}
                                                    className={styles.techTag}
                                                >
                                                    {tech.nome}
                                                </Tag>
                                            ))}
                                        </div>
                                    </div>
                                ) : (
                                    <p className={styles.summaryHint}>
                                        {selectedId === 'none'
                                            ? 'O projeto ficará sem stack vinculada até escolher uma opção.'
                                            : 'Selecione uma stack para ver o detalhe das tecnologias.'}
                                    </p>
                                )}

                                {somenteLeitura ? (
                                    <p className={styles.summaryHint}>
                                        Consulta apenas. Para gravar tecnologias a partir do repositório, use
                                        a sincronização Cursor (Conectar projeto).
                                    </p>
                                ) : null}

                                {dirty && !somenteLeitura ? (
                                    <p className={styles.summaryHint}>
                                        <strong>Alteração pendente.</strong> Salve para aplicar ao projeto.
                                    </p>
                                ) : null}

                                <div className={styles.summaryActions}>
                                    <PermissionGuard
                                        permission="projetos.editar"
                                        module="projetos"
                                        action="update"
                                        fallback={
                                            <Tooltip title={TOOLTIP_SEM_PERMISSAO_STACK}>
                                                <span style={{ display: 'block', width: '100%' }}>
                                                    <Button
                                                        type="primary"
                                                        block
                                                        size="large"
                                                        disabled
                                                        icon={<Save size={ICON_SIZE_MD} aria-hidden />}
                                                        data-testid="projeto-stack-save"
                                                    >
                                                        Salvar stack
                                                    </Button>
                                                </span>
                                            </Tooltip>
                                        }
                                    >
                                        <Tooltip
                                            title={
                                                !canEditar && !permsLoading
                                                    ? TOOLTIP_SEM_PERMISSAO_STACK
                                                    : undefined
                                            }
                                        >
                                            <span style={{ display: 'block', width: '100%' }}>
                                                <Button
                                                    type="primary"
                                                    block
                                                    size="large"
                                                    onClick={handleSave}
                                                    loading={updateMutation.isPending}
                                                    disabled={!dirty || !canEditar || permsLoading}
                                                    icon={<Save size={ICON_SIZE_MD} aria-hidden />}
                                                    data-testid="projeto-stack-save"
                                                >
                                                    Salvar stack
                                                </Button>
                                            </span>
                                        </Tooltip>
                                    </PermissionGuard>
                                    {stackAtual && selectedId !== stackAtual.id && selectedId !== 'none' ? (
                                        <Text type="secondary" style={{ fontSize: 12, textAlign: 'center' }}>
                                            Substitui "{stackAtual.nome}"
                                        </Text>
                                    ) : null}
                                </div>
                            </div>
                        </ContentCard>
                    </aside>
                    ) : null}
                </div>

                <ModuleRelatedLinksPanel
                    surfaceKey={PROJETOS_SOFTWARE_STACK_RELATED_SURFACE}
                    variant="footer"
                    pagePrefix="projeto-software-stack"
                    projetoId={id}
                />
            </div>

            {isMobile && !somenteLeitura ? (
                <MobilePageActionBar
                    hideOpcoes
                    trailingAction={
                        <PermissionGuard
                            permission="projetos.editar"
                            module="projetos"
                            action="update"
                            fallback={
                                <Tooltip title={TOOLTIP_SEM_PERMISSAO_STACK}>
                                    <span>
                                        <Button
                                            type="primary"
                                            disabled
                                            icon={<Save size={ICON_SIZE_MD} aria-hidden />}
                                            data-testid="projeto-stack-save"
                                        >
                                            Salvar
                                        </Button>
                                    </span>
                                </Tooltip>
                            }
                        >
                            <Tooltip
                                title={
                                    !canEditar && !permsLoading
                                        ? TOOLTIP_SEM_PERMISSAO_STACK
                                        : dirty
                                          ? 'Salvar stack selecionada'
                                          : 'Nenhuma alteração para salvar'
                                }
                            >
                                <span>
                                    <Button
                                        type="primary"
                                        onClick={handleSave}
                                        loading={updateMutation.isPending}
                                        disabled={!dirty || !canEditar || permsLoading}
                                        icon={<Save size={ICON_SIZE_MD} aria-hidden />}
                                        data-testid="projeto-stack-save"
                                    >
                                        Salvar
                                    </Button>
                                </span>
                            </Tooltip>
                        </PermissionGuard>
                    }
                />
            ) : null}
        </ProjetoLayout>
    );
}
