import { useEffect, useMemo, useRef, useState } from "react";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import {
  AlertCircle,
  ArrowLeft,
  CheckCircle2,
  ExternalLink,
  FileText,
  ListChecks,
  Loader2,
  Pencil,
  Plus,
  Repeat,
  RotateCcw,
  Sigma,
  Target,
  Trash2,
  User,
  Wallet,
} from "lucide-react";
import { toast } from "sonner";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { useAuthAccess } from "@/contexts/AuthAccessContext";
import { fechamentoBancoPontosService } from "@/services/fechamento/bancoPontos";
import { fechamentoCompetenciasService, type CompetenciaItem } from "@/services/fechamento/competencias";
import { fechamentoFechamentosService, type FechamentoTarefaItem } from "@/services/fechamento/fechamentos";

function formatPontos(valor: number): string {
  return valor.toLocaleString("pt-BR", { minimumFractionDigits: 0, maximumFractionDigits: 4 });
}

/** Ex.: toast após concluir — vírgula pt-BR e no máximo 2 casas decimais. */
function formatPontosAte2Casas(valor: number): string {
  if (!Number.isFinite(valor)) return "—";
  return valor.toLocaleString("pt-BR", { minimumFractionDigits: 0, maximumFractionDigits: 2 });
}

/** Alinhado ao `requerMotivoAjuste`: evita "-0" e cor errada por ruído de float. */
const SALDO_PONTOS_EPS = 0.0001;

function corSaldoPontos(valor: number): string {
  if (!Number.isFinite(valor)) return "text-foreground";
  if (valor > SALDO_PONTOS_EPS) return "text-emerald-600";
  if (valor < -SALDO_PONTOS_EPS) return "text-red-600";
  return "text-foreground";
}

function formatPontosSaldoModal(valor: number): string {
  if (!Number.isFinite(valor)) return "—";
  const v = Math.abs(valor) < SALDO_PONTOS_EPS ? 0 : valor;
  return formatPontos(v);
}

function parsePontuacaoInput(value: string): number {
  const normalized = value.trim().replace(/\s/g, "").replace(",", ".");
  const parsed = Number(normalized);
  return Number.isFinite(parsed) ? parsed : Number.NaN;
}

const PONTUACAO_LANCAMENTO_MAX_FRAC = 2;

/** Pontuação do modal de lançamento: ≥ 0, até duas casas decimais (o tipo bonus/desconto define o sinal no backend). */
function sanitizePontuacaoLancamentoDigitando(raw: string): string {
  const t = raw.trim().replace(/\s/g, "");
  if (t === "") return "";
  if (t === "," || t === ".") return "0" + t;

  const c = t.indexOf(",");
  const d = t.indexOf(".");
  const si = c >= 0 && d >= 0 ? Math.min(c, d) : c >= 0 ? c : d >= 0 ? d : -1;
  const sep = si >= 0 ? t[si]! : null;

  if (sep == null) {
    const digits = t.replace(/\D/g, "");
    if (digits === "") return "";
    const n = Number(digits);
    if (n < 0) return "0";
    return digits;
  }

  const intStr = t.slice(0, si).replace(/\D/g, "");
  const rawAfter = t.slice(si + 1);
  const fracStr = rawAfter.replace(/\D/g, "").slice(0, PONTUACAO_LANCAMENTO_MAX_FRAC);
  const intPart = intStr === "" ? "0" : intStr;
  if (t.endsWith(sep) && fracStr.length === 0) {
    return intPart + sep;
  }
  return intPart + sep + fracStr;
}

/** Valor em R$ no modal de lançamento: dígitos + um separador decimal, até 2 casas (pt-BR). */
function sanitizeValorRealLancamentoDigitando(raw: string): string {
  const cleaned = raw.replace(/[^\d.,]/g, "");
  if (!cleaned) return "";

  let int = "";
  let frac = "";
  let sawSeparator = false;

  for (const ch of cleaned) {
    if (ch === "," || ch === ".") {
      if (!sawSeparator) sawSeparator = true;
      continue;
    }
    if (!sawSeparator) int += ch;
    else if (frac.length < 2) frac += ch;
  }

  if (!sawSeparator) return int;
  return frac.length > 0 ? `${int},${frac}` : `${int},`;
}

function parseValorRealMonetarioInput(raw: string): number {
  let t = raw.trim().replace(/\s/g, "").replace(/R\$\s?/gi, "");
  if (!t) return Number.NaN;
  if (t.includes(",") && t.includes(".")) {
    t = t.replace(/\./g, "").replace(",", ".");
  } else if (t.includes(",")) {
    t = t.replace(",", ".");
  }
  return Number(t);
}

/** Pontuação: no máximo 2 casas decimais, sempre para cima (ex.: 1,1111 → 1,12). Valores já em centésimos exatos (ex.: 1,00) não são inflados por erro de float. */
function pontuacaoParaCimaAte2Casas(value: number): number {
  if (!Number.isFinite(value)) return value;
  if (value === 0) return 0;
  const sign = value < 0 ? -1 : 1;
  const m = Math.abs(value);
  const scaled = m * 100;
  const nearest = Math.round(scaled);
  const n =
    Math.abs(scaled - nearest) < 1e-7 ? nearest : Math.ceil(scaled - 1e-9);
  return sign * (n / 100);
}

function toPontuacaoInput(value: number): string {
  if (!Number.isFinite(value)) return "0";
  const rounded = pontuacaoParaCimaAte2Casas(value);
  return String(rounded);
}

function formatDateOnly(value: string | null): string {
  if (!value) return "—";
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return "—";
  return parsed.toLocaleDateString("pt-BR");
}

function formatDateTime(value: string | null): string {
  if (!value) return "—";
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return "—";
  return parsed.toLocaleString("pt-BR", {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

function normalizeTextFilter(value: string): string {
  return value.trim().toLocaleLowerCase("pt-BR");
}

function toFilterDate(value: string | null): string {
  if (!value) return "";
  const isoMatch = value.match(/^\d{4}-\d{2}-\d{2}/);
  if (isoMatch) return isoMatch[0];

  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return "";
  const year = parsed.getFullYear();
  const month = String(parsed.getMonth() + 1).padStart(2, "0");
  const day = String(parsed.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}

function formatCompetenciaMesAno(item: Pick<CompetenciaItem, "mes" | "ano">): string {
  return `${String(item.mes).padStart(2, "0")}/${item.ano}`;
}

function getTipoLancamentoLabel(tipo: string): string {
  if (tipo === "bonus") return "Bônus Comercial";
  if (tipo === "desconto") return "Desconto Comercial";
  return tipo;
}

type FechamentoDetalhesLocationState = {
  competenciaId?: string;
  status?: "em_aberto" | "fechado";
  readonlyView?: boolean;
};

export default function FechamentoDetalhes() {
  const location = useLocation();
  const navigate = useNavigate();
  const { me, papel } = useAuthAccess();
  const { id: fechamentoId = "" } = useParams();
  const initialState = (location.state as FechamentoDetalhesLocationState | null) ?? null;
  const [competenciaId, setCompetenciaId] = useState(initialState?.competenciaId ?? "");
  const [fechamentoStatus, setFechamentoStatus] = useState<"em_aberto" | "fechado">(initialState?.status ?? "em_aberto");
  const [loading, setLoading] = useState(true);
  const [tarefas, setTarefas] = useState<FechamentoTarefaItem[]>([]);
  const [estadoRevisaoInicial, setEstadoRevisaoInicial] = useState<Record<string, boolean>>({});
  const [bulkUpdatingRevisao, setBulkUpdatingRevisao] = useState(false);
  const [deletingTaskId, setDeletingTaskId] = useState<string | null>(null);
  const [isLancamentoOpen, setIsLancamentoOpen] = useState(false);
  const [savingLancamento, setSavingLancamento] = useState(false);
  const [isConcluirOpen, setIsConcluirOpen] = useState(false);
  const [concluindo, setConcluindo] = useState(false);
  const [exportandoPdf, setExportandoPdf] = useState(false);
  const [pontuacaoPagaInput, setPontuacaoPagaInput] = useState("");
  const [motivoAjuste, setMotivoAjuste] = useState("");
  const [isReabrirOpen, setIsReabrirOpen] = useState(false);
  const [reabrindo, setReabrindo] = useState(false);
  const [motivoReabertura, setMotivoReabertura] = useState("");
  const [lancamentoTipo, setLancamentoTipo] = useState<"bonus" | "desconto">("bonus");
  const [lancamentoDescricao, setLancamentoDescricao] = useState("");
  const [lancamentoModo, setLancamentoModo] = useState<"pontos" | "real">("pontos");
  const [lancamentoPontuacao, setLancamentoPontuacao] = useState("0");
  const [lancamentoValorReal, setLancamentoValorReal] = useState("");
  const [pontuacaoMeta, setPontuacaoMeta] = useState<number | null>(null);
  const [parceiroId, setParceiroId] = useState<string | null>(null);
  const [parceiroNome, setParceiroNome] = useState<string | null>(null);
  const [parceiroFator, setParceiroFator] = useState<number | null>(null);
  const [saldoBancoAtual, setSaldoBancoAtual] = useState<number | null>(null);
  const [loadingSaldoBanco, setLoadingSaldoBanco] = useState(false);
  const [erroSaldoBanco, setErroSaldoBanco] = useState(false);
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
  const [deletingTarefa, setDeletingTarefa] = useState<FechamentoTarefaItem | null>(null);
  const [isReprocessAsanaOpen, setIsReprocessAsanaOpen] = useState(false);
  const [reprocessandoAsana, setReprocessandoAsana] = useState(false);
  const [isAlterarCompetenciaOpen, setIsAlterarCompetenciaOpen] = useState(false);
  const [loadingCompetenciasAbertas, setLoadingCompetenciasAbertas] = useState(false);
  const [savingAlteracaoCompetencia, setSavingAlteracaoCompetencia] = useState(false);
  const [competenciasAbertas, setCompetenciasAbertas] = useState<CompetenciaItem[]>([]);
  const [tarefaAlteracaoCompetencia, setTarefaAlteracaoCompetencia] = useState<FechamentoTarefaItem | null>(null);
  const [competenciaDestinoId, setCompetenciaDestinoId] = useState("");
  const [motivoAlteracaoCompetencia, setMotivoAlteracaoCompetencia] = useState("");
  const [isEditarOpen, setIsEditarOpen] = useState(false);
  const [savingEdicao, setSavingEdicao] = useState(false);
  const [editingTarefa, setEditingTarefa] = useState<FechamentoTarefaItem | null>(null);
  const [edicaoNumeroTicket, setEdicaoNumeroTicket] = useState("");
  const [edicaoDescricao, setEdicaoDescricao] = useState("");
  const [edicaoCliente, setEdicaoCliente] = useState("");
  const [edicaoTempoMinutos, setEdicaoTempoMinutos] = useState("");
  const [edicaoPontuacao, setEdicaoPontuacao] = useState("");
  const tableScrollRef = useRef<HTMLDivElement | null>(null);
  const stickyScrollRef = useRef<HTMLDivElement | null>(null);
  const stickyScrollSpacerRef = useRef<HTMLDivElement | null>(null);
  const [showStickyScrollbar, setShowStickyScrollbar] = useState(false);
  const [showFilters, setShowFilters] = useState(false);
  const [filtroDescricao, setFiltroDescricao] = useState("");
  const [filtroTicket, setFiltroTicket] = useState("");
  const [filtroCliente, setFiltroCliente] = useState("");
  const [filtroDataConclusao, setFiltroDataConclusao] = useState("");
  const [competenciaStatus, setCompetenciaStatus] = useState<"em_aberto" | "concluido">("em_aberto");
  const isFechado = fechamentoStatus === "fechado";
  const isCompetenciaConcluida = competenciaStatus === "concluido";
  const isReadonly = Boolean(initialState?.readonlyView) || isFechado || isCompetenciaConcluida;
  const caps = me?.capabilities;
  const podeTarefaEditarRevisao = caps?.fechamentos.tarefaEditarRevisao ?? false;
  const podeTarefaLancarAjuste = caps?.fechamentos.tarefaLancarAjuste ?? false;
  const verFatorParceiro = caps?.parceiros.verFator ?? false;
  const fatorParceiroValidoParaReal =
    parceiroFator != null && Number.isFinite(parceiroFator) && parceiroFator > 0;
  /** Quem vê o fator na API sabe se está cadastrado; sem fator não dá para lançar em Real no front. */
  const lancamentoEmRealBloqueado = verFatorParceiro && !fatorParceiroValidoParaReal;
  const podeReprocessarAsana = caps?.fechamentos.reprocessarAsana ?? false;
  const podeConcluirFechamento = caps?.fechamentos.concluir ?? false;
  const podeReabrirFechamento = caps?.fechamentos.reabrir ?? false;
  const podeExportarPdf = caps?.fechamentos.exportarPdf ?? false;
  const supervisorPodeExportarPdf =
    podeExportarPdf &&
    (papel !== "supervisor" || Boolean(me?.parceiroId && parceiroId != null && parceiroId === me.parceiroId));
  const podeAlterarCompetenciaTarefa = caps?.fechamentos.tarefaAlterarCompetencia ?? false;
  const podeExcluirLancamentoManual = caps?.fechamentos.tarefaExcluirManual ?? false;
  const bloqueioEdicaoTarefa = isReadonly || !podeTarefaEditarRevisao;

  const lancamentoPreviewPontos = useMemo(() => {
    if (lancamentoModo !== "real" || parceiroFator == null || !(parceiroFator > 0)) return null;
    const valor = parseValorRealMonetarioInput(lancamentoValorReal.trim());
    if (!Number.isFinite(valor) || valor <= 0) return null;
    return pontuacaoParaCimaAte2Casas(valor / (parceiroFator * 3));
  }, [lancamentoModo, parceiroFator, lancamentoValorReal]);

  const totais = useMemo(() => {
    const aprovadas = tarefas.filter((t) => t.estaRevisada);
    const pontosAprovados = aprovadas.reduce((acc, t) => acc + Number(t.pontuacao || 0), 0);
    const pontosTotalMes = tarefas.reduce((acc, t) => acc + Number(t.pontuacao || 0), 0);
    return {
      /** Soma das pontuações em tarefas marcadas como revisadas (equivale ao que entra no fechamento). */
      pontos: pontosAprovados,
      /** Soma de todas as pontuações das tarefas listadas no fechamento (mês). */
      pontosTotalMes,
    };
  }, [tarefas]);
  const pontuacaoPagaNumero = parsePontuacaoInput(pontuacaoPagaInput || "0");
  const bancoCalculado = totais.pontos - pontuacaoPagaNumero;
  const diferencaParaMeta = totais.pontos - Number(pontuacaoMeta ?? 0);
  const diferencaPagamentoMeta = pontuacaoPagaNumero - Number(pontuacaoMeta ?? 0);
  const requerMotivoAjuste = Number.isFinite(bancoCalculado) && Math.abs(bancoCalculado) > 0.0001;
  const pontuacaoTotalLabel = toPontuacaoInput(totais.pontos);
  const isValorEditado = pontuacaoPagaInput.trim() !== pontuacaoTotalLabel;
  const saldoBancoPosFechamento =
    saldoBancoAtual != null ? saldoBancoAtual + bancoCalculado : null;
  const dividaParaQuitar =
    saldoBancoAtual != null && saldoBancoAtual < 0 ? -saldoBancoAtual : 0;
  const saldoPositivoDisponivel =
    saldoBancoAtual != null && saldoBancoAtual > 0 ? saldoBancoAtual : 0;
  /** Zera o banco: saldo + (aprovados − pago) = 0 ⇒ pago = aprovados + saldo (saldo negativo = dívida). */
  const sugestaoQuitarDivida = totais.pontos - dividaParaQuitar;
  /** Zera o banco com saldo positivo: precisa movimento negativo no banco ⇒ pago = aprovados + saldo. */
  const sugestaoUsarSaldoPositivo = totais.pontos + saldoPositivoDisponivel;
  const todasTarefasRevisadas = tarefas.length > 0 && tarefas.every((tarefa) => tarefa.estaRevisada);
  const competenciasDestino = useMemo(
    () => competenciasAbertas.filter((item) => item.id !== competenciaId),
    [competenciasAbertas, competenciaId],
  );
  const hasActiveFilters = Boolean(
    filtroDescricao ||
      filtroTicket ||
      filtroCliente ||
      filtroDataConclusao,
  );
  const tarefasFiltradas = useMemo(() => {
    const descricaoFilter = normalizeTextFilter(filtroDescricao);
    const ticketFilter = normalizeTextFilter(filtroTicket);
    const clienteFilter = normalizeTextFilter(filtroCliente);

    return tarefas.filter((tarefa) => {
      if (descricaoFilter && !normalizeTextFilter(tarefa.descricao ?? "").includes(descricaoFilter)) return false;
      if (ticketFilter && !normalizeTextFilter(tarefa.numeroTicket ?? "").includes(ticketFilter)) return false;
      if (clienteFilter && !normalizeTextFilter(tarefa.cliente ?? "").includes(clienteFilter)) return false;
      if (filtroDataConclusao && toFilterDate(tarefa.dataConclusao) !== filtroDataConclusao) return false;
      return true;
    });
  }, [
    tarefas,
    filtroDescricao,
    filtroTicket,
    filtroCliente,
    filtroDataConclusao,
  ]);

  const loadTarefas = async () => {
    try {
      setLoading(true);
      const data = await fechamentoFechamentosService.listarTarefas(fechamentoId);
      const tarefasOrdenadas = [...data].sort((a, b) => {
        const timeA = a.dataConclusao ? new Date(a.dataConclusao).getTime() : Number.POSITIVE_INFINITY;
        const timeB = b.dataConclusao ? new Date(b.dataConclusao).getTime() : Number.POSITIVE_INFINITY;
        return timeA - timeB;
      });
      const estadoInicialBanco = Object.fromEntries(tarefasOrdenadas.map((tarefa) => [tarefa.id, Boolean(tarefa.estaRevisada)]));
      setTarefas(tarefasOrdenadas);
      setEstadoRevisaoInicial(estadoInicialBanco);
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao carregar detalhes do fechamento.";
      toast.error(message);
      setTarefas([]);
    } finally {
      setLoading(false);
    }
  };

  const loadFechamentoStatus = async (currentCompetenciaId: string) => {
    if (!currentCompetenciaId) return;
    try {
      const [rows, competencias] = await Promise.all([
        fechamentoCompetenciasService.listarFechamentosDaCompetencia(currentCompetenciaId),
        fechamentoCompetenciasService.listarCompetencias({}),
      ]);
      const current = rows.find((row) => row.id === fechamentoId);
      const competenciaAtual = competencias.find((item) => item.id === currentCompetenciaId);
      if (!current) return;
      setFechamentoStatus(current.status);
      setPontuacaoMeta(current.pontuacaoMeta);
      setCompetenciaStatus(competenciaAtual?.status ?? "em_aberto");
      setParceiroId(current.parceiroId);
      setParceiroNome(current.parceiroNome);
      const f = current.parceiroFator;
      setParceiroFator(
        f !== undefined && f !== null && Number.isFinite(Number(f)) && Number(f) > 0 ? Number(f) : null,
      );
      if (!competenciaId) {
        setCompetenciaId(current.competenciaId);
      }
    } catch {
      // mantém status atual em caso de erro para evitar bloquear navegação
    }
  };

  const loadSaldoBanco = async (id: string) => {
    setLoadingSaldoBanco(true);
    setErroSaldoBanco(false);
    try {
      const response = await fechamentoBancoPontosService.listarExtrato(id, { page: 1, perPage: 1 });
      setSaldoBancoAtual(response.parceiro?.saldo ?? 0);
    } catch {
      setErroSaldoBanco(true);
      setSaldoBancoAtual(null);
    } finally {
      setLoadingSaldoBanco(false);
    }
  };

  const toastBloqueioFechado = () => {
    toast.error("Fechamento está fechado. Reabra para editar.");
  };

  const toastBloqueioCompetenciaConcluida = () => {
    toast.error("Competência concluída. Reabra a competência para editar.");
  };

  useEffect(() => {
    if (fechamentoId) {
      void loadTarefas();
    }
  }, [fechamentoId]);

  useEffect(() => {
    if (competenciaId) {
      void loadFechamentoStatus(competenciaId);
    }
  }, [competenciaId, fechamentoId]);

  useEffect(() => {
    if (isFechado) {
      setIsConcluirOpen(false);
      setIsLancamentoOpen(false);
    }
  }, [isFechado]);

  useEffect(() => {
    if (!isLancamentoOpen || !lancamentoEmRealBloqueado) return;
    setLancamentoModo("pontos");
  }, [isLancamentoOpen, lancamentoEmRealBloqueado]);

  useEffect(() => {
    if (isConcluirOpen && parceiroId) {
      void loadSaldoBanco(parceiroId);
    }
    if (!isConcluirOpen) {
      setSaldoBancoAtual(null);
      setErroSaldoBanco(false);
    }
  }, [isConcluirOpen, parceiroId]);

  useEffect(() => {
    const main = tableScrollRef.current;
    const sticky = stickyScrollRef.current;
    if (!main || !sticky) return;

    let syncingFromMain = false;
    let syncingFromSticky = false;

    const syncMetricsAndVisibility = () => {
      const spacer = stickyScrollSpacerRef.current;
      const canScrollX = main.scrollWidth > main.clientWidth + 1;
      if (spacer) spacer.style.width = `${main.scrollWidth}px`;
      if (sticky.scrollLeft !== main.scrollLeft) sticky.scrollLeft = main.scrollLeft;
      setShowStickyScrollbar(canScrollX);
    };

    const onMainScroll = () => {
      if (syncingFromSticky) return;
      syncingFromMain = true;
      sticky.scrollLeft = main.scrollLeft;
      syncingFromMain = false;
    };

    const onStickyScroll = () => {
      if (syncingFromMain) return;
      syncingFromSticky = true;
      main.scrollLeft = sticky.scrollLeft;
      syncingFromSticky = false;
    };

    syncMetricsAndVisibility();
    main.addEventListener("scroll", onMainScroll, { passive: true });
    sticky.addEventListener("scroll", onStickyScroll, { passive: true });
    window.addEventListener("resize", syncMetricsAndVisibility);
    const resizeObserver = new ResizeObserver(() => syncMetricsAndVisibility());
    resizeObserver.observe(main);

    return () => {
      main.removeEventListener("scroll", onMainScroll);
      sticky.removeEventListener("scroll", onStickyScroll);
      window.removeEventListener("resize", syncMetricsAndVisibility);
      resizeObserver.disconnect();
    };
  }, [tarefas.length, loading]);

  const handleToggleAprovada = async (tarefa: FechamentoTarefaItem, approved: boolean) => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    setTarefas((prev) =>
      prev.map((item) =>
        item.id === tarefa.id
          ? {
              ...item,
              estaRevisada: approved,
            }
          : item,
      ),
    );
  };

  const handleLimparFiltros = () => {
    setFiltroDescricao("");
    setFiltroTicket("");
    setFiltroCliente("");
    setFiltroDataConclusao("");
  };

  const handleToggleTodasAprovadas = async () => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    const novoValor = !todasTarefasRevisadas;
    const tarefasParaAtualizar = tarefas.filter((tarefa) => tarefa.estaRevisada !== novoValor);
    if (tarefasParaAtualizar.length === 0) return;
    setBulkUpdatingRevisao(true);
    setTarefas((prev) => prev.map((tarefa) => ({ ...tarefa, estaRevisada: novoValor })));
    setBulkUpdatingRevisao(false);
  };

  const persistirRevisoesPendentes = async () => {
    if (!me?.id) {
      throw new Error("Não foi possível identificar o usuário para registrar a edição.");
    }
    const tarefasAlteradas = tarefas.filter(
      (tarefa) => estadoRevisaoInicial[tarefa.id] !== undefined && estadoRevisaoInicial[tarefa.id] !== tarefa.estaRevisada,
    );
    if (tarefasAlteradas.length === 0) return;
    await Promise.all(
      tarefasAlteradas.map((tarefa) =>
        fechamentoFechamentosService.patchTarefa(fechamentoId, tarefa.id, {
          estaRevisada: tarefa.estaRevisada,
          editadoPorId: me.id,
        }),
      ),
    );
    setEstadoRevisaoInicial((prev) => {
      const next = { ...prev };
      for (const tarefa of tarefasAlteradas) {
        next[tarefa.id] = tarefa.estaRevisada;
      }
      return next;
    });
  };

  const resetLancamentoForm = () => {
    setLancamentoTipo("bonus");
    setLancamentoDescricao("");
    setLancamentoModo("pontos");
    setLancamentoPontuacao("0");
    setLancamentoValorReal("");
  };

  const handleSalvarLancamento = async () => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    const descricao = lancamentoDescricao.trim();
    if (!descricao) {
      toast.error("Informe a descrição do lançamento.");
      return;
    }

    if (lancamentoModo === "real") {
      if (lancamentoEmRealBloqueado) {
        toast.error("Primeiro cadastre o fator do parceiro para poder lançar em Real.");
        return;
      }
      const valorNum = parseValorRealMonetarioInput(lancamentoValorReal.trim());
      if (!Number.isFinite(valorNum) || valorNum <= 0) {
        toast.error("Informe um valor em real válido maior que zero.");
        return;
      }
    } else {
      const pontuacao = (() => {
        const n = parsePontuacaoInput(lancamentoPontuacao);
        if (!Number.isFinite(n)) return Number.NaN;
        return pontuacaoParaCimaAte2Casas(n);
      })();
      if (!Number.isFinite(pontuacao) || pontuacao <= 0) {
        toast.error("Informe uma pontuação válida maior que zero.");
        return;
      }
    }

    try {
      setSavingLancamento(true);
      if (lancamentoModo === "real") {
        const valorNum = parseValorRealMonetarioInput(lancamentoValorReal.trim());
        await fechamentoFechamentosService.criarLancamento(fechamentoId, {
          tipo: lancamentoTipo,
          descricao,
          valorReal: valorNum,
        });
      } else {
        const pontuacao = (() => {
          const n = parsePontuacaoInput(lancamentoPontuacao);
          if (!Number.isFinite(n)) return Number.NaN;
          return pontuacaoParaCimaAte2Casas(n);
        })();
        await fechamentoFechamentosService.criarLancamento(fechamentoId, {
          tipo: lancamentoTipo,
          descricao,
          pontuacao,
        });
      }
      toast.success("Lançamento incluído com sucesso.");
      setIsLancamentoOpen(false);
      resetLancamentoForm();
      await loadTarefas();
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao incluir lançamento.";
      toast.error(message);
    } finally {
      setSavingLancamento(false);
    }
  };

  const handleAbrirConcluir = () => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    setPontuacaoPagaInput(pontuacaoTotalLabel);
    setMotivoAjuste("");
    setIsConcluirOpen(true);
  };

  const handleExportarPdf = async () => {
    if (!fechamentoId || !isFechado) return;
    try {
      setExportandoPdf(true);
      const { buffer, filename } = await fechamentoFechamentosService.exportarPdf(fechamentoId);
      const blob = new Blob([buffer], { type: "application/pdf" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = filename ?? `fechamento-${fechamentoId}.pdf`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      toast.success("PDF exportado com sucesso.");
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao exportar PDF.";
      toast.error(message);
    } finally {
      setExportandoPdf(false);
    }
  };

  const handleConcluirFechamento = async () => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    const pontuacaoPagaRaw = parsePontuacaoInput(pontuacaoPagaInput);
    if (!Number.isFinite(pontuacaoPagaRaw)) {
      toast.error("Informe uma pontuação paga válida.");
      return;
    }
    if (pontuacaoPagaRaw <= 0) {
      toast.error("A pontuação paga deve ser maior que zero.");
      return;
    }
    if (requerMotivoAjuste && !motivoAjuste.trim()) {
      toast.error("Informe o motivo do ajuste quando houver diferença de saldo.");
      return;
    }
    try {
      setConcluindo(true);
      await persistirRevisoesPendentes();
      const data = await fechamentoFechamentosService.concluirFechamento(fechamentoId, {
        pontuacaoPaga: pontuacaoPagaRaw,
        motivoAjuste: motivoAjuste.trim() || undefined,
      });
      toast.success(`Fechamento concluído. Banco de pontos: ${formatPontosAte2Casas(data.pontuacaoBanco)}.`);
      setFechamentoStatus("fechado");
      if (supervisorPodeExportarPdf) {
        try {
          const { buffer, filename } = await fechamentoFechamentosService.exportarPdf(fechamentoId);
          const blob = new Blob([buffer], { type: "application/pdf" });
          const url = URL.createObjectURL(blob);
          const a = document.createElement("a");
          a.href = url;
          a.download = filename ?? `fechamento-${fechamentoId}.pdf`;
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
          URL.revokeObjectURL(url);
          toast.success("PDF do fechamento baixado.");
        } catch {
          toast.warning(
            "Fechamento concluído, mas o PDF não pôde ser gerado automaticamente. Use Exportar PDF na tela.",
          );
        }
      }
      navigate(`/intelligence-score/competencias/${data.competenciaId}`);
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao concluir fechamento.";
      toast.error(message);
      if (competenciaId) {
        await loadFechamentoStatus(competenciaId);
      }
      await loadTarefas();
    } finally {
      setConcluindo(false);
    }
  };

  const handleReabrirFechamento = async () => {
    if (!me?.id) {
      toast.error("Não foi possível identificar o usuário para reabertura.");
      return;
    }
    if (!motivoReabertura.trim()) {
      toast.error("Informe o motivo da reabertura do fechamento.");
      return;
    }
    try {
      setReabrindo(true);
      const data = await fechamentoFechamentosService.reabrirFechamento(fechamentoId, {
        reabertoPorId: me.id,
        motivo: motivoReabertura.trim(),
      });
      toast.success("Fechamento reaberto com sucesso.");
      setFechamentoStatus(data.status);
      setIsReabrirOpen(false);
      setMotivoReabertura("");
      await loadTarefas();
      if (data.competenciaId) {
        setCompetenciaId(data.competenciaId);
      } else if (competenciaId) {
        await loadFechamentoStatus(competenciaId);
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao reabrir fechamento.";
      toast.error(message);
      if (competenciaId) {
        await loadFechamentoStatus(competenciaId);
      }
    } finally {
      setReabrindo(false);
    }
  };

  const handleExcluirLancamento = (tarefa: FechamentoTarefaItem) => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    const isManual = tarefa.tipo === "bonus" || tarefa.tipo === "desconto";
    if (!isManual) return;
    setDeletingTarefa(tarefa);
    setIsDeleteDialogOpen(true);
  };

  const confirmDeleteLancamento = async () => {
    if (!deletingTarefa) return;
    try {
      setDeletingTaskId(deletingTarefa.id);
      await fechamentoFechamentosService.excluirLancamento(fechamentoId, deletingTarefa.id);
      toast.success("Lançamento excluído com sucesso.");
      setIsDeleteDialogOpen(false);
      setDeletingTarefa(null);
      await loadTarefas();
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao excluir lançamento.";
      toast.error(message);
    } finally {
      setDeletingTaskId(null);
    }
  };

  const openEditarTarefa = (tarefa: FechamentoTarefaItem) => {
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    setEditingTarefa(tarefa);
    setEdicaoNumeroTicket(tarefa.numeroTicket ?? "");
    setEdicaoDescricao(tarefa.descricao ?? "");
    setEdicaoCliente(tarefa.cliente ?? "");
    setEdicaoTempoMinutos(tarefa.tempoMinutos != null ? String(tarefa.tempoMinutos) : "");
    setEdicaoPontuacao(String(Number(tarefa.pontuacao ?? 0)));
    setIsEditarOpen(true);
  };

  const carregarCompetenciasAbertas = async () => {
    try {
      setLoadingCompetenciasAbertas(true);
      const competencias = await fechamentoCompetenciasService.listarCompetencias({ status: "em_aberto" });
      setCompetenciasAbertas(competencias);
      return competencias;
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao carregar competências em aberto.";
      toast.error(message);
      return [] as CompetenciaItem[];
    } finally {
      setLoadingCompetenciasAbertas(false);
    }
  };

  const openAlterarCompetencia = async (tarefa: FechamentoTarefaItem) => {
    if (!podeAlterarCompetenciaTarefa) {
      toast.error("Sem permissão para alterar competência da tarefa.");
      return;
    }
    if (isCompetenciaConcluida) {
      toastBloqueioCompetenciaConcluida();
      return;
    }
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    const competencias = await carregarCompetenciasAbertas();
    const opcoes = competencias.filter((item) => item.id !== competenciaId);
    if (opcoes.length === 0) {
      toast.error("Não há outra competência em aberto para mover a tarefa.");
      return;
    }
    setTarefaAlteracaoCompetencia(tarefa);
    setCompetenciaDestinoId(opcoes[0]?.id ?? "");
    setMotivoAlteracaoCompetencia("");
    setIsAlterarCompetenciaOpen(true);
  };

  const handleConfirmarAlteracaoCompetencia = async () => {
    if (!tarefaAlteracaoCompetencia) return;
    if (!me?.id) {
      toast.error("Não foi possível identificar o usuário para registrar a alteração.");
      return;
    }
    if (!competenciaDestinoId) {
      toast.error("Selecione a competência de destino.");
      return;
    }
    try {
      setSavingAlteracaoCompetencia(true);
      await fechamentoFechamentosService.alterarCompetenciaTarefa(fechamentoId, tarefaAlteracaoCompetencia.id, {
        competenciaDestinoId,
        alteradoPorId: me.id,
        motivo: motivoAlteracaoCompetencia,
      });
      toast.success("Competência da tarefa alterada com sucesso.");
      setIsAlterarCompetenciaOpen(false);
      setTarefaAlteracaoCompetencia(null);
      setCompetenciaDestinoId("");
      setMotivoAlteracaoCompetencia("");
      await loadTarefas();
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao alterar competência da tarefa.";
      toast.error(message);
    } finally {
      setSavingAlteracaoCompetencia(false);
    }
  };

  const handleSalvarEdicao = async () => {
    if (!editingTarefa) return;
    if (!me?.id) {
      toast.error("Não foi possível identificar o usuário para registrar a edição.");
      return;
    }
    const isManual = editingTarefa.tipo === "bonus" || editingTarefa.tipo === "desconto";
    const descricao = edicaoDescricao.trim();
    const pontuacao = pontuacaoParaCimaAte2Casas(parsePontuacaoInput(edicaoPontuacao));
    if (!descricao) {
      toast.error("Descrição é obrigatória.");
      return;
    }
    if (!Number.isFinite(pontuacao) || pontuacao <= 0) {
      toast.error("Pontuação deve ser maior que zero.");
      return;
    }

    let tempoMinutos: number | null | undefined = undefined;
    if (!isManual) {
      const tempoRaw = edicaoTempoMinutos.trim();
      if (tempoRaw.length > 0) {
        const tempoParsed = Number(tempoRaw);
        if (!Number.isFinite(tempoParsed) || tempoParsed < 0 || !Number.isInteger(tempoParsed)) {
          toast.error("Horas/minutos deve ser um número inteiro maior ou igual a zero.");
          return;
        }
        tempoMinutos = tempoParsed;
      } else {
        tempoMinutos = null;
      }
    }

    try {
      setSavingEdicao(true);
      await fechamentoFechamentosService.patchTarefa(fechamentoId, editingTarefa.id, {
        descricao,
        pontuacao,
        ...(isManual
          ? {}
          : {
              numeroTicket: edicaoNumeroTicket.trim() ? edicaoNumeroTicket.trim() : null,
              cliente: edicaoCliente.trim() ? edicaoCliente.trim() : null,
              tempoMinutos,
            }),
        editadoPorId: me.id,
      });
      toast.success("Tarefa atualizada com sucesso.");
      setIsEditarOpen(false);
      setEditingTarefa(null);
      await loadTarefas();
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao editar tarefa.";
      toast.error(message);
    } finally {
      setSavingEdicao(false);
    }
  };

  const handleReprocessarAsana = async () => {
    if (isFechado) {
      toastBloqueioFechado();
      return;
    }
    try {
      setReprocessandoAsana(true);
      const data = await fechamentoFechamentosService.reprocessarAsana(fechamentoId);
      toast.success(
        `Reprocessamento concluído: ${data.tarefasImportadas} tarefa(s) atualizada(s) para este parceiro.`,
      );
      setIsReprocessAsanaOpen(false);
      await loadTarefas();
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao reprocessar Asana.";
      toast.error(message);
    } finally {
      setReprocessandoAsana(false);
    }
  };

  return (
    <div className="flex h-full flex-col bg-background pb-16 md:pb-0">
      <div className="border-b border-border bg-muted/20 p-3 md:p-6">
        <div className="mb-2">
          <Button variant="ghost" size="sm" className="hover:bg-muted/60 hover:text-foreground" onClick={() => navigate(-1)}>
            <ArrowLeft className="mr-1 h-4 w-4" />
            Voltar
          </Button>
        </div>

        <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
          <div className="min-w-0">
            <h1 className="flex items-center gap-2 text-xl font-bold text-foreground md:text-3xl">
              <ListChecks className="h-5 w-5 md:h-6 md:w-6" />
              Detalhes do Fechamento
            </h1>
            <p className="mt-1 text-sm text-muted-foreground">Revisão operacional de tarefas, pontos e horas.</p>
          </div>

          {!loading ? (
            <div className="flex flex-wrap items-center gap-2 xl:justify-end">
              <Badge variant={isReadonly ? "secondary" : "outline"}>{isFechado ? "Fechado" : "Em aberto"}</Badge>
              {isCompetenciaConcluida ? <Badge variant="secondary">Competência concluída</Badge> : null}
              <Button
                size="sm"
                variant="outline"
                onClick={() => {
                  resetLancamentoForm();
                  setIsLancamentoOpen(true);
                }}
                disabled={isReadonly || !podeTarefaLancarAjuste}
                className="min-w-[152px] hover:bg-muted/60 hover:text-foreground"
              >
                <Plus className="mr-2 h-4 w-4" />
                Fazer lançamento
              </Button>
              {!isReadonly && podeReprocessarAsana ? (
                <Button
                  size="sm"
                  variant="outline"
                  onClick={() => setIsReprocessAsanaOpen(true)}
                  disabled={reprocessandoAsana}
                  className="min-w-[152px] hover:bg-muted/60 hover:text-foreground"
                >
                  <RotateCcw className="mr-2 h-4 w-4" />
                  Reprocessar Asana
                </Button>
              ) : null}
              {isFechado ? (
                <>
                  {supervisorPodeExportarPdf ? (
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() => void handleExportarPdf()}
                      disabled={exportandoPdf || isCompetenciaConcluida}
                      className="min-w-[152px] hover:bg-muted/60 hover:text-foreground"
                    >
                      <FileText className="mr-2 h-4 w-4" />
                      {exportandoPdf ? "Gerando PDF..." : "Exportar PDF"}
                    </Button>
                  ) : null}
                  {podeReabrirFechamento ? (
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() => setIsReabrirOpen(true)}
                      disabled={reabrindo || isCompetenciaConcluida}
                      className="min-w-[152px]"
                    >
                      <RotateCcw className="mr-2 h-4 w-4" />
                      Reabrir fechamento
                    </Button>
                  ) : null}
                </>
              ) : podeConcluirFechamento ? (
                <Button
                  size="sm"
                  variant="secondary"
                  onClick={handleAbrirConcluir}
                  disabled={tarefas.length === 0 || concluindo || isCompetenciaConcluida}
                  className="min-w-[152px]"
                >
                  <CheckCircle2 className="mr-2 h-4 w-4" />
                  Concluir fechamento
                </Button>
              ) : null}
            </div>
          ) : null}
        </div>

        {!loading ? (
          <div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3">
            {isCompetenciaConcluida ? (
              <div className="sm:col-span-2 xl:col-span-4 rounded-lg border border-amber-300 bg-amber-50 p-3 text-sm text-amber-900">
                Competência concluída. Reabra a competência para editar este fechamento.
              </div>
            ) : null}
            <Card className="border-border/70 bg-card shadow-sm transition hover:shadow-md">
              <CardHeader className="space-y-2 p-4">
                <div className="flex items-start justify-between">
                  <CardDescription className="text-[11px] uppercase tracking-wide">Total de tarefas</CardDescription>
                  <ListChecks className="h-4 w-4 text-muted-foreground" />
                </div>
                <CardTitle className="text-3xl">{tarefas.length}</CardTitle>
              </CardHeader>
            </Card>
            <Card className="border-border/70 bg-card shadow-sm transition hover:shadow-md">
              <CardHeader className="space-y-2 p-4">
                <div className="flex items-start justify-between">
                  <CardDescription className="text-[11px] uppercase tracking-wide">
                    Pontuação total do mês
                  </CardDescription>
                  <Sigma className="h-4 w-4 text-muted-foreground" />
                </div>
                <CardTitle className="text-3xl">{formatPontos(totais.pontosTotalMes)}</CardTitle>
              </CardHeader>
            </Card>
            <Card className="border-border/70 bg-card shadow-sm transition hover:shadow-md">
              <CardHeader className="space-y-2 p-4">
                <div className="flex items-start justify-between">
                  <CardDescription className="text-[11px] uppercase tracking-wide">
                    Pontuação aprovada
                  </CardDescription>
                  <Target className="h-4 w-4 text-muted-foreground" />
                </div>
                <CardTitle className="text-3xl">{formatPontos(totais.pontos)}</CardTitle>
              </CardHeader>
            </Card>
          </div>
        ) : null}
      </div>

      <div className="flex-1 overflow-auto p-3 md:p-6">
        {!loading && tarefas.length === 0 ? (
          <Card className="mx-auto mt-12 max-w-2xl">
            <CardHeader>
              <CardTitle>Nenhuma tarefa encontrada</CardTitle>
              <CardDescription>Este fechamento não possui tarefas cadastradas.</CardDescription>
            </CardHeader>
          </Card>
        ) : (
          <div className="space-y-3">
            {!loading ? (
              <div className="space-y-3">
                <div className="flex flex-wrap items-center justify-end gap-2">
                  <Button type="button" size="sm" variant="outline" onClick={() => setShowFilters((prev) => !prev)}>
                    {showFilters ? "Ocultar filtros" : "Exibir filtros"}
                  </Button>
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    onClick={handleLimparFiltros}
                    disabled={!hasActiveFilters}
                  >
                    Limpar filtros
                  </Button>
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    onClick={() => void handleToggleTodasAprovadas()}
                    disabled={bloqueioEdicaoTarefa || bulkUpdatingRevisao}
                  >
                    {bulkUpdatingRevisao ? (
                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    ) : (
                      <CheckCircle2 className="mr-2 h-4 w-4" />
                    )}
                    {todasTarefasRevisadas ? "Desmarcar todas" : "Marcar todas"}
                  </Button>
                </div>
                {showFilters ? (
                  <div className="grid grid-cols-1 gap-3 rounded-lg border bg-muted/20 p-3 md:grid-cols-2 xl:grid-cols-4">
                    <div className="space-y-1">
                      <Label htmlFor="filtro-descricao">Descrição</Label>
                      <Input
                        id="filtro-descricao"
                        value={filtroDescricao}
                        onChange={(e) => setFiltroDescricao(e.target.value)}
                        placeholder="Digite parte da descrição"
                      />
                    </div>
                    <div className="space-y-1">
                      <Label htmlFor="filtro-ticket">Ticket</Label>
                      <Input
                        id="filtro-ticket"
                        value={filtroTicket}
                        onChange={(e) => setFiltroTicket(e.target.value)}
                        placeholder="Ex.: TKT-1234"
                      />
                    </div>
                    <div className="space-y-1">
                      <Label htmlFor="filtro-cliente">Cliente</Label>
                      <Input
                        id="filtro-cliente"
                        value={filtroCliente}
                        onChange={(e) => setFiltroCliente(e.target.value)}
                        placeholder="Nome do cliente"
                      />
                    </div>
                    <div className="space-y-1">
                      <Label htmlFor="filtro-data-conclusao">Data de conclusão</Label>
                      <Input
                        id="filtro-data-conclusao"
                        type="date"
                        value={filtroDataConclusao}
                        onChange={(e) => setFiltroDataConclusao(e.target.value)}
                      />
                    </div>
                  </div>
                ) : null}
              </div>
            ) : null}
            <div ref={tableScrollRef} className="overflow-x-auto rounded-lg border">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="min-w-[120px]">Aprovada</TableHead>
                  <TableHead className="min-w-[120px]">Ticket</TableHead>
                  <TableHead className="min-w-[320px]">Descrição</TableHead>
                  <TableHead className="min-w-[180px]">Cliente</TableHead>
                  <TableHead className="min-w-[110px]">Tipo</TableHead>
                  <TableHead className="min-w-[130px]">Data início</TableHead>
                  <TableHead className="min-w-[140px]">Data vencimento</TableHead>
                  <TableHead className="min-w-[170px]">Data conclusão</TableHead>
                  <TableHead className="min-w-[240px]">Etiquetas</TableHead>
                  <TableHead className="min-w-[120px]">Pontuação</TableHead>
                  <TableHead className="min-w-[140px] text-right">Ações</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {loading ? (
                  <TableRow>
                    <TableCell colSpan={11} className="py-8 text-center text-muted-foreground">
                      Carregando tarefas...
                    </TableCell>
                  </TableRow>
                ) : tarefasFiltradas.length === 0 ? (
                  <TableRow>
                    <TableCell colSpan={11} className="py-8 text-center text-muted-foreground">
                      Nenhuma tarefa encontrada com os filtros aplicados.
                    </TableCell>
                  </TableRow>
                ) : (
                  tarefasFiltradas.map((tarefa) => (
                    <TableRow key={tarefa.id}>
                      <TableCell>
                        <div className="flex items-center gap-2">
                          <Checkbox
                            checked={tarefa.estaRevisada}
                            onCheckedChange={(checked) => void handleToggleAprovada(tarefa, Boolean(checked))}
                            disabled={bloqueioEdicaoTarefa || bulkUpdatingRevisao}
                          />
                        </div>
                      </TableCell>
                      <TableCell>{tarefa.numeroTicket || "—"}</TableCell>
                      <TableCell className="font-medium">{tarefa.descricao}</TableCell>
                      <TableCell>{tarefa.cliente || "—"}</TableCell>
                      <TableCell>{getTipoLancamentoLabel(tarefa.tipo)}</TableCell>
                      <TableCell>{formatDateOnly(tarefa.dataInicio)}</TableCell>
                      <TableCell>{formatDateOnly(tarefa.dataVencimento)}</TableCell>
                      <TableCell>{formatDateTime(tarefa.dataConclusao)}</TableCell>
                      <TableCell>
                        {tarefa.etiquetas && tarefa.etiquetas.length > 0 ? (
                          <div className="flex flex-wrap gap-1">
                            {tarefa.etiquetas.map((etiqueta) => (
                              <Badge key={`${tarefa.id}-${etiqueta.gid}`} variant="outline" className="font-normal">
                                {etiqueta.name}
                              </Badge>
                            ))}
                          </div>
                        ) : (
                          "—"
                        )}
                      </TableCell>
                      <TableCell>{Number(tarefa.pontuacao || 0)}</TableCell>
                      <TableCell className="text-right">
                        <div className="flex items-center justify-end gap-1">
                          {tarefa.linkAsana ? (
                            <Button type="button" size="sm" variant="ghost" asChild>
                              <a href={tarefa.linkAsana} target="_blank" rel="noopener noreferrer" title="Abrir tarefa no Asana">
                                <ExternalLink className="h-4 w-4" />
                                <span className="ml-1">Abrir</span>
                              </a>
                            </Button>
                          ) : null}
                          <Button
                            type="button"
                            size="sm"
                            variant="ghost"
                            onClick={() => openEditarTarefa(tarefa)}
                            disabled={bloqueioEdicaoTarefa}
                          >
                            <Pencil className="h-4 w-4" />
                            <span className="ml-1">Editar</span>
                          </Button>
                          {podeAlterarCompetenciaTarefa && tarefa.tipo === "tarefa" ? (
                            <Button
                              type="button"
                              size="sm"
                              variant="ghost"
                              onClick={() => void openAlterarCompetencia(tarefa)}
                              disabled={bloqueioEdicaoTarefa || savingAlteracaoCompetencia}
                            >
                              <Repeat className="h-4 w-4" />
                              <span className="ml-1">Alterar competência</span>
                            </Button>
                          ) : null}
                          {tarefa.tipo === "bonus" || tarefa.tipo === "desconto" ? (
                            <Button
                              type="button"
                              size="sm"
                              variant="ghost"
                              className="text-red-600 hover:text-red-700 hover:bg-red-50"
                              onClick={() => void handleExcluirLancamento(tarefa)}
                              disabled={bloqueioEdicaoTarefa || !podeExcluirLancamentoManual || deletingTaskId === tarefa.id}
                            >
                              {deletingTaskId === tarefa.id ? (
                                <Loader2 className="h-4 w-4 animate-spin" />
                              ) : (
                                <Trash2 className="h-4 w-4" />
                              )}
                              <span className="ml-1">Excluir</span>
                            </Button>
                          ) : null}
                        </div>
                      </TableCell>
                    </TableRow>
                  ))
                )}
              </TableBody>
            </Table>
          </div>
            {showStickyScrollbar ? (
              <div className="fixed bottom-2 left-2 right-2 z-50 rounded-md border bg-background/95 shadow-md backdrop-blur supports-[backdrop-filter]:bg-background/80">
                <div ref={stickyScrollRef} className="overflow-x-auto">
                  <div ref={stickyScrollSpacerRef} className="h-4 min-w-full" />
                </div>
              </div>
            ) : null}
          </div>
        )}
      </div>

      <Dialog
        open={isLancamentoOpen}
        onOpenChange={(open) => {
          setIsLancamentoOpen(open);
          if (!open) {
            resetLancamentoForm();
          }
        }}
      >
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Fazer lançamento</DialogTitle>
          </DialogHeader>

          <div className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="lancamento-tipo">Tipo de lançamento</Label>
              <Select
                value={lancamentoTipo}
                onValueChange={(value) => setLancamentoTipo(value as "bonus" | "desconto")}
              >
                <SelectTrigger id="lancamento-tipo">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="bonus">{getTipoLancamentoLabel("bonus")}</SelectItem>
                  <SelectItem value="desconto">{getTipoLancamentoLabel("desconto")}</SelectItem>
                </SelectContent>
              </Select>
            </div>

            <div className="space-y-2">
              <Label>Forma do lançamento</Label>
              {lancamentoEmRealBloqueado ? (
                <Alert variant="destructive" className="py-2">
                  <AlertCircle className="h-4 w-4" />
                  <AlertDescription>
                    Primeiro cadastre o fator do parceiro para poder lançar em Real.
                  </AlertDescription>
                </Alert>
              ) : null}
              <RadioGroup
                value={lancamentoModo}
                onValueChange={(v) => setLancamentoModo(v as "pontos" | "real")}
                className="flex flex-wrap gap-4"
              >
                <div className="flex items-center space-x-2">
                  <RadioGroupItem value="pontos" id="lancamento-modo-pontos" />
                  <Label htmlFor="lancamento-modo-pontos" className="cursor-pointer font-normal">
                    Pontuação
                  </Label>
                </div>
                <div className="flex items-center space-x-2">
                  <RadioGroupItem value="real" id="lancamento-modo-real" disabled={lancamentoEmRealBloqueado} />
                  <Label
                    htmlFor="lancamento-modo-real"
                    className={
                      lancamentoEmRealBloqueado ? "cursor-not-allowed font-normal text-muted-foreground" : "cursor-pointer font-normal"
                    }
                  >
                    Valor em real (R$)
                  </Label>
                </div>
              </RadioGroup>
            </div>

            {lancamentoModo === "pontos" ? (
              <div className="space-y-2">
                <Label htmlFor="lancamento-pontuacao">Pontuação</Label>
                <Input
                  id="lancamento-pontuacao"
                  type="text"
                  inputMode="decimal"
                  value={lancamentoPontuacao}
                  onChange={(e) => setLancamentoPontuacao(sanitizePontuacaoLancamentoDigitando(e.target.value))}
                  placeholder="Ex.: 1,5"
                />
              </div>
            ) : (
              <div className="space-y-2">
                <Label htmlFor="lancamento-valor-real">Valor (R$)</Label>
                <Input
                  id="lancamento-valor-real"
                  type="text"
                  inputMode="decimal"
                  autoComplete="off"
                  value={lancamentoValorReal}
                  onChange={(e) => setLancamentoValorReal(sanitizeValorRealLancamentoDigitando(e.target.value))}
                  placeholder="Ex.: 90,00"
                />
                {lancamentoPreviewPontos != null ? (
                  <p className="text-xs font-medium text-foreground">
                    Pontuação estimada: {formatPontos(lancamentoPreviewPontos)}
                  </p>
                ) : (
                  <p className="text-xs text-muted-foreground">
                    A conversão é feita ao salvar com o fator cadastrado do parceiro (valor ÷ (fator × 3)).
                  </p>
                )}
              </div>
            )}

            <div className="space-y-2">
              <Label htmlFor="lancamento-descricao">Descrição</Label>
              <Input
                id="lancamento-descricao"
                value={lancamentoDescricao}
                onChange={(e) => setLancamentoDescricao(e.target.value)}
                placeholder="Ex.: ajuste de meta / retrabalho / bônus de sprint"
              />
            </div>
          </div>

          <DialogFooter>
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => {
                setIsLancamentoOpen(false);
                resetLancamentoForm();
              }}
              disabled={savingLancamento}
            >
              Cancelar
            </Button>
            <Button
              onClick={() => void handleSalvarLancamento()}
              disabled={
                savingLancamento ||
                isReadonly ||
                !podeTarefaLancarAjuste ||
                (lancamentoModo === "real" && lancamentoEmRealBloqueado)
              }
            >
              {savingLancamento ? "Salvando..." : "Salvar lançamento"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={isAlterarCompetenciaOpen}
        onOpenChange={(open) => {
          setIsAlterarCompetenciaOpen(open);
          if (!open) {
            setTarefaAlteracaoCompetencia(null);
            setMotivoAlteracaoCompetencia("");
            setCompetenciaDestinoId("");
          }
        }}
      >
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Alterar competência da tarefa</DialogTitle>
            <DialogDescription>
              Mova a tarefa para outra competência em aberto. O histórico da alteração ficará registrado.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-2">
              <Label>Competência atual</Label>
              <p className="rounded-md border bg-muted/30 px-3 py-2 text-sm text-muted-foreground">
                {competenciaId
                  ? (() => {
                      const atual = competenciasAbertas.find((item) => item.id === competenciaId);
                      if (atual) return formatCompetenciaMesAno(atual);
                      return "Competência atual do fechamento";
                    })()
                  : "Competência atual do fechamento"}
              </p>
            </div>
            <div className="space-y-2">
              <Label htmlFor="competencia-destino">Competência destino</Label>
              <Select
                value={competenciaDestinoId}
                onValueChange={setCompetenciaDestinoId}
                disabled={loadingCompetenciasAbertas || savingAlteracaoCompetencia}
              >
                <SelectTrigger id="competencia-destino">
                  <SelectValue placeholder="Selecione a competência de destino" />
                </SelectTrigger>
                <SelectContent>
                  {competenciasDestino.map((item) => (
                    <SelectItem key={item.id} value={item.id}>
                      {formatCompetenciaMesAno(item)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label htmlFor="motivo-alteracao-competencia">Motivo (opcional)</Label>
              <Input
                id="motivo-alteracao-competencia"
                value={motivoAlteracaoCompetencia}
                onChange={(e) => setMotivoAlteracaoCompetencia(e.target.value)}
                placeholder="Ex.: tarefa entregue no mês seguinte por atraso de baixa"
                maxLength={500}
                disabled={savingAlteracaoCompetencia}
              />
            </div>
          </div>
          <DialogFooter>
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => setIsAlterarCompetenciaOpen(false)}
              disabled={savingAlteracaoCompetencia}
            >
              Cancelar
            </Button>
            <Button
              onClick={() => void handleConfirmarAlteracaoCompetencia()}
              disabled={savingAlteracaoCompetencia || !competenciaDestinoId}
            >
              {savingAlteracaoCompetencia ? "Alterando..." : "Confirmar alteração"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={isConcluirOpen} onOpenChange={setIsConcluirOpen}>
        <DialogContent className="gap-0 overflow-hidden p-0 sm:max-w-2xl">
          <div className="border-b border-border bg-muted/40 px-6 pb-4 pt-6 sm:px-8">
            <DialogHeader className="space-y-1 text-left">
              <DialogTitle className="text-xl font-semibold tracking-tight">Concluir fechamento</DialogTitle>
              <DialogDescription className="text-sm text-muted-foreground">
                Informe a pontuação paga e confirme.
              </DialogDescription>
            </DialogHeader>
            {parceiroNome ? (
              <div className="mt-4 flex items-center gap-2 rounded-lg border border-border/80 bg-background/80 px-3 py-2.5">
                <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted">
                  <User className="h-4 w-4 text-muted-foreground" aria-hidden />
                </div>
                <div className="min-w-0">
                  <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Parceiro</p>
                  <p className="truncate text-sm font-semibold text-foreground">{parceiroNome}</p>
                </div>
              </div>
            ) : null}
          </div>

          <div className="max-h-[min(75vh,36rem)] space-y-0 overflow-y-auto px-6 py-5 sm:px-8">
            <div className="grid gap-4 md:grid-cols-2 md:gap-5">
              <section className="rounded-xl border border-border bg-card p-4 shadow-sm">
                <div className="mb-3 flex items-center gap-2">
                  <div className="flex h-8 w-8 items-center justify-center rounded-md bg-muted">
                    <ListChecks className="h-4 w-4 text-muted-foreground" aria-hidden />
                  </div>
                  <h3 className="text-sm font-semibold text-foreground">Este mês</h3>
                </div>
                <dl className="space-y-0">
                  <div className="flex items-baseline justify-between gap-4 border-b border-border/60 py-2.5 first:pt-0">
                    <dt className="text-sm text-muted-foreground">Aprovados</dt>
                    <dd className="text-right text-lg font-semibold tabular-nums tracking-tight text-foreground">
                      {formatPontos(totais.pontos)}
                    </dd>
                  </div>
                  <div className="flex items-baseline justify-between gap-4 border-b border-border/60 py-2.5">
                    <dt className="text-sm text-muted-foreground">Meta</dt>
                    <dd className="text-right text-lg font-semibold tabular-nums tracking-tight text-foreground">
                      {formatPontos(Number(pontuacaoMeta ?? 0))}
                    </dd>
                  </div>
                  <div className="flex items-baseline justify-between gap-4 py-2.5 last:pb-0">
                    <dt className="text-sm text-muted-foreground">Diferença</dt>
                    <dd
                      className={`text-right text-lg font-semibold tabular-nums tracking-tight ${
                        diferencaParaMeta >= 0 ? "text-emerald-600" : "text-red-600"
                      }`}
                    >
                      {diferencaParaMeta >= 0 ? "+" : ""}
                      {formatPontos(diferencaParaMeta)}
                    </dd>
                  </div>
                </dl>
              </section>

              <section className="rounded-xl border border-primary/20 bg-primary/[0.06] p-4">
                <div className="mb-3 flex items-center gap-2">
                  <div className="flex h-8 w-8 items-center justify-center rounded-md bg-background shadow-sm">
                    <Wallet className="h-4 w-4 text-primary" aria-hidden />
                  </div>
                  <h3 className="text-sm font-semibold text-foreground">Banco de pontos</h3>
                </div>
              <dl className="space-y-0">
                <div className="flex items-baseline justify-between gap-4 border-b border-primary/10 py-2.5 first:pt-0">
                  <dt className="text-sm text-muted-foreground">Saldo hoje</dt>
                  <dd className="text-right">
                    {loadingSaldoBanco ? (
                      <Skeleton className="ml-auto h-7 w-24 rounded-md" />
                    ) : erroSaldoBanco ? (
                      <div className="flex flex-col items-end gap-1">
                        <span className="text-sm font-medium text-destructive">Não foi possível carregar</span>
                        {parceiroId ? (
                          <button
                            type="button"
                            className="text-xs font-medium text-primary underline-offset-2 hover:underline"
                            onClick={() => void loadSaldoBanco(parceiroId)}
                          >
                            Tentar de novo
                          </button>
                        ) : null}
                      </div>
                    ) : (
                      <span
                        className={`text-lg font-semibold tabular-nums tracking-tight ${corSaldoPontos(saldoBancoAtual ?? 0)}`}
                      >
                        {formatPontosSaldoModal(saldoBancoAtual ?? 0)}
                      </span>
                    )}
                  </dd>
                </div>
                <div className="flex items-baseline justify-between gap-4 border-b border-primary/10 py-2.5">
                  <dt className="text-sm text-muted-foreground">Movimento</dt>
                  <dd
                    className={`text-right text-lg font-semibold tabular-nums tracking-tight ${corSaldoPontos(bancoCalculado)}`}
                  >
                    {bancoCalculado > SALDO_PONTOS_EPS ? "+" : ""}
                    {formatPontosSaldoModal(bancoCalculado)}
                  </dd>
                </div>
                <div className="flex items-baseline justify-between gap-4 py-2.5 last:pb-0">
                  <dt className="text-sm font-medium text-foreground">Depois</dt>
                  <dd className="text-right">
                    {saldoBancoPosFechamento == null ? (
                      <span className="text-lg font-semibold tabular-nums text-muted-foreground">—</span>
                    ) : (
                      <span
                        className={`text-lg font-semibold tabular-nums tracking-tight ${corSaldoPontos(saldoBancoPosFechamento)}`}
                      >
                        {formatPontosSaldoModal(saldoBancoPosFechamento)}
                      </span>
                    )}
                  </dd>
                </div>
              </dl>
              </section>
            </div>

            <Separator className="my-5" />

            <div className="space-y-3">
              <Label htmlFor="pontuacao-paga" className="text-sm font-semibold">
                Pontuação paga
              </Label>
              <Input
                id="pontuacao-paga"
                type="text"
                inputMode="decimal"
                className="h-11 text-base font-medium tabular-nums"
                value={pontuacaoPagaInput}
                onChange={(e) => setPontuacaoPagaInput(e.target.value)}
                placeholder="Ex.: 10,5"
              />
              {isValorEditado ? (
                <button
                  type="button"
                  className="text-xs font-medium text-primary underline-offset-2 hover:underline"
                  onClick={() => setPontuacaoPagaInput(pontuacaoTotalLabel)}
                >
                  Voltar para o total aprovado ({formatPontos(totais.pontos)})
                </button>
              ) : null}
              <div className="rounded-lg border border-dashed border-border bg-muted/30 p-3">
                <div className="flex flex-col gap-2 sm:flex-row sm:flex-wrap">
                  <Button
                    type="button"
                    variant="secondary"
                    size="sm"
                    className="h-9 justify-center font-normal"
                    onClick={() => setPontuacaoPagaInput(pontuacaoTotalLabel)}
                  >
                    Igual aos aprovados
                  </Button>
                  <Button
                    type="button"
                    variant="secondary"
                    size="sm"
                    className="h-9 justify-center font-normal"
                    onClick={() => setPontuacaoPagaInput(String(pontuacaoMeta ?? 0))}
                  >
                    Igual à meta
                  </Button>
                  {dividaParaQuitar > 0 && sugestaoQuitarDivida > SALDO_PONTOS_EPS ? (
                    <Button
                      type="button"
                      variant="secondary"
                      size="sm"
                      className="h-9 justify-center border border-red-200 bg-red-50 font-normal text-red-800 hover:bg-red-100 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-200 dark:hover:bg-red-950/60"
                      title={`${formatPontos(sugestaoQuitarDivida)} pontos — aprovados menos a dívida; zera o banco`}
                      onClick={() => setPontuacaoPagaInput(toPontuacaoInput(sugestaoQuitarDivida))}
                    >
                      Quitar dívida ({formatPontos(dividaParaQuitar)})
                    </Button>
                  ) : null}
                  {saldoPositivoDisponivel > 0 ? (
                    <Button
                      type="button"
                      variant="secondary"
                      size="sm"
                      className="h-9 justify-center border border-emerald-200 bg-emerald-50 font-normal text-emerald-900 hover:bg-emerald-100 dark:border-emerald-900/50 dark:bg-emerald-950/40 dark:text-emerald-100 dark:hover:bg-emerald-950/60"
                      title={`${formatPontos(sugestaoUsarSaldoPositivo)} pontos — aprovados + saldo; zera o banco`}
                      onClick={() => setPontuacaoPagaInput(toPontuacaoInput(sugestaoUsarSaldoPositivo))}
                    >
                      Usar saldo positivo ({formatPontos(saldoPositivoDisponivel)})
                    </Button>
                  ) : null}
                </div>
              </div>
            </div>

            {requerMotivoAjuste ? (
              <div className="mt-5 space-y-2 rounded-lg border border-amber-200/80 bg-amber-50/80 p-3 dark:border-amber-900/40 dark:bg-amber-950/25">
                <Label htmlFor="motivo-ajuste" className="text-sm font-semibold text-amber-950 dark:text-amber-100">
                  Motivo do ajuste *
                </Label>
                <Input
                  id="motivo-ajuste"
                  value={motivoAjuste}
                  onChange={(e) => setMotivoAjuste(e.target.value)}
                  placeholder="Ex.: pagamento parcial acordado com o parceiro"
                  className="bg-background"
                />
              </div>
            ) : null}
          </div>

          <DialogFooter className="gap-2 border-t border-border bg-muted/30 px-6 py-4 sm:justify-end sm:px-8">
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => setIsConcluirOpen(false)}
              disabled={concluindo}
            >
              Cancelar
            </Button>
            <Button
              onClick={() => void handleConcluirFechamento()}
              disabled={concluindo || isReadonly || !podeConcluirFechamento}
              className="min-w-[160px] shadow-md hover:shadow-primary/40"
            >
              {concluindo ? (
                <>
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  Concluindo...
                </>
              ) : (
                "Concluir"
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={isReabrirOpen} onOpenChange={setIsReabrirOpen}>
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Reabrir fechamento</DialogTitle>
            <DialogDescription>
              Ao reabrir, o fechamento volta para edição e será necessário concluir novamente depois.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-2">
            <Label htmlFor="motivo-reabertura">Motivo *</Label>
            <Input
              id="motivo-reabertura"
              value={motivoReabertura}
              onChange={(e) => setMotivoReabertura(e.target.value)}
              placeholder="Ex.: ajuste após revisão financeira"
              required
            />
          </div>
          <DialogFooter>
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => setIsReabrirOpen(false)}
              disabled={reabrindo}
            >
              Cancelar
            </Button>
            <Button
              onClick={() => void handleReabrirFechamento()}
              disabled={reabrindo || !motivoReabertura.trim()}
            >
              {reabrindo ? "Reabrindo..." : "Confirmar reabertura"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
        <DialogContent className="sm:max-w-sm">
          <DialogHeader>
            <DialogTitle>Excluir lançamento</DialogTitle>
            <DialogDescription>
              Deseja realmente excluir o lançamento manual{" "}
              <strong>{deletingTarefa?.descricao}</strong>? Esta ação não pode ser desfeita.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="gap-2">
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => {
                setIsDeleteDialogOpen(false);
                setDeletingTarefa(null);
              }}
              disabled={deletingTaskId !== null}
            >
              Cancelar
            </Button>
            <Button
              variant="destructive"
              onClick={() => void confirmDeleteLancamento()}
              disabled={deletingTaskId !== null}
            >
              {deletingTaskId !== null ? "Excluindo..." : "Confirmar exclusão"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={isReprocessAsanaOpen} onOpenChange={setIsReprocessAsanaOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Reprocessar Asana deste fechamento</DialogTitle>
            <DialogDescription>
              Esta ação atualiza somente as tarefas do Asana para este parceiro no período da competência. Lançamentos
              manuais (bônus/desconto) serão preservados.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="gap-2">
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => setIsReprocessAsanaOpen(false)}
              disabled={reprocessandoAsana}
            >
              Cancelar
            </Button>
            <Button
              onClick={() => void handleReprocessarAsana()}
              disabled={reprocessandoAsana}
              variant="secondary"
              className="shadow-md hover:shadow-secondary/40"
            >
              {reprocessandoAsana ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  Reprocessando...
                </>
              ) : (
                "Confirmar reprocessamento"
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={isEditarOpen} onOpenChange={setIsEditarOpen}>
        <DialogContent className="sm:max-w-2xl">
          <DialogHeader>
            <DialogTitle>Editar tarefa</DialogTitle>
            <DialogDescription>
              {editingTarefa?.tipo === "bonus" || editingTarefa?.tipo === "desconto"
                ? "Para bônus/desconto, você pode editar apenas descrição e pontuação."
                : "Edite os campos da tarefa e salve as alterações."}
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            {editingTarefa?.tipo === "tarefa" ? (
              <>
                <div className="space-y-1">
                  <Label htmlFor="edit-ticket">Ticket</Label>
                  <Input id="edit-ticket" value={edicaoNumeroTicket} onChange={(e) => setEdicaoNumeroTicket(e.target.value)} />
                </div>
                <div className="space-y-1">
                  <Label htmlFor="edit-descricao">Descrição</Label>
                  <Input id="edit-descricao" value={edicaoDescricao} onChange={(e) => setEdicaoDescricao(e.target.value)} />
                </div>
                <div className="space-y-1">
                  <Label htmlFor="edit-cliente">Cliente</Label>
                  <Input id="edit-cliente" value={edicaoCliente} onChange={(e) => setEdicaoCliente(e.target.value)} />
                </div>
                <div className="space-y-1">
                  <Label htmlFor="edit-tempo">Horas (minutos)</Label>
                  <Input
                    id="edit-tempo"
                    type="number"
                    min={0}
                    step={1}
                    value={edicaoTempoMinutos}
                    onChange={(e) => setEdicaoTempoMinutos(e.target.value)}
                  />
                </div>
              </>
            ) : null}
            {editingTarefa?.tipo !== "tarefa" ? (
              <div className="space-y-1">
                <Label htmlFor="edit-descricao">Descrição</Label>
                <Input id="edit-descricao" value={edicaoDescricao} onChange={(e) => setEdicaoDescricao(e.target.value)} />
              </div>
            ) : null}
            <div className="space-y-1">
              <Label htmlFor="edit-pontuacao">Pontuação</Label>
              <Input
                id="edit-pontuacao"
                type="text"
                inputMode="decimal"
                value={edicaoPontuacao}
                onChange={(e) => setEdicaoPontuacao(e.target.value)}
              />
            </div>
          </div>
          <DialogFooter>
            <Button
              variant="outline"
              className="hover:bg-muted/60 hover:text-foreground"
              onClick={() => setIsEditarOpen(false)}
              disabled={savingEdicao}
            >
              Cancelar
            </Button>
            <Button onClick={() => void handleSalvarEdicao()} disabled={savingEdicao || bloqueioEdicaoTarefa}>
              {savingEdicao ? "Salvando..." : "Salvar"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
