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

/**
 * Os boletins: as páginas de aviso publicadas em info.ktalogu.com.br.
 *
 * Tudo passa pela chave de serviço depois de conferir que é o dono. O corpo do
 * texto passa pela faxina antes de encostar no banco: é a única porta por onde
 * HTML entra num endereço que abre sem login.
 */

const CAMPOS =
  "id,slug,title,subtitle,tag,cover_image_url,body_html,status,published_at,created_at,updated_at";

function texto(valor: unknown) {
  return typeof valor === "string" ? valor.trim() : "";
}

function endereco(valor: unknown) {
  const bruto = texto(valor);
  if (!bruto) return null;
  try {
    const url = new URL(bruto);
    return url.protocol === "http:" || url.protocol === "https:" ? bruto : null;
  } catch {
    return null;
  }
}

function situacao(valor: unknown) {
  return texto(valor).toLowerCase() === "published" ? "published" : "draft";
}

async function conferirDono() {
  const supabase = await createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();
  if (!user || !isOwnerUser({ id: user.id, email: user.email })) {
    return { ok: false as const, status: 403 };
  }
  return { ok: true as const, status: 200 };
}

export async function GET(request: Request) {
  const auth = await conferirDono();
  if (!auth.ok) return NextResponse.json({ error: "Sem permissão." }, { status: auth.status });

  const { searchParams } = new URL(request.url);
  const id = texto(searchParams.get("id"));

  const admin = createAdminClient();
  if (id) {
    const { data, error } = await admin.from("system_bulletins").select(CAMPOS).eq("id", id).maybeSingle();
    if (error) return NextResponse.json({ error: "Não foi possível carregar o boletim." }, { status: 400 });
    if (!data) return NextResponse.json({ error: "Boletim não encontrado." }, { status: 404 });
    return NextResponse.json({ ok: true, bulletin: data });
  }

  const { data, error } = await admin
    .from("system_bulletins")
    .select(CAMPOS)
    .order("updated_at", { ascending: false })
    .limit(300);
  if (error) return NextResponse.json({ error: "Não foi possível carregar os boletins." }, { status: 400 });
  return NextResponse.json({ ok: true, bulletins: data ?? [] });
}

/**
 * Um endereço livre.
 *
 * Dois boletins com o mesmo endereço seriam a mesma página, e o banco recusa.
 * Em vez de devolver erro para quem só quis reaproveitar um título, a rota
 * acrescenta um número no fim até achar um livre.
 */
async function enderecoLivre(
  admin: ReturnType<typeof createAdminClient>,
  desejado: string,
  ignorarId: string | null
) {
  const base = desejado || "boletim";
  for (let tentativa = 0; tentativa < 40; tentativa += 1) {
    const candidato = tentativa === 0 ? base : `${base}-${tentativa + 1}`;
    const consulta = admin.from("system_bulletins").select("id").eq("slug", candidato);
    const { data } = ignorarId ? await consulta.neq("id", ignorarId) : await consulta;
    if (!data || data.length === 0) return candidato;
  }
  return `${base}-${Date.now()}`;
}

export async function POST(request: Request) {
  const auth = await conferirDono();
  if (!auth.ok) return NextResponse.json({ error: "Sem permissão." }, { status: auth.status });

  const body = (await request.json().catch(() => null)) as Record<string, unknown> | null;
  const title = texto(body?.title);
  if (!title) return NextResponse.json({ error: "Informe o título do boletim." }, { status: 400 });

  const admin = createAdminClient();
  const slug = await enderecoLivre(admin, faxinarSlug(body?.slug || title), null);
  const status = situacao(body?.status);

  const { data, error } = await admin
    .from("system_bulletins")
    .insert({
      slug,
      title,
      subtitle: texto(body?.subtitle) || null,
      tag: texto(body?.tag) || null,
      cover_image_url: endereco(body?.cover_image_url),
      body_html: faxinarHtmlDoBoletim(body?.body_html),
      status,
      published_at: status === "published" ? new Date().toISOString() : null,
    })
    .select("id,slug")
    .single();

  if (error || !data?.id) {
    return NextResponse.json({ error: "Não foi possível salvar o boletim." }, { status: 400 });
  }
  return NextResponse.json({ ok: true, id: data.id, slug: data.slug });
}

export async function PATCH(request: Request) {
  const auth = await conferirDono();
  if (!auth.ok) return NextResponse.json({ error: "Sem permissão." }, { status: auth.status });

  const body = (await request.json().catch(() => null)) as Record<string, unknown> | null;
  const id = texto(body?.id);
  if (!id) return NextResponse.json({ error: "Boletim inválido." }, { status: 400 });

  const admin = createAdminClient();
  const { data: atual } = await admin.from("system_bulletins").select("status,published_at").eq("id", id).maybeSingle();
  if (!atual) return NextResponse.json({ error: "Boletim não encontrado." }, { status: 404 });

  const payload: Record<string, unknown> = {};

  if (body?.title !== undefined) {
    const title = texto(body.title);
    if (!title) return NextResponse.json({ error: "Informe o título do boletim." }, { status: 400 });
    payload.title = title;
  }
  if (body?.subtitle !== undefined) payload.subtitle = texto(body.subtitle) || null;
  if (body?.tag !== undefined) payload.tag = texto(body.tag) || null;
  if (body?.cover_image_url !== undefined) payload.cover_image_url = endereco(body.cover_image_url);
  if (body?.body_html !== undefined) payload.body_html = faxinarHtmlDoBoletim(body.body_html);

  if (body?.slug !== undefined) {
    const desejado = faxinarSlug(body.slug);
    if (!desejado) return NextResponse.json({ error: "Endereço inválido." }, { status: 400 });
    payload.slug = await enderecoLivre(admin, desejado, id);
  }

  if (body?.status !== undefined) {
    const status = situacao(body.status);
    payload.status = status;
    /* A data de publicação é carimbada na primeira vez que sai do rascunho, e
       não é reescrita a cada correção de texto depois. */
    if (status === "published" && !atual.published_at) payload.published_at = new Date().toISOString();
  }

  const { error } = await admin.from("system_bulletins").update(payload).eq("id", id);
  if (error) return NextResponse.json({ error: "Não foi possível atualizar o boletim." }, { status: 400 });

  const { data } = await admin.from("system_bulletins").select("slug,status").eq("id", id).maybeSingle();
  return NextResponse.json({ ok: true, slug: data?.slug ?? null, status: data?.status ?? null });
}

export async function DELETE(request: Request) {
  const auth = await conferirDono();
  if (!auth.ok) return NextResponse.json({ error: "Sem permissão." }, { status: auth.status });

  const { searchParams } = new URL(request.url);
  const id = texto(searchParams.get("id"));
  if (!id) return NextResponse.json({ error: "Boletim inválido." }, { status: 400 });

  const admin = createAdminClient();
  const { error } = await admin.from("system_bulletins").delete().eq("id", id);
  if (error) return NextResponse.json({ error: "Não foi possível excluir o boletim." }, { status: 400 });
  return NextResponse.json({ ok: true });
}
