import { NextResponse } from "next/server";
import { createClient } from "@/lib/supabase-server";
import { createAdminClient } from "@/lib/supabase-admin";
import { isOwnerUser } from "@/lib/owner-auth";
import { faxinarSlug } from "@/lib/faxina-html";
import { CAMPOS_DA_SECAO, DESENHOS, CORES_DA_SECAO, texto } from "@/lib/help";

/**
 * As seções do centro de aprendizado.
 *
 * Uma por módulo do sistema, com o mesmo nome do menu: quem travou numa tela
 * acha a seção dela pelo nome, sem traduzir nada.
 *
 * O slug é a primeira metade do endereço público, então ele só muda por pedido
 * explícito — e mudar quebra todo link já enviado.
 */

export const dynamic = "force-dynamic";

async function conferirDono() {
  const supabase = await createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();
  if (!user || !isOwnerUser({ id: user.id, email: user.email })) return null;
  return user;
}

function semPermissao() {
  return NextResponse.json({ error: "Sem permissão." }, { status: 403 });
}

function desenho(valor: unknown) {
  const bruto = texto(valor);
  return bruto in DESENHOS ? bruto : "livro";
}

function cor(valor: unknown) {
  const bruto = texto(valor).toLowerCase();
  return CORES_DA_SECAO.includes(bruto) ? bruto : CORES_DA_SECAO[0];
}

export async function GET() {
  if (!(await conferirDono())) return semPermissao();

  const admin = createAdminClient();
  const { data, error } = await admin
    .from("help_sections")
    .select(CAMPOS_DA_SECAO)
    .order("position", { ascending: true })
    .order("created_at", { ascending: true });

  if (error) return NextResponse.json({ error: "Não foi possível carregar as seções." }, { status: 400 });

  /* A contagem de artigos vem junto: a listagem mostra "22 artigos" ao lado de
     cada seção, e buscar isso na tela seria uma chamada por linha. */
  const { data: artigos } = await admin.from("help_articles").select("section_id,status");
  const contagem = new Map<string, { total: number; no_ar: number }>();
  for (const a of artigos ?? []) {
    const atual = contagem.get(a.section_id) ?? { total: 0, no_ar: 0 };
    atual.total += 1;
    if (a.status === "published") atual.no_ar += 1;
    contagem.set(a.section_id, atual);
  }

  const secoes = (data ?? []).map((s) => ({
    ...s,
    artigos: contagem.get(s.id)?.total ?? 0,
    artigos_no_ar: contagem.get(s.id)?.no_ar ?? 0,
  }));

  return NextResponse.json({ ok: true, sections: secoes });
}

export async function POST(request: Request) {
  if (!(await conferirDono())) return semPermissao();

  const body = (await request.json().catch(() => null)) as Record<string, unknown> | null;
  const title = texto(body?.title);
  if (!title) return NextResponse.json({ error: "A seção precisa de um nome." }, { status: 400 });

  const slug = faxinarSlug(texto(body?.slug) || title);
  if (!slug) return NextResponse.json({ error: "Endereço inválido." }, { status: 400 });

  const admin = createAdminClient();

  /* Nova seção nasce no fim da lista. Ordem é do dono, não do relógio. */
  const { data: ultima } = await admin
    .from("help_sections")
    .select("position")
    .order("position", { ascending: false })
    .limit(1)
    .maybeSingle();

  const { data, error } = await admin
    .from("help_sections")
    .insert({
      slug,
      title,
      description: texto(body?.description) || null,
      icon: desenho(body?.icon),
      color: cor(body?.color),
      position: (ultima?.position ?? 0) + 1,
    })
    .select(CAMPOS_DA_SECAO)
    .single();

  if (error) {
    const repetido = /duplicate key/i.test(error.message);
    return NextResponse.json(
      { error: repetido ? "Já existe uma seção com esse endereço." : "Não foi possível criar a seção." },
      { status: 400 }
    );
  }
  return NextResponse.json({ ok: true, section: data });
}

export async function PATCH(request: Request) {
  if (!(await conferirDono())) return semPermissao();

  const body = (await request.json().catch(() => null)) as Record<string, unknown> | null;

  /* Reordenar é um caso à parte: chega a lista inteira de uma vez, porque
     arrastar uma linha muda a posição de todas as outras. */
  if (Array.isArray(body?.order)) {
    const admin = createAdminClient();
    const ids = (body.order as unknown[]).map((v) => texto(v)).filter(Boolean);
    for (let i = 0; i < ids.length; i += 1) {
      await admin.from("help_sections").update({ position: i }).eq("id", ids[i]);
    }
    return NextResponse.json({ ok: true, reordenadas: ids.length });
  }

  const id = texto(body?.id);
  if (!id) return NextResponse.json({ error: "Sem seção." }, { status: 400 });

  const mudanca: Record<string, unknown> = {};
  if (body?.title !== undefined) {
    const title = texto(body.title);
    if (!title) return NextResponse.json({ error: "A seção precisa de um nome." }, { status: 400 });
    mudanca.title = title;
  }
  if (body?.slug !== undefined) {
    const slug = faxinarSlug(body.slug);
    if (!slug) return NextResponse.json({ error: "Endereço inválido." }, { status: 400 });
    mudanca.slug = slug;
  }
  if (body?.description !== undefined) mudanca.description = texto(body.description) || null;
  if (body?.icon !== undefined) mudanca.icon = desenho(body.icon);
  if (body?.color !== undefined) mudanca.color = cor(body.color);
  if (body?.active !== undefined) mudanca.active = Boolean(body.active);

  if (Object.keys(mudanca).length === 0) return NextResponse.json({ ok: true });

  const admin = createAdminClient();
  const { data, error } = await admin
    .from("help_sections")
    .update(mudanca)
    .eq("id", id)
    .select(CAMPOS_DA_SECAO)
    .single();

  if (error) {
    const repetido = /duplicate key/i.test(error.message);
    return NextResponse.json(
      { error: repetido ? "Já existe uma seção com esse endereço." : "Não foi possível salvar a seção." },
      { status: 400 }
    );
  }
  return NextResponse.json({ ok: true, section: data });
}

export async function DELETE(request: Request) {
  if (!(await conferirDono())) return semPermissao();

  const { searchParams } = new URL(request.url);
  const id = texto(searchParams.get("id"));
  if (!id) return NextResponse.json({ error: "Sem seção." }, { status: 400 });

  const admin = createAdminClient();

  /* Seção com artigo dentro não some: o banco recusaria de qualquer jeito
     (`on delete restrict`), e um aviso claro vale mais que um erro do Postgres
     traduzido pela metade. */
  const { count } = await admin
    .from("help_articles")
    .select("id", { count: "exact", head: true })
    .eq("section_id", id);

  if ((count ?? 0) > 0) {
    return NextResponse.json(
      { error: `Esta seção tem ${count} artigo(s). Mova ou apague os artigos antes.` },
      { status: 400 }
    );
  }

  const { error } = await admin.from("help_sections").delete().eq("id", id);
  if (error) return NextResponse.json({ error: "Não foi possível apagar a seção." }, { status: 400 });
  return NextResponse.json({ ok: true });
}
