"use client";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";

import { apiClient } from "@/lib/api/client";
import { showApiError } from "@/components/feedback/ApiErrorToast";
import { useT } from "@/hooks/i18n/useT";
import type { FlowGraph } from "@/lib/followup/graph-schema";
import type { FollowupFlowSurface } from "@/lib/followup/api-schemas";
import type { FollowupFlowStatus } from "./useFollowupFlows";

export interface FollowupFlowDetailRow {
  id: string;
  name: string;
  status: FollowupFlowStatus;
  active_version_id: string | null;
  draft_graph: FlowGraph | null;
  handoff_policy: "pause" | "cancel" | "allow";
  /**
   * #3974 — "enviar mesmo com a conversa atribuída a uma pessoa". Opção do
   * FLUXO, independente da política de handoff (que continua valendo para a IA
   * responder). Ausente em fluxo antigo = `false`, o comportamento de sempre.
   */
  send_when_assigned: boolean;
  trigger_config: Record<string, unknown>;
  /** Superfície do fluxo: decide a paleta, os controles da barra e o Fim. */
  surface: FollowupFlowSurface;
  created_at: string;
  updated_at: string;
  versions_count: number;
  previous_version_id: string | null;
}

interface SingleResponse {
  data: FollowupFlowDetailRow;
}

export function followupFlowQueryKey(id: string) {
  return ["followup", "flows", "detail", id] as const;
}

export function useFollowupFlow(id: string, opts?: { initialData?: FollowupFlowDetailRow }) {
  return useQuery({
    queryKey: followupFlowQueryKey(id),
    queryFn: async () => {
      try {
        const res = await apiClient.get<SingleResponse>(`/api/v1/ai/followup-flows/${id}`);
        return res.data;
      } catch (err) {
        showApiError(err);
        throw err;
      }
    },
    initialData: opts?.initialData,
  });
}

/** PATCH draft_graph — "Salvar". Errors handled by the caller (dirty-state UI), no toast noise. */
export function useSaveFollowupFlowDraft(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (draft_graph: FlowGraph) => {
      const res = await apiClient.patch<SingleResponse>(`/api/v1/ai/followup-flows/${id}`, {
        draft_graph,
      });
      return res.data;
    },
    onSuccess: (updated) => {
      qc.setQueryData<FollowupFlowDetailRow>(followupFlowQueryKey(id), (prev) =>
        prev ? { ...prev, ...updated } : prev,
      );
      toast.success(t("Rascunho salvo."));
    },
    onError: (err) => showApiError(err),
  });
}

/**
 * POST publish. Deliberately NO onError toast here: a 422 validation_failed
 * carries `details.errors[].node_id` that the caller renders anchored to the
 * offending node — a generic toast would duplicate/bury that signal.
 */
export function usePublishFollowupFlow(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async () => {
      const res = await apiClient.post<SingleResponse>(`/api/v1/ai/followup-flows/${id}/publish`, {});
      return res.data;
    },
    onSuccess: (data) => {
      qc.invalidateQueries({ queryKey: followupFlowQueryKey(id) });
      qc.invalidateQueries({ queryKey: ["followup", "flows", "list"] });
      toast.success(t("Fluxo publicado."));
      // OS AVISOS DO GATILHO, um a um, no momento em que a pessoa está olhando.
      // Eles não reprovam a publicação (ver `avisosDoGatilho`), e guardá-los
      // para depois é guardá-los para nunca. `duration` longa de propósito: a
      // frase é longa e diz o que fazer, não só que há algo errado.
      const avisos = (data as { avisos?: Array<{ code: string; message: string }> } | undefined)?.avisos;
      for (const aviso of avisos ?? []) {
        toast.warning(t(aviso.message), { duration: 12_000 });
      }
    },
  });
}

export function useDeleteFollowupFlow() {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (id: string) => {
      const res = await apiClient.delete<{ data: { id: string } }>(`/api/v1/ai/followup-flows/${id}`);
      return res.data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["followup", "flows", "list"] });
      toast.success(t("Fluxo excluído."));
    },
    onError: (err) => showApiError(err),
  });
}

export function useDisableFollowupFlow(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async () => {
      const res = await apiClient.post<{ data: { id: string; status: string } }>(
        `/api/v1/ai/followup-flows/${id}/disable`,
        {},
      );
      return res.data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: followupFlowQueryKey(id) });
      qc.invalidateQueries({ queryKey: ["followup", "flows", "list"] });
      toast.success(t("Fluxo desativado."));
    },
    onError: (err) => showApiError(err),
  });
}

export function useRollbackFollowupFlow(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (version_id: string) => {
      const res = await apiClient.post<SingleResponse>(`/api/v1/ai/followup-flows/${id}/rollback`, {
        version_id,
      });
      return res.data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: followupFlowQueryKey(id) });
      toast.success(t("Fluxo revertido para a versão anterior."));
    },
    onError: (err) => showApiError(err),
  });
}

/** PATCH trigger_config — controle de gatilho (Manual/Silêncio) na PublishBar. */
export function useUpdateTriggerConfig(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (trigger_config: Record<string, unknown>) => {
      const res = await apiClient.patch<SingleResponse>(`/api/v1/ai/followup-flows/${id}`, {
        trigger_config,
      });
      return res.data;
    },
    onSuccess: (updated) => {
      qc.setQueryData<FollowupFlowDetailRow>(followupFlowQueryKey(id), (prev) =>
        prev ? { ...prev, ...updated } : prev,
      );
      toast.success(t("Gatilho atualizado."));
    },
    onError: (err) => showApiError(err),
  });
}

export function useRenameFollowupFlow() {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async ({ id, name }: { id: string; name: string }) => {
      const res = await apiClient.patch<SingleResponse>(`/api/v1/ai/followup-flows/${id}`, { name });
      return res.data;
    },
    onSuccess: (updated) => {
      qc.setQueryData<FollowupFlowDetailRow>(followupFlowQueryKey(updated.id), (prev) =>
        prev ? { ...prev, ...updated } : prev,
      );
      qc.invalidateQueries({ queryKey: ["followup", "flows", "list"] });
      toast.success(t("Fluxo renomeado."));
    },
  });
}

export function useUpdateHandoffPolicy(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (handoff_policy: "pause" | "cancel" | "allow") => {
      const res = await apiClient.patch<SingleResponse>(`/api/v1/ai/followup-flows/${id}`, {
        handoff_policy,
      });
      return res.data;
    },
    onSuccess: (updated) => {
      qc.setQueryData<FollowupFlowDetailRow>(followupFlowQueryKey(id), (prev) =>
        prev ? { ...prev, ...updated } : prev,
      );
      toast.success(t("Política de handoff atualizada."));
    },
    onError: (err) => showApiError(err),
  });
}

/**
 * #3974 — a opção "enviar mesmo com a conversa atribuída a uma pessoa".
 *
 * PATCH da coluna do pointer, como a política de handoff: é uma decisão do
 * FLUXO (esta etapa manda mesmo com o vendedor dono da conversa?), não um ajuste
 * de tela — por isso não passa por `draft_graph` e não exige salvar o grafo.
 */
export function useUpdateSendWhenAssigned(id: string) {
  const t = useT();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (send_when_assigned: boolean) => {
      const res = await apiClient.patch<SingleResponse>(`/api/v1/ai/followup-flows/${id}`, {
        send_when_assigned,
      });
      return res.data;
    },
    onSuccess: (updated) => {
      qc.setQueryData<FollowupFlowDetailRow>(followupFlowQueryKey(id), (prev) =>
        prev ? { ...prev, ...updated } : prev,
      );
      toast.success(t("Opção de envio com a conversa atribuída atualizada."));
    },
    onError: (err) => showApiError(err),
  });
}
