import { AVISO_DE_DADOS, contagem, exigir, falha, limparBusca, pode, recusar } from "./comum";
import { empresaNoEstoqueV2 } from "./estoque-do-canal";
import { consultarEstoqueV2 } from "./estoque-v2";
import type { FerramentaDeLeitura } from "./tipos";

type Insumo = {
  id: string;
  name: string | null;
  unit: string | null;
  current_stock: number | null;
  min_stock_alert: number | null;
};

type ProdutoComEstoque = {
  id: string;
  name: string | null;
  stock: number | null;
  sku: string | null;
  inventory_scope: string | null;
};

export const consultarEstoque: FerramentaDeLeitura = {
  nome: "consultar_estoque",
  titulo: "Consultar o estoque",
  descricao:
    "Mostra o estoque dos insumos (papel, tinta, canecas em branco) e dos produtos prontos que a empresa controla. Com apenas_baixo, traz só o que está no mínimo ou abaixo dele, que é a lista do que repor. No estoque novo, traz a grade (tamanho, cor) com o saldo de cada célula.",
  campos: {
    busca: { tipo: "texto", descricao: "Parte do nome do insumo ou do produto.", max: 80 },
    apenas_baixo: { tipo: "booleano", descricao: "Só o que está no estoque mínimo ou abaixo." },
  },
  tipo: "leitura",
  permissoes: ["materials.read", "products.stock.read"],
  async executar(ctx, args) {
    const veInsumos = pode(ctx, "materials.read");
    const veProdutos = pode(ctx, "products.stock.read");
    if (!veInsumos && !veProdutos) exigir(ctx, "products.stock.read", "ver o estoque");
    /* Estoque v2: os itens com a grade e o saldo por célula (os campos
       antigos ficam de fora: são só espelho). */
    if (await empresaNoEstoqueV2(ctx)) return consultarEstoqueV2(ctx, args);

    const busca = limparBusca(args.busca);
    const apenasBaixo = args.apenas_baixo === true;
    const dados: Record<string, unknown> = { _observacao: AVISO_DE_DADOS };
    let contados = 0;

    if (veInsumos) {
      let consulta = ctx.supabase
        .from("materials")
        .select("id,name,unit,current_stock,min_stock_alert")
        .in("user_id", ctx.tenantIds)
        .eq("track_stock", true)
        .not("is_active", "is", false)
        .order("name")
        .limit(500);
      if (busca) consulta = consulta.ilike("name", `%${busca}%`);
      const { data, error } = await consulta;
      if (error) falha("ler o estoque de insumos", error);

      const insumos = ((data ?? []) as Insumo[])
        .map((insumo) => {
          const atual = Number(insumo.current_stock ?? 0);
          const minimo = insumo.min_stock_alert === null ? null : Number(insumo.min_stock_alert);
          return {
            id: insumo.id,
            nome: insumo.name ?? "",
            unidade: insumo.unit || null,
            em_estoque: atual,
            minimo,
            baixo: minimo !== null && atual <= minimo,
          };
        })
        .filter((insumo) => !apenasBaixo || insumo.baixo);
      dados.insumos = insumos.slice(0, 100);
      if (insumos.length > 100) dados.insumos_cortados_em = 100;
      contados += insumos.length;
    }

    /* Produto pronto não tem estoque mínimo cadastrado: "baixo" aqui é zerado. */
    if (veProdutos) {
      let consulta = ctx.supabase
        .from("products")
        .select("id,name,stock,sku,inventory_scope")
        .in("user_id", ctx.tenantIds)
        .neq("product_kind", "digital")
        .eq("track_inventory", true)
        .eq("active", true)
        .order("name")
        .limit(500);
      if (busca) consulta = consulta.ilike("name", `%${busca}%`);
      const { data, error } = await consulta;
      if (error) falha("ler o estoque de produtos", error);

      const produtos = ((data ?? []) as ProdutoComEstoque[])
        .map((produto) => ({
          id: produto.id,
          nome: produto.name ?? "",
          codigo: produto.sku || null,
          em_estoque: Number(produto.stock ?? 0),
          zerado: Number(produto.stock ?? 0) <= 0,
          ...(produto.inventory_scope && produto.inventory_scope !== "product" ? { controlado_por_variacao: true } : {}),
        }))
        .filter((produto) => !apenasBaixo || produto.zerado);
      dados.produtos_prontos = produtos.slice(0, 100);
      if (produtos.length > 100) dados.produtos_cortados_em = 100;
      contados += produtos.length;
    }

    if (!contados && !busca && !apenasBaixo) {
      recusar("Esta empresa ainda não controla estoque de nenhum insumo nem produto. O controle é ligado no cadastro de cada um, no painel.");
    }

    return {
      dados,
      resumo: `Consultou o estoque${apenasBaixo ? " baixo" : ""} (${contagem(contados, "item", "itens")})`,
    };
  },
};
