import { apagarArquivoDaBiblioteca } from "@/lib/digitais/servidor/acoes/arquivos";
import {
  arquivosDasGravacoes,
  cancelarLiveDaLoja,
  conviteParaApresentarJunto,
  criarLiveDaLoja,
  lerLiveDaLoja,
  linkParaApresentar,
  listarLivesDaLoja,
  salvarLiveDaLoja,
} from "@/lib/digitais/servidor/acoes/lives";
import type { ContextoDigital } from "@/lib/digitais/servidor/contexto";
import { configuracaoDoR2 } from "@/lib/digitais/r2";
import { semLimiteDePessoas } from "@/lib/live/sala";

import type { ContextoDoAssistente } from "../contexto";
import type { Campos } from "../esquema";
import { DESCRICAO_DO_CAMPO_DE_IMAGEM } from "../imagens";
import { AVISO_DE_DADOS, exigir, reais, recusar, texto } from "./comum";
import {
  abrirDigital,
  COMO_MOSTRAR_O_LINK,
  guardarImagemDigital,
  linkCurtoDoArquivo,
  naRota,
  prepararImagemDigital,
  semContatoNovo,
  type ImagemDigital,
} from "./digitais-comum";
import { CAMPOS_DA_LIVE, dadosDaLiveParaSalvar, dataEHoraBr, duracaoBr, mudaPrecoNaLoja, SITUACAO_DA_LIVE, tamanhoBr } from "./digitais-regras";
import type { Ferramenta, FerramentaDeEscrita, FerramentaDeLeitura } from "./tipos";

/*
 * KtaloguLive pelo assistente, como a tela Lives: listar, ver, criar (live de
 * venda, com página na loja, ou reunião por link), mudar todos os detalhes,
 * pôr ou tirar da loja, cancelar, o link de quem apresenta, o convite para
 * apresentar junto, e as gravações (link curto de 24 horas para assistir ou
 * baixar; apagar). Pelas funções das rotas (lib/digitais/servidor/acoes/lives.ts),
 * com a permissão da tela (digital.products.read / digital.products.write).
 */

const PARTICIPACAO: Record<string, string> = { levantando_a_mao: "mao", so_quem_apresenta: "so_apresentador", todo_mundo: "livre" };
const PARTICIPACAO_NA_FERRAMENTA: Record<string, string> = { mao: "levantando_a_mao", so_apresentador: "so_quem_apresenta", livre: "todo_mundo" };

const CAMPOS_DA_FICHA_DA_LIVE: Campos = {
  titulo: { tipo: "texto", descricao: "Nome da live (ou da reunião).", max: 160 },
  dia: { tipo: "data", descricao: "Dia (Brasília)." },
  hora: { tipo: "hora", descricao: "Hora de começar (Brasília)." },
  duracao_min: { tipo: "inteiro", descricao: "Duração prevista em minutos (10 a 720; padrão 60).", min: 10, max: 720 },
  espera_min: { tipo: "inteiro", descricao: "Minutos antes em que a sala abre para esperar (0 a 120; padrão 15).", min: 0, max: 120 },
  acesso: { tipo: "opcao", descricao: "Live de venda: paga (com preço), cadastro (grátis com cadastro) ou aberta (quem tem o link). Reunião é sempre aberta.", opcoes: ["paga", "cadastro", "aberta"] },
  preco: { tipo: "numero", descricao: "Preço da vaga em reais (live paga; a partir de 1,00).", min: 0, max: 1_000_000 },
  vender_durante: { tipo: "booleano", descricao: "Continua vendendo a vaga durante a live." },
  limite_de_vagas: { tipo: "inteiro", descricao: "Limite de vagas (0 = sem limite).", min: 0, max: 100000 },
  participacao: { tipo: "opcao", descricao: "Quem fala: levantando_a_mao (você libera), so_quem_apresenta (o resto só no bate-papo) ou todo_mundo.", opcoes: ["levantando_a_mao", "so_quem_apresenta", "todo_mundo"] },
  cameras_dos_participantes: { tipo: "booleano", descricao: "Quem participa pode ligar a câmera." },
  chat: { tipo: "opcao", descricao: "Bate-papo: aberto, perguntas (só perguntas) ou desligado.", opcoes: ["aberto", "perguntas", "desligado"] },
  gravar: { tipo: "booleano", descricao: "Gravar a live." },
  gravacao_para: { tipo: "opcao", descricao: "Live de venda: a gravação fica para os compradores ou para ninguém (só a loja baixa).", opcoes: ["compradores", "ninguem"] },
  gravacao_modo: { tipo: "opcao", descricao: "O que grava: palco (a tela com a câmera de quem apresenta) ou sala (a sala inteira, como no Meet).", opcoes: ["palco", "sala"] },
  vaga: { tipo: "opcao", descricao: "Qual vaga do KtaloguLive a live usa: gratis (as do mês) ou pacote (com pacote_id).", opcoes: ["gratis", "pacote"] },
  pacote_id: { tipo: "id", descricao: "O pacote KtaloguLive (compra_id em saldo.pacotes de listar_lives)." },
  itens_para_soltar: {
    tipo: "lista",
    descricao: "\"Para soltar na live\": cupons, produtos da loja e links que aparecem em cima do vídeo num toque (troca a lista; [] apaga; até 30).",
    maxItens: 30,
    itens: {
      tipo: { tipo: "opcao", descricao: "cupom, produto ou link.", opcoes: ["cupom", "produto", "link"], obrigatorio: true },
      titulo: { tipo: "texto", descricao: "O que aparece (produto: padrão o nome dele).", max: 90 },
      detalhe: { tipo: "texto", descricao: "Uma linha a mais (ex.: 10% na primeira compra).", max: 140 },
      codigo: { tipo: "texto", descricao: "Cupom: o código.", max: 40 },
      produto_id: { tipo: "id", descricao: "Produto: o id do produto da loja (buscar_produtos ou listar_produtos_digitais)." },
      link: { tipo: "texto", descricao: "Link: o endereço (https://). Cupom: link opcional do botão.", max: 1000 },
      preco: { tipo: "numero", descricao: "Preço mostrado (opcional).", min: 0, max: 1_000_000 },
      preco_de: { tipo: "numero", descricao: "Preço \"de\" riscado (opcional).", min: 0, max: 1_000_000 },
    },
  },
  vitrine: { tipo: "booleano", descricao: "Live de venda: mostrar a vitrine de produtos durante a live (liveshop)." },
  produtos_da_vitrine: { tipo: "textos", descricao: "Ids dos produtos da vitrine (até 40; troca a lista).", max: 40, maxItens: 40 },
  apresentador_nome: { tipo: "texto", descricao: "Quem apresenta: nome.", max: 80 },
  apresentador_bio: { tipo: "texto", descricao: "Quem apresenta: uma linha sobre a pessoa.", max: 200 },
  apresentador_foto: { tipo: "texto", descricao: `Quem apresenta: foto quadrada. ${DESCRICAO_DO_CAMPO_DE_IMAGEM}`, max: 2000 },
  o_que_vai_ver: { tipo: "textos", descricao: "O que a pessoa vai ver na live (até 8 frases; troca a lista).", max: 140, maxItens: 8 },
  capa: { tipo: "texto", descricao: `Capa quadrada da live. ${DESCRICAO_DO_CAMPO_DE_IMAGEM}`, max: 2000 },
  descricao: { tipo: "texto", descricao: "Descrição da página da live.", max: 4000 },
};

type LiveLida = Awaited<ReturnType<typeof lerLiveDaLoja>>;

function liveParaOAssistente(l: LiveLida["live"], links?: LiveLida["links"]) {
  return {
    live_id: l.id,
    categoria: l.categoria === "reuniao" ? "reuniao" : "venda",
    titulo: l.titulo,
    quando: dataEHoraBr(l.comecaEm),
    duracao_min: l.duracaoMin,
    sala_abre_antes_min: l.esperaMin,
    situacao: SITUACAO_DA_LIVE[l.situacao] ?? l.situacao,
    na_loja: l.naLoja,
    acesso: l.acesso,
    preco: reais(l.preco),
    vagas_garantidas: l.vagas,
    limite_de_vagas: l.limiteVagas,
    vender_durante: l.venderDurante,
    participacao: PARTICIPACAO_NA_FERRAMENTA[l.participacao] ?? l.participacao,
    cameras_dos_participantes: l.camerasAlunos,
    chat: l.chat,
    gravar: l.gravar,
    gravacao_para: l.gravacaoPara,
    gravacao_modo: l.gravacaoModo,
    gravacao: { situacao: l.gravacao.status, duracao: duracaoBr(l.gravacao.segundos), tamanho: l.gravacao.bytes ? tamanhoBr(l.gravacao.bytes) : null },
    vaga: l.vaga,
    pacote_id: l.vagaCompraId,
    itens_para_soltar: l.itens.map((i) => ({ tipo: i.tipo, titulo: i.titulo, detalhe: i.detalhe, codigo: i.codigo, link: i.destino, preco: i.preco, preco_de: i.precoDe })),
    vitrine: l.vitrine,
    produtos_da_vitrine: l.produtosVitrine,
    apresentador: { nome: l.apresentadorNome, bio: l.apresentadorBio, foto: l.apresentadorFoto },
    o_que_vai_ver: l.aprender,
    capa: l.capa,
    descricao: texto(l.descricao, 1500),
    pico_de_pessoas: l.picoPessoas,
    tem_convite_ativo: l.temConvite,
    ...(links
      ? { link_da_sala: links.sala, link_da_pagina_de_venda: links.pagina }
      : { link_da_sala: l.link }),
  };
}

function saldoParaOAssistente(saldo: LiveLida["saldo"]) {
  return {
    gratis_no_mes: saldo.ilimitado ? "sem limite (cortesia)" : `${saldo.gratis_restantes} de ${saldo.gratis_por_mes}`,
    pessoas_por_live_gratis: semLimiteDePessoas(saldo) ? "sem limite de pessoas (cortesia)" : saldo.gratis_pessoas,
    pacotes: saldo.pacotes.map((p) => ({ compra_id: p.compra_id, nome: p.nome, lives_restantes: p.restantes, pessoas: p.pessoas, valido_ate: p.valida_ate })),
  };
}

async function lerLiveFerramenta(contexto: ContextoDigital, id: string) {
  return naRota(() => lerLiveDaLoja(contexto, id));
}

/* ------------------------------------------------------------ leituras */

export const listarLives: FerramentaDeLeitura = {
  nome: "listar_lives",
  titulo: "Ver as lives",
  descricao: "Lista as lives e reuniões da loja (KtaloguLive): quando, situação (agendada, hoje, no ar, encerrada, cancelada), se está na loja, preço, vagas, gravação e o link da sala; e o saldo do mês (lives grátis e pacotes).",
  campos: { situacao: { tipo: "opcao", descricao: "Filtrar: proximas (agendadas, hoje e no ar), passadas ou todas.", opcoes: ["proximas", "passadas", "todas"] } },
  tipo: "leitura",
  permissoes: ["digital.products.read"],
  async executar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.read", "ver as lives");
    const lista = await naRota(() => listarLivesDaLoja(contexto));
    const proximas = new Set(["agendada", "hoje", "ao_vivo"]);
    const lives = lista.lives
      .filter((l) => !args.situacao || args.situacao === "todas" || (args.situacao === "proximas" ? proximas.has(l.situacao) : !proximas.has(l.situacao)))
      .map((l) => liveParaOAssistente(l));
    return {
      dados: { _observacao: AVISO_DE_DADOS, saldo: saldoParaOAssistente(lista.saldo), lives, total: lives.length },
      resumo: `Consultou as lives (${lives.length})`,
    };
  },
};

export const verLive: FerramentaDeLeitura = {
  nome: "ver_live",
  titulo: "Ver uma live",
  descricao: "Todos os detalhes de uma live ou reunião, como a tela: configuração, itens para soltar, vitrine, quem apresenta, a gravação e os links (link da sala para mandar a quem vai participar e a página de venda). O link de quem apresenta sai em link_para_apresentar.",
  campos: { live_id: { tipo: "id", descricao: "Id da live (de listar_lives).", obrigatorio: true } },
  tipo: "leitura",
  permissoes: ["digital.products.read"],
  async executar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.read", "ver as lives");
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    return {
      dados: { _observacao: AVISO_DE_DADOS, live: liveParaOAssistente(lido.live, lido.links), saldo: saldoParaOAssistente(lido.saldo) },
      resumo: `Consultou a live ${lido.live.titulo}`,
    };
  },
};

/* ------------------------------------------------------------ montar os dados */

type ImagensDaLive = { capa: ImagemDigital | null; foto: ImagemDigital | null };

async function dadosDaFicha(ctx: ContextoDoAssistente, contexto: ContextoDigital, args: Record<string, unknown>, base: Record<string, unknown>) {
  const dados: Record<string, unknown> = { ...base };
  for (const [campo, chave] of Object.entries(CAMPOS_DA_LIVE)) {
    if (args[campo] === undefined) continue;
    dados[chave] = campo === "participacao" ? PARTICIPACAO[String(args[campo])] : args[campo];
  }
  if (args.limite_de_vagas === 0) dados.limiteVagas = null;
  if (args.dia !== undefined || args.hora !== undefined) {
    const atual = typeof base.comecaEm === "string" ? new Date(new Date(base.comecaEm).getTime() - 3 * 3600 * 1000).toISOString() : null;
    dados.dia = args.dia ?? atual?.slice(0, 10);
    dados.hora = args.hora ?? atual?.slice(11, 16);
    if (!dados.dia || !dados.hora) recusar("Diga o dia e a hora da live.");
    delete dados.comecaEm;
  }
  if (args.itens_para_soltar !== undefined) {
    const itens: Record<string, unknown>[] = [];
    for (const item of args.itens_para_soltar as Array<Record<string, unknown>>) {
      if (item.tipo === "produto") {
        if (!item.produto_id) recusar("Item de produto: diga o produto_id.");
        const { data } = await contexto.admin
          .from("products")
          .select("id,name,price,image_url")
          .eq("id", String(item.produto_id))
          .eq("user_id", contexto.lojaId)
          .neq("active", false)
          .maybeSingle();
        const produto = data as { id: string; name: string; price: number | null; image_url: string | null } | null;
        if (!produto) recusar("Produto da loja não encontrado para o item da live.");
        itens.push({
          tipo: "produto",
          titulo: item.titulo ?? produto.name,
          detalhe: item.detalhe,
          imagem: produto.image_url && /^https:/.test(produto.image_url) ? produto.image_url : null,
          preco: item.preco ?? (Number(produto.price) || null),
          precoDe: item.preco_de,
          destino: `/p/${produto.id}`,
        });
      } else {
        if (!item.titulo) recusar("Cada item para soltar precisa de um título.");
        if (item.tipo === "link" && !item.link) recusar("Item de link: diga o link.");
        itens.push({ tipo: item.tipo, titulo: item.titulo, detalhe: item.detalhe, codigo: item.codigo, preco: item.preco, precoDe: item.preco_de, destino: item.link });
      }
    }
    dados.itens = itens;
  }
  if (args.produtos_da_vitrine !== undefined) {
    const ids = (args.produtos_da_vitrine as string[]).filter((id) => /^[0-9a-f-]{36}$/i.test(id));
    if (ids.length) {
      const { data } = await contexto.admin.from("products").select("id").eq("user_id", contexto.lojaId).in("id", ids);
      const achados = new Set(((data ?? []) as Array<{ id: string }>).map((p) => p.id));
      const faltam = ids.filter((id) => !achados.has(id));
      if (faltam.length) recusar(`Produtos da vitrine que não são desta loja: ${faltam.join(", ")}.`);
    }
    dados.produtosVitrine = ids;
  }
  const imagens: ImagensDaLive = {
    capa: args.capa ? await prepararImagemDigital(ctx, args.capa, "quadrada") : null,
    foto: args.apresentador_foto ? await prepararImagemDigital(ctx, args.apresentador_foto, "quadrada") : null,
  };
  semContatoNovo(
    JSON.stringify([base.titulo, base.descricao, base.apresentadorBio, base.aprender, base.apresentadorNome]),
    JSON.stringify([dados.titulo, dados.descricao, dados.apresentadorBio, dados.aprender, dados.apresentadorNome]),
    "na tela da live"
  );
  return { dados, imagens };
}

async function comImagens(ctx: ContextoDoAssistente, dados: Record<string, unknown>, imagens: ImagensDaLive) {
  const pronto = { ...dados };
  if (imagens.capa) pronto.capa = await guardarImagemDigital(ctx, imagens.capa, "digitais/lives");
  if (imagens.foto) pronto.apresentadorFoto = await guardarImagemDigital(ctx, imagens.foto, "digitais/apresentadores");
  return pronto;
}

/* ------------------------------------------------------------ criar */

type CargaDaLive = { liveId: string | null; dados: Record<string, unknown>; imagens: ImagensDaLive; naLoja: boolean | null; titulo: string };

export const criarLive: FerramentaDeEscrita<CargaDaLive> = {
  nome: "criar_live",
  titulo: "Criar uma live ou reunião",
  descricao:
    "Cria uma live (KtaloguLive). categoria venda = live da loja virtual, com página de venda (nasce fora da loja; publique com alterar_live na_loja); categoria reuniao = conversa por link, como o Meet (nunca vai à loja; o link já sai pronto). Mande dia e hora, ou agora = true para começar já. Devolve o link da sala para mandar a quem vai participar e, com agora, o link de quem apresenta. Usa uma live do saldo do mês (ou do pacote escolhido).",
  campos: {
    categoria: { tipo: "opcao", descricao: "venda ou reuniao.", opcoes: ["venda", "reuniao"], obrigatorio: true },
    agora: { tipo: "booleano", descricao: "true = começar agora (reunião instantânea)." },
    ...CAMPOS_DA_FICHA_DA_LIVE,
    titulo: { tipo: "texto", descricao: "Nome da live (ou da reunião).", obrigatorio: true, max: 160 },
  },
  tipo: "escrita",
  permissoes: ["digital.products.write"],
  async preparar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "criar lives");
    if (!args.agora && (!args.dia || !args.hora)) recusar("Diga o dia e a hora da live (ou agora = true para começar já).");
    const { dados, imagens } = await dadosDaFicha(ctx, contexto, args, { categoria: args.categoria });
    if (args.agora === true) dados.agora = true;
    if (args.categoria === "venda" && !dados.acesso) dados.acesso = "paga";
    return {
      previa: {
        categoria: args.categoria,
        titulo: args.titulo,
        quando: args.agora ? "agora" : `${args.dia} ${args.hora}`,
        ...(args.categoria === "venda" ? { acesso: dados.acesso, preco: dados.preco !== undefined ? reais(dados.preco) : null, fica: "fora da loja até publicar" } : {}),
      },
      resumo: `Prévia de ${args.categoria === "reuniao" ? "reunião" : "live"} nova`,
      avisos: [],
      carga: { liveId: null, dados, imagens, naLoja: null, titulo: String(args.titulo) },
    };
  },
  async gravar(ctx, carga) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "criar lives");
    const corpo = await comImagens(ctx, carga.dados, carga.imagens);
    const criada = await naRota(() => criarLiveDaLoja(contexto, corpo));
    const lido = await lerLiveFerramenta(contexto, criada.id);
    return {
      dados: {
        live: liveParaOAssistente(lido.live, lido.links),
        ...(criada.apresentar ? { link_para_apresentar: criada.apresentar, link_para_apresentar_vale: "12 horas, só para quem organiza" } : {}),
        proximo_passo:
          lido.live.categoria === "reuniao"
            ? "Mande o link_da_sala a quem vai participar. Na hora, quem organiza entra pelo link_para_apresentar (peça com link_para_apresentar)."
            : "A live nasceu fora da loja. Publique com alterar_live (na_loja true) quando a pessoa pedir; o link_da_sala é para quem garantiu a vaga.",
      },
      resumo: `Criou a ${lido.live.categoria === "reuniao" ? "reunião" : "live"} ${lido.live.titulo}`,
    };
  },
};

/* ------------------------------------------------------------ alterar */

export const alterarLive: FerramentaDeEscrita<CargaDaLive> = {
  nome: "alterar_live",
  titulo: "Mudar uma live",
  descricao:
    "Muda qualquer detalhe de uma live ou reunião (nome, dia e hora, duração, acesso e preço, vagas, participação, câmeras, bate-papo, gravação, itens para soltar, vitrine, quem apresenta, capa, descrição) e põe ou tira da loja (na_loja). Mudar o dia faz os lembretes saírem de novo no horário novo. Mudar o preço de live que está na loja pede confirmação. Mande só o que muda.",
  campos: {
    live_id: { tipo: "id", descricao: "Id da live.", obrigatorio: true },
    ...CAMPOS_DA_FICHA_DA_LIVE,
    na_loja: { tipo: "booleano", descricao: "Live de venda: true = põe na loja; false = tira." },
  },
  tipo: "escrita",
  sobrescreve: true,
  permissoes: ["digital.products.write"],
  async preparar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "mudar lives");
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    const base = dadosDaLiveParaSalvar(lido.live as unknown as Record<string, unknown>);
    const { dados, imagens } = await dadosDaFicha(ctx, contexto, args, base);
    const mudou = Object.keys(args).filter((k) => k !== "live_id");
    if (!mudou.length) recusar("Nada para mudar.");
    const sensivel = mudaPrecoNaLoja({ naLoja: lido.live.naLoja && args.na_loja !== false, precoAtual: lido.live.preco, precoNovo: args.preco as number | undefined });
    return {
      previa: {
        live: lido.live.titulo,
        mudancas: mudou,
        ...(args.preco !== undefined ? { preco: `${reais(lido.live.preco)} → ${reais(args.preco)}` } : {}),
        ...(args.na_loja !== undefined ? { na_loja: args.na_loja } : {}),
      },
      resumo: `Prévia da mudança na live ${lido.live.titulo}`,
      avisos: sensivel ? ["A live está na loja: o preço novo vale para as próximas vagas assim que confirmar."] : [],
      sensivel,
      carga: { liveId: lido.live.id, dados, imagens, naLoja: typeof args.na_loja === "boolean" ? args.na_loja : null, titulo: lido.live.titulo },
    };
  },
  async gravar(ctx, carga) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "mudar lives");
    const dados = await comImagens(ctx, carga.dados, carga.imagens);
    await naRota(() => salvarLiveDaLoja(contexto, carga.liveId!, { dados, ...(carga.naLoja !== null ? { naLoja: carga.naLoja } : {}) }));
    const lido = await lerLiveFerramenta(contexto, carga.liveId!);
    return { dados: { live: liveParaOAssistente(lido.live, lido.links) }, resumo: `Mudou a live ${lido.live.titulo}` };
  },
};

export const cancelarLive: FerramentaDeEscrita<CargaDaLive> = {
  nome: "cancelar_live",
  titulo: "Cancelar uma live",
  descricao: "Cancela uma live ou reunião agendada: sai da loja e a sala não abre mais (o link deixa de funcionar). Quem garantiu vaga precisa ser avisado pela loja e, se pagou, receber a devolução pelo pedido. Sempre pede confirmação.",
  campos: { live_id: { tipo: "id", descricao: "Id da live.", obrigatorio: true } },
  tipo: "escrita",
  sobrescreve: true,
  sensivel: true,
  permissoes: ["digital.products.write"],
  async preparar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "cancelar lives");
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    if (lido.live.status !== "agendada") recusar(lido.live.status === "cancelada" ? "Esta live já está cancelada." : "Só live agendada se cancela (no ar, encerre pela sala).");
    return {
      previa: { cancelar: lido.live.titulo, quando: dataEHoraBr(lido.live.comecaEm), vagas_garantidas: lido.live.vagas },
      resumo: `Prévia de cancelar a live ${lido.live.titulo}`,
      avisos: lido.live.vagas
        ? [`${lido.live.vagas} ${lido.live.vagas === 1 ? "pessoa já garantiu" : "pessoas já garantiram"} a vaga: avise e, se foi pago, devolva pelo pedido.`]
        : [],
      carga: { liveId: lido.live.id, dados: {}, imagens: { capa: null, foto: null }, naLoja: null, titulo: lido.live.titulo },
    };
  },
  async gravar(ctx, carga) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "cancelar lives");
    await naRota(() => cancelarLiveDaLoja(contexto, carga.liveId!));
    return { dados: { cancelada: carga.titulo }, resumo: `Cancelou a live ${carga.titulo}` };
  },
};

/* ------------------------------------------------------------ links */

type CargaDoLink = { liveId: string; titulo: string };

export const linkParaApresentarFerramenta: FerramentaDeEscrita<CargaDoLink> = {
  nome: "link_para_apresentar",
  titulo: "Link de quem apresenta a live",
  descricao:
    "O link de \"Entrar ao vivo\" (ou \"Entrar na reunião\") de quem organiza: entra nos bastidores, com os controles (silenciar, tirar alguém, gravar). Vale 12 horas e é só da pessoa que organiza: não mande a participantes (para eles é o link_da_sala de ver_live).",
  campos: { live_id: { tipo: "id", descricao: "Id da live.", obrigatorio: true } },
  tipo: "escrita",
  permissoes: ["digital.products.write"],
  async preparar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "apresentar lives");
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    return { previa: { live: lido.live.titulo }, resumo: "Prévia do link de quem apresenta", avisos: [], carga: { liveId: lido.live.id, titulo: lido.live.titulo } };
  },
  async gravar(ctx, carga) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "apresentar lives");
    const { link } = await naRota(() => linkParaApresentar(contexto, carga.liveId));
    return {
      dados: { link_para_apresentar: link, vale: "12 horas", proximo_passo: "Mostre o link à pessoa exatamente como veio. É só dela (quem organiza): não mande a participantes." },
      resumo: `Gerou o link de quem apresenta a live ${carga.titulo}`,
    };
  },
};

export const gerarConviteDaLive: FerramentaDeEscrita<CargaDoLink> = {
  nome: "gerar_convite_da_live",
  titulo: "Convidar alguém para apresentar junto",
  descricao: "Gera o link de convite para alguém apresentar junto (entra já com microfone, câmera e tela). Gerar outro cancela o anterior.",
  campos: { live_id: { tipo: "id", descricao: "Id da live.", obrigatorio: true } },
  tipo: "escrita",
  sobrescreve: true,
  permissoes: ["digital.products.write"],
  async preparar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "convidar para as lives");
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    return {
      previa: { live: lido.live.titulo, convite_anterior_para_de_valer: lido.live.temConvite },
      resumo: "Prévia do convite para apresentar junto",
      avisos: lido.live.temConvite ? ["O convite anterior deixa de funcionar."] : [],
      carga: { liveId: lido.live.id, titulo: lido.live.titulo },
    };
  },
  async gravar(ctx, carga) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "convidar para as lives");
    const { link } = await naRota(() => conviteParaApresentarJunto(contexto, carga.liveId));
    return {
      dados: { link_de_convite: link, proximo_passo: "Mostre o link exatamente como veio; a pessoa manda a quem vai apresentar junto." },
      resumo: `Gerou um convite para apresentar junto na live ${carga.titulo}`,
    };
  },
};

/* ------------------------------------------------------------ gravações */

export const listarGravacoes: FerramentaDeLeitura = {
  nome: "listar_gravacoes",
  titulo: "Ver as gravações de uma live",
  descricao: "As gravações prontas de uma live, cada uma com um link curto para assistir e outro para baixar (valem 24 horas). Mostre os links exatamente como vierem.",
  campos: { live_id: { tipo: "id", descricao: "Id da live.", obrigatorio: true } },
  tipo: "leitura",
  permissoes: ["digital.products.read"],
  async executar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.read", "ver as gravações das lives");
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    if (!configuracaoDoR2()) recusar("O depósito de arquivos não está ligado neste servidor agora.");
    const arquivos = await naRota(() => arquivosDasGravacoes(contexto, lido.live.id));
    const gravacoes = [];
    for (const a of arquivos) {
      const links = await linkCurtoDoArquivo(ctx, { id: a.id, nome: a.nome });
      gravacoes.push({
        gravacao_id: a.id,
        nome: a.nome,
        duracao: duracaoBr(a.meta?.segundos),
        tamanho: tamanhoBr(a.tamanho_bytes),
        gravada_em: dataEHoraBr(a.criado_em),
        link_para_assistir: links.assistir,
        link_para_baixar: links.baixar,
      });
    }
    return {
      dados: {
        live: lido.live.titulo,
        situacao_da_gravacao: lido.live.gravacao.status,
        gravacoes,
        ...(gravacoes.length ? { proximo_passo: COMO_MOSTRAR_O_LINK } : { aviso: lido.live.gravar ? "Ainda não há gravação pronta desta live." : "Esta live não está marcada para gravar." }),
      },
      resumo: `Consultou as gravações da live ${lido.live.titulo} (${gravacoes.length})`,
    };
  },
};

type CargaDaGravacao = { arquivoId: string; nome: string };

export const apagarGravacao: FerramentaDeEscrita<CargaDaGravacao> = {
  nome: "apagar_gravacao",
  titulo: "Apagar a gravação de uma live",
  descricao: "Apaga uma gravação de live da biblioteca (sai do depósito em 30 dias; quem comprou deixa de ver). Sempre pede confirmação.",
  campos: {
    live_id: { tipo: "id", descricao: "Id da live.", obrigatorio: true },
    gravacao_id: { tipo: "id", descricao: "Id da gravação (de listar_gravacoes).", obrigatorio: true },
  },
  tipo: "escrita",
  sobrescreve: true,
  sensivel: true,
  permissoes: ["digital.products.write"],
  async preparar(ctx, args) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "apagar as gravações das lives");
    exigirArquivos(ctx);
    const lido = await lerLiveFerramenta(contexto, String(args.live_id));
    const arquivos = await naRota(() => arquivosDasGravacoes(contexto, lido.live.id));
    const gravacao = arquivos.find((a) => a.id === args.gravacao_id);
    if (!gravacao) recusar("Gravação não encontrada nesta live. Veja listar_gravacoes.");
    return {
      previa: { live: lido.live.titulo, apagar_gravacao: gravacao.nome, tamanho: tamanhoBr(gravacao.tamanho_bytes) },
      resumo: `Prévia de apagar a gravação ${gravacao.nome}`,
      avisos: lido.live.gravacaoPara === "compradores" ? ["Quem comprou a live deixa de ver esta gravação."] : [],
      carga: { arquivoId: gravacao.id, nome: gravacao.nome },
    };
  },
  async gravar(ctx, carga) {
    const contexto = await abrirDigital(ctx, "digital.products.write", "apagar as gravações das lives");
    exigirArquivos(ctx);
    await naRota(() => apagarArquivoDaBiblioteca(contexto.admin, contexto.lojaId, carga.arquivoId));
    return { dados: { apagada: carga.nome }, resumo: `Apagou a gravação ${carga.nome}` };
  },
};

/* Apagar a gravação é apagar um arquivo da biblioteca: a tela pede também "digital.files.write". */
function exigirArquivos(ctx: ContextoDoAssistente) {
  exigir(ctx, "digital.files.write", "apagar arquivos dos produtos digitais");
}

export const FERRAMENTAS_DE_LIVES: Ferramenta[] = [
  listarLives,
  verLive,
  criarLive,
  alterarLive,
  cancelarLive,
  linkParaApresentarFerramenta,
  gerarConviteDaLive,
  listarGravacoes,
  apagarGravacao,
] as Ferramenta[];
