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

/**
 * Quem viu o aviso, e o que fez com ele.
 *
 * A lista parte das EMPRESAS que o popup alcança, e não de quem já apareceu no
 * registro. Sem isso não daria para responder a pergunta que importa, que é
 * quem ainda não viu: quem não viu não tem linha nenhuma em lugar nenhum.
 */

export const dynamic = "force-dynamic";

type Situacao = "ciente" | "viu" | "nao_viu";

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 popupId = String(searchParams.get("popup_id") || "").trim();
  if (!popupId) return NextResponse.json({ error: "Popup inválido." }, { status: 400 });

  const admin = createAdminClient();

  const { data: popup } = await admin
    .from("system_popups")
    .select("id,title,audience,require_ack,ack_label,created_at,updated_at")
    .eq("id", popupId)
    .maybeSingle();
  if (!popup) return NextResponse.json({ error: "Popup não encontrado." }, { status: 404 });

  /* O universo: todas as empresas, ou só as escolhidas no cadastro. */
  let empresas: Array<{ id: string; name: string }> = [];
  if (popup.audience === "selected") {
    const { data: vinculos } = await admin
      .from("system_popup_companies")
      .select("company_id")
      .eq("popup_id", popupId);
    const ids = (vinculos ?? []).map((linha) => String(linha.company_id));
    if (ids.length > 0) {
      const { data } = await admin.from("companies").select("id,name").in("id", ids);
      empresas = (data ?? []).map((linha) => ({ id: String(linha.id), name: String(linha.name || "Sem nome") }));
    }
  } else {
    const { data } = await admin.from("companies").select("id,name").order("name", { ascending: true }).limit(3000);
    empresas = (data ?? []).map((linha) => ({ id: String(linha.id), name: String(linha.name || "Sem nome") }));
  }

  const { data: registros } = await admin
    .from("system_popup_views")
    .select("user_id,company_id,opened_at,seen_at,acknowledged_at,ack_label")
    .eq("popup_id", popupId);

  /* Uma empresa pode ter várias pessoas. Vale a melhor situação de todas: se
     alguém deu ciência, a empresa está ciente. */
  const peso: Record<Situacao, number> = { nao_viu: 0, viu: 1, ciente: 2 };
  const porEmpresa = new Map<
    string,
    { situacao: Situacao; quando: string | null; user_id: string | null; ack_label: string | null }
  >();
  const semEmpresa: Array<{ user_id: string; situacao: Situacao; quando: string | null }> = [];

  for (const registro of registros ?? []) {
    const situacao: Situacao = registro.acknowledged_at ? "ciente" : "viu";
    const quando = (registro.acknowledged_at || registro.seen_at || registro.opened_at) as string | null;
    const empresa = registro.company_id ? String(registro.company_id) : "";

    if (!empresa) {
      semEmpresa.push({ user_id: String(registro.user_id), situacao, quando });
      continue;
    }
    const atual = porEmpresa.get(empresa);
    if (!atual || peso[situacao] > peso[atual.situacao]) {
      porEmpresa.set(empresa, {
        situacao,
        quando,
        user_id: String(registro.user_id),
        ack_label: (registro.ack_label as string | null) ?? null,
      });
    }
  }

  /* Quem foi, pelo e-mail do vínculo com a empresa. O nome não é guardado no
     registro de propósito: seria congelar um dado que muda, e o que identifica
     a pessoa numa prova é o e-mail com que ela entrou. */
  const donos = [...porEmpresa.values()].map((linha) => linha.user_id).filter(Boolean) as string[];
  const nomes = new Map<string, string>();
  if (donos.length > 0) {
    const { data: vinculos } = await admin.from("company_users").select("user_id,email").in("user_id", donos);
    for (const vinculo of vinculos ?? []) {
      const email = String(vinculo.email || "");
      if (email) nomes.set(String(vinculo.user_id), email);
    }
  }

  const linhas = empresas
    .map((empresa) => {
      const registro = porEmpresa.get(empresa.id);
      return {
        company_id: empresa.id,
        company_name: empresa.name,
        situacao: (registro?.situacao ?? "nao_viu") as Situacao,
        quando: registro?.quando ?? null,
        quem: registro?.user_id ? nomes.get(registro.user_id) || "" : "",
        ack_label: registro?.ack_label ?? null,
      };
    })
    .sort((a, b) => peso[b.situacao] - peso[a.situacao] || a.company_name.localeCompare(b.company_name, "pt-BR"));

  const conta = (situacao: Situacao) => linhas.filter((linha) => linha.situacao === situacao).length;

  return NextResponse.json({
    ok: true,
    popup: {
      id: popup.id,
      title: popup.title,
      require_ack: popup.require_ack === true,
      ack_label: popup.ack_label,
      audience: popup.audience,
    },
    resumo: {
      alcancadas: linhas.length,
      cientes: conta("ciente"),
      viram: conta("viu"),
      nao_viram: conta("nao_viu"),
      /* Gente que abriu o sistema sem empresa no contexto. Raro, mas se
         aparecer é sinal de cadastro pela metade, e some do total das linhas. */
      fora_de_empresa: semEmpresa.length,
    },
    linhas,
  });
}
