import { after, NextResponse } from "next/server";

import { avisarLojaPorPush } from "@/lib/chats-push";
import { lerAjustesDigitais } from "@/lib/digitais/servidor/vitrine";
import { acessoAAula, nomeEntreAlunos } from "@/lib/digitais/servidor/curso";
import type { ComentarioNaTela } from "@/lib/digitais/tipos-do-curso";
import { createAdminClient } from "@/lib/supabase-admin";

/*
 * Os comentários de uma aula. Entre alunos aparece só o primeiro nome e a
 * inicial; a resposta da loja aparece com o nome dela. O comentário que
 * espera aprovação só aparece para quem escreveu.
 */

type Linha = {
  id: string;
  client_id: string | null;
  autor_equipe: string | null;
  parent_id: string | null;
  texto: string;
  status: string;
  curtidas: number;
  criado_em: string;
  clients: { name: string | null } | null;
};

const POR_DEZ_MINUTOS = 8;

export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
  const semCache = { headers: { "cache-control": "no-store" } };
  try {
    const { id } = await params;
    const slug = String(new URL(request.url).searchParams.get("slug") || "").trim().toLowerCase();
    const admin = createAdminClient();
    const acesso = await acessoAAula(admin, { slug, aulaId: id });
    if (!acesso.ok) return NextResponse.json({ error: acesso.motivo }, { status: acesso.status, ...semCache });
    const { aula, quem, lojaId } = acesso;
    const clienteId = quem.tipo === "aluno" ? quem.clienteId : null;

    const [comentarios, perfil, curtidas] = await Promise.all([
      admin
        .from("digital_course_comments")
        /* "clients!..._client_id_fkey": as curtidas também ligam comentário e
           cliente, e sem dizer qual ligação o banco recusa a leitura. */
        .select("id,client_id,autor_equipe,parent_id,texto,status,curtidas,criado_em,clients!digital_course_comments_client_id_fkey(name)")
        .eq("user_id", lojaId)
        .eq("lesson_id", aula.id)
        .is("apagado_em", null)
        .order("criado_em", { ascending: true })
        .limit(500),
      admin.from("profiles").select("catalog_name,store_name").eq("id", lojaId).maybeSingle(),
      clienteId ? admin.from("digital_course_comment_likes").select("comment_id").eq("client_id", clienteId).limit(2000) : Promise.resolve({ data: [] }),
    ]);
    if (comentarios.error) {
      console.error("[digitais] comentarios (ler)", comentarios.error.message);
      return NextResponse.json({ error: "Não foi possível carregar os comentários." }, { status: 500, ...semCache });
    }
    const nomeDaLoja = String((perfil.data as { catalog_name?: string | null; store_name?: string | null } | null)?.catalog_name || (perfil.data as { store_name?: string | null } | null)?.store_name || "Loja");
    const curti = new Set(((curtidas.data ?? []) as Array<{ comment_id: string }>).map((c) => c.comment_id));

    const visiveis = ((comentarios.data ?? []) as unknown as Linha[]).filter(
      (c) => c.status === "publicado" || (c.status === "pendente" && clienteId && c.client_id === clienteId)
    );
    const paraATela = (c: Linha): ComentarioNaTela => ({
      id: c.id,
      autor: c.autor_equipe ? nomeDaLoja : nomeEntreAlunos(c.clients?.name),
      daLoja: Boolean(c.autor_equipe),
      meu: Boolean(clienteId && c.client_id === clienteId),
      texto: c.texto,
      pendente: c.status === "pendente",
      curtidas: c.curtidas,
      curti: curti.has(c.id),
      criadoEm: c.criado_em,
      respostas: [],
    });
    const principais = visiveis.filter((c) => !c.parent_id).map(paraATela);
    const porId = new Map(principais.map((c) => [c.id, c]));
    for (const resposta of visiveis.filter((c) => c.parent_id)) {
      porId.get(String(resposta.parent_id))?.respostas.push(paraATela(resposta));
    }
    return NextResponse.json(
      {
        ok: true,
        ligados: aula.comentarios,
        podeComentar: aula.comentarios && quem.tipo === "aluno",
        comentarios: principais.reverse(),
      },
      semCache
    );
  } catch (erro) {
    console.error("[digitais] comentarios (ler)", erro);
    return NextResponse.json({ error: "Não foi possível carregar os comentários." }, { status: 500, ...semCache });
  }
}

export async function POST(request: Request, { params }: { params: Promise<{ id: string }> }) {
  const semCache = { headers: { "cache-control": "no-store" } };
  try {
    const { id } = await params;
    const corpo = (await request.json().catch(() => null)) as { slug?: unknown; texto?: unknown; respostaA?: unknown } | null;
    const slug = typeof corpo?.slug === "string" ? corpo.slug.trim().toLowerCase() : "";
    const texto = typeof corpo?.texto === "string" ? corpo.texto.replace(/\u0000/g, "").trim().slice(0, 2000) : "";
    if (!texto) return NextResponse.json({ error: "Escreva o comentário." }, { status: 400, ...semCache });

    const admin = createAdminClient();
    const acesso = await acessoAAula(admin, { slug, aulaId: id });
    if (!acesso.ok) return NextResponse.json({ error: acesso.motivo }, { status: acesso.status, ...semCache });
    const { aula, quem, lojaId } = acesso;
    if (quem.tipo !== "aluno") return NextResponse.json({ error: "Na prévia não dá para comentar." }, { status: 403, ...semCache });
    if (!aula.comentarios) return NextResponse.json({ error: "Os comentários deste vídeo estão desligados." }, { status: 403, ...semCache });

    /* Freio: poucos comentários em dez minutos. */
    const { count } = await admin
      .from("digital_course_comments")
      .select("id", { count: "exact", head: true })
      .eq("client_id", quem.clienteId)
      .gte("criado_em", new Date(Date.now() - 10 * 60 * 1000).toISOString());
    if ((count ?? 0) >= POR_DEZ_MINUTOS) return NextResponse.json({ error: "Muitos comentários seguidos. Espere alguns minutos." }, { status: 429, ...semCache });

    let paiId: string | null = null;
    if (typeof corpo?.respostaA === "string" && /^[0-9a-f-]{36}$/i.test(corpo.respostaA)) {
      const { data: pai } = await admin
        .from("digital_course_comments")
        .select("id,parent_id")
        .eq("id", corpo.respostaA)
        .eq("lesson_id", aula.id)
        .eq("user_id", lojaId)
        .is("apagado_em", null)
        .maybeSingle();
      const linhaDoPai = pai as { id: string; parent_id: string | null } | null;
      if (!linhaDoPai) return NextResponse.json({ error: "Comentário não encontrado." }, { status: 404, ...semCache });
      /* Uma conversa só tem um nível: resposta de resposta vai para o principal. */
      paiId = linhaDoPai.parent_id ?? linhaDoPai.id;
    }

    const { comentarios } = await lerAjustesDigitais(admin, lojaId);
    const { data, error } = await admin
      .from("digital_course_comments")
      .insert({
        user_id: lojaId,
        product_id: aula.product_id,
        lesson_id: aula.id,
        client_id: quem.clienteId,
        parent_id: paiId,
        texto,
        status: comentarios.quando === "aprovacao" ? "pendente" : "publicado",
      })
      .select("id,status")
      .single();
    if (error || !data) return NextResponse.json({ error: "Não foi possível publicar agora." }, { status: 500, ...semCache });
    const pendente = (data as { status: string }).status === "pendente";

    /* "Me avisar" (Configurações dos digitais): a equipe recebe no celular. O
       aviso sai depois da resposta: o aluno não espera por ele, e falhar aqui
       não desfaz o comentário. */
    if (comentarios.avisar) {
      const clienteId = quem.clienteId;
      after(async () => {
        try {
          const { data: cliente } = await admin.from("clients").select("name").eq("id", clienteId).maybeSingle();
          const nome = String((cliente as { name?: string | null } | null)?.name || "").trim().slice(0, 40) || "Um cliente";
          await avisarLojaPorPush(admin, {
            tenantId: lojaId,
            titulo: pendente ? `Comentário esperando aprovação · ${aula.titulo}`.slice(0, 90) : `Comentário novo · ${aula.titulo}`.slice(0, 90),
            corpo: `${nome}: ${texto.slice(0, 140)}`,
            rota: "/dashboard/digitais/comentarios",
            tag: `ktalogu-comentario-${aula.id}`,
          });
        } catch (erro) {
          console.error("[digitais] aviso do comentario", erro);
        }
      });
    }
    return NextResponse.json({ ok: true, id: (data as { id: string }).id, pendente }, semCache);
  } catch (erro) {
    console.error("[digitais] comentarios (publicar)", erro);
    return NextResponse.json({ error: "Não foi possível publicar agora." }, { status: 500, ...semCache });
  }
}
