import { linhaDaAgenda } from "./agenda";
import { AVISO_DE_DADOS, dinheiro, hojeEmBrasilia, nomeDoCliente, pode, um } from "./comum";
import { aReceberDePedidos, recebidoNoPeriodo } from "./financeiro";
import type { FerramentaDeLeitura } from "./tipos";

type Alerta = { tipo: string | null; gravidade: string | null; titulo: string | null; detalhe: string | null; quando: string | null };

type OrcamentoEnviado = {
  id: string;
  number: number | null;
  total: number | null;
  created_at: string | null;
  public_view_count: number | null;
  public_last_viewed_at: string | null;
  clients?: { name?: string | null; company_name?: string | null } | Array<{ name?: string | null; company_name?: string | null }> | null;
};

/*
  O "como está a minha gráfica hoje": junta num pedido só o que o dono abriria
  em quatro telas. Cada parte só aparece para quem tem a permissão dela; quem
  não tem recebe o resto, sem erro.
*/
export const resumoDoDia: FerramentaDeLeitura = {
  nome: "resumo_do_dia",
  titulo: "Resumo do dia",
  descricao:
    "O retrato de hoje da empresa, num pedido só: o que pede atenção (atrasos e vencimentos), o que está na agenda de hoje, os orçamentos enviados que esperam resposta (com quantas vezes o cliente abriu o link), os pedidos em andamento e, para quem pode ver, o dinheiro que entrou hoje e o que está a receber. É o melhor começo para perguntas como 'como está minha gráfica?'.",
  campos: {},
  tipo: "leitura",
  permissoes: [],
  async executar(ctx) {
    const hoje = hojeEmBrasilia();
    const dados: Record<string, unknown> = { _observacao: AVISO_DE_DADOS, hoje };
    const tarefas: Promise<void>[] = [];

    if (pode(ctx, "agenda.board.read")) {
      tarefas.push(
        (async () => {
          const [alertas, agenda] = await Promise.all([
            ctx.supabase.rpc("get_agenda_alertas"),
            ctx.supabase.rpc("get_agenda_range", { p_inicio: hoje, p_fim: hoje }),
          ]);
          if (!alertas.error) {
            dados.pede_atencao = ((alertas.data ?? []) as Alerta[]).slice(0, 25).map((alerta) => ({
              gravidade: alerta.gravidade,
              titulo: alerta.titulo ?? "",
              detalhe: alerta.detalhe || null,
              quando: alerta.quando,
            }));
          }
          if (!agenda.error) {
            dados.agenda_de_hoje = ((agenda.data ?? []) as Parameters<typeof linhaDaAgenda>[0][]).slice(0, 40).map(linhaDaAgenda);
          }
        })()
      );
    }

    if (pode(ctx, "quotes.read")) {
      tarefas.push(
        (async () => {
          const { data, error, count } = await ctx.supabase
            .from("quotes")
            .select("id,number,total,created_at,public_view_count,public_last_viewed_at,clients(name,company_name)", { count: "exact" })
            .in("user_id", ctx.tenantIds)
            .eq("status", "sent")
            .order("total", { ascending: false })
            .limit(8);
          if (error) return;
          const enviados = (data ?? []) as unknown as OrcamentoEnviado[];
          dados.orcamentos_esperando_resposta = {
            quantidade: count ?? enviados.length,
            maiores: enviados.map((orcamento) => ({
              id: orcamento.id,
              numero: orcamento.number,
              cliente: nomeDoCliente(um(orcamento.clients)),
              total: dinheiro(orcamento.total),
              enviado_em: orcamento.created_at,
              aberturas_do_link: Number(orcamento.public_view_count ?? 0),
              ultima_abertura: orcamento.public_last_viewed_at,
            })),
          };
        })()
      );
    }

    if (pode(ctx, "orders.read")) {
      tarefas.push(
        (async () => {
          const contar = () => ctx.supabase.from("orders").select("id", { count: "exact", head: true }).in("user_id", ctx.tenantIds);
          const [aguardando, produzindo, prontos, atrasados] = await Promise.all([
            contar().eq("status", "pending_production"),
            contar().eq("status", "in_production"),
            contar().eq("status", "finished"),
            contar().lt("delivery_date", hoje).not("status", "in", "(delivered,canceled)"),
          ]);
          dados.pedidos_em_andamento = {
            aguardando_producao: aguardando.count ?? 0,
            em_producao: produzindo.count ?? 0,
            prontos_para_entregar: prontos.count ?? 0,
            com_entrega_atrasada: atrasados.count ?? 0,
          };
        })()
      );
    }

    if (pode(ctx, "financial.overview.read") && pode(ctx, "financial.amounts.see")) {
      tarefas.push(
        (async () => {
          try {
            const [recebido, aReceber] = await Promise.all([recebidoNoPeriodo(ctx, hoje, hoje), aReceberDePedidos(ctx)]);
            dados.dinheiro = {
              entrou_hoje: recebido.total,
              a_receber_de_pedidos: aReceber.total,
              pedidos_em_aberto: aReceber.pedidos,
            };
          } catch {
            /* O resumo não cai por causa de uma parte: segue sem o dinheiro. */
          }
        })()
      );
    }

    await Promise.all(tarefas);

    return { dados, resumo: "Consultou o resumo do dia" };
  },
};
