import { NextResponse } from "next/server";
import { acessoDoChat } from "@/lib/chats/acesso";
import { createAdminClient } from "@/lib/supabase-server";

/*
  O que a barra "/" oferece.

  Quem atende nao pode largar a conversa para ir procurar o preco de um produto
  em outra aba, nem decorar o codigo do cupom da semana. Aqui vem tudo o que o
  atalho precisa mostrar: os produtos da loja, os cupons que estao valendo e as
  respostas prontas que a propria loja escreveu.

  Nada disso e cadastro novo: produto e cupom ja existem no sistema, so estavam
  longe da conversa.
*/

function texto(valor: unknown) {
  return String(valor ?? "").trim();
}

/*
  O endereço público da loja.

  Link relativo funciona dentro da loja, mas o cartão também aparece no celular
  de quem recebeu o aviso e no portal do cliente — e ali "/metra" não leva a
  lugar nenhum. Por isso o endereço é montado inteiro, na seguinte ordem: o
  domínio próprio da loja, a base configurada, e por último o próprio endereço
  de quem pediu, sem o "admin." da frente — que é onde a loja mora.
*/
async function baseDaLoja(admin: ReturnType<typeof createAdminClient>, tenantId: string, request: Request) {
  const { data } = await admin
    .from("profile_custom_domains")
    .select("domain,verified")
    .eq("profile_id", tenantId)
    .eq("verified", true)
    .maybeSingle();

  const proprio = texto((data as { domain?: string } | null)?.domain).replace(/^https?:\/\//, "").replace(/\/$/, "");
  if (proprio) return `https://${proprio}`;

  const configurada = texto(process.env.NEXT_PUBLIC_PUBLIC_CATALOG_BASE_URL).replace(/\/$/, "");
  if (configurada) return configurada;

  try {
    const endereco = new URL(request.url);
    const casa = endereco.host.replace(/^admin\./, "");
    return `${endereco.protocol}//${casa}`;
  } catch {
    return "";
  }
}

function enderecoDaLoja(base: string, slug: string, caminho: string) {
  return `${base.replace(/\/$/, "")}/${slug}${caminho}`;
}

const RESPOSTAS_SUGERIDAS = [
  { atalho: "prazo", texto: "Nosso prazo de produção é de X dias úteis, e o envio sai logo depois da aprovação da arte." },
  { atalho: "arte", texto: "Pode mandar a arte por aqui mesmo! Aceito PDF, PNG ou JPG em boa resolução." },
  { atalho: "pagamento", texto: "Aceitamos Pix e cartão. No Pix a confirmação é na hora e já entra na fila de produção." },
  { atalho: "obrigado", texto: "Obrigado pelo contato! Qualquer dúvida, é só chamar por aqui." },
];

export async function GET(request: Request) {
  const acesso = await acessoDoChat();
  if ("erro" in acesso) return acesso.erro;

  const endereco = new URL(request.url);
  const tipo = texto(endereco.searchParams.get("tipo"));
  const busca = texto(endereco.searchParams.get("busca"));

  const admin = createAdminClient();

  if (tipo === "produto") {
    const { data: perfil } = await admin
      .from("profiles")
      .select("slug,catalog_price_mode")
      .eq("id", acesso.tenantIds[0])
      .maybeSingle();
    const slug = texto((perfil as { slug?: string } | null)?.slug);
    /* Loja com preço escondido (Regras da loja): o cartão sai sem preço, como
       o produto sob consulta, para quem atende não mostrar na conversa o que
       a loja escolheu não mostrar. */
    const precoVisivel = (texto((perfil as { catalog_price_mode?: string | null } | null)?.catalog_price_mode) || "public") === "public";
    const base = await baseDaLoja(admin, acesso.tenantIds[0], request);

    let consulta = admin
      .from("products")
      .select("id,name,price,image_url,price_on_request")
      .in("user_id", acesso.tenantIds)
      .eq("active", true)
      .order("name")
      .limit(20);

    if (busca) consulta = consulta.ilike("name", `%${busca}%`);

    const { data, error } = await consulta;
    if (error) return NextResponse.json({ error: error.message }, { status: 400 });

    const itens = ((data || []) as {
      id: string;
      name: string;
      price: number | null;
      image_url: string | null;
      price_on_request: boolean | null;
    }[]).map((produto) => ({
      id: produto.id,
      nome: produto.name,
      preco: produto.price_on_request || !precoVisivel ? null : Number(produto.price || 0),
      imagem: produto.image_url,
      link: slug && base ? enderecoDaLoja(base, slug, `/p/${produto.id}`) : null,
    }));

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

  if (tipo === "loja") {
    const { data } = await admin.from("profiles").select("slug").eq("id", acesso.tenantIds[0]).maybeSingle();
    const slug = texto((data as { slug?: string } | null)?.slug);
    const base = await baseDaLoja(admin, acesso.tenantIds[0], request);
    return NextResponse.json({ ok: true, link: slug && base ? enderecoDaLoja(base, slug, "") : null });
  }

  if (tipo === "cupom") {
    const agora = new Date().toISOString();
    const { data, error } = await admin
      .from("catalog_coupons")
      .select("id,code,type,value,min_total,min_items,active,starts_at,ends_at")
      .in("user_id", acesso.tenantIds)
      .eq("active", true)
      /* O automático entra sozinho no carrinho: não há código para mandar. */
      .neq("application", "automatic")
      .order("created_at", { ascending: false })
      .limit(30);

    if (error) return NextResponse.json({ error: error.message }, { status: 400 });

    /* Cupom vencido na lista e cilada: a pessoa oferece, o cliente tenta usar e
       nao vale. Some daqui. */
    const itens = ((data || []) as {
      id: string;
      code: string;
      type: string;
      value: number;
      min_total: number | null;
      min_items: number | null;
      starts_at: string | null;
      ends_at: string | null;
    }[])
      .filter((cupom) => !cupom.ends_at || cupom.ends_at >= agora)
      .filter((cupom) => !cupom.starts_at || cupom.starts_at <= agora)
      .filter((cupom) => !busca || cupom.code.toLowerCase().includes(busca.toLowerCase()))
      .map((cupom) => ({
        id: cupom.id,
        codigo: cupom.code,
        tipo: cupom.type,
        valor: Number(cupom.value || 0),
        minimo: cupom.min_total ? Number(cupom.min_total) : null,
        minimoItens: cupom.min_items ? Number(cupom.min_items) : null,
        vence: cupom.ends_at,
      }));

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

  if (tipo === "resposta") {
    const { data } = await admin
      .from("profiles")
      .select("chat_quick_replies")
      .eq("id", acesso.tenantIds[0])
      .maybeSingle();

    const guardadas = (data as { chat_quick_replies?: unknown } | null)?.chat_quick_replies;
    const itens = Array.isArray(guardadas) ? (guardadas as { atalho: string; texto: string }[]) : RESPOSTAS_SUGERIDAS;

    return NextResponse.json({
      ok: true,
      itens: itens.filter(
        (resposta) =>
          !busca ||
          String(resposta.atalho || "").toLowerCase().includes(busca.toLowerCase()) ||
          String(resposta.texto || "").toLowerCase().includes(busca.toLowerCase())
      ),
      /* A loja ainda nao escreveu as suas: o que aparece e sugestao, e a tela
         precisa saber disso para convidar a editar. */
      sugeridas: !Array.isArray(guardadas),
    });
  }

  return NextResponse.json({ error: "Atalho desconhecido." }, { status: 400 });
}

/* As respostas prontas sao editadas de dentro do proprio Chats: sair para uma
   tela de configuracao no meio de um atendimento e perder o cliente. */
export async function PUT(request: Request) {
  const acesso = await acessoDoChat();
  if ("erro" in acesso) return acesso.erro;
  if (!acesso.podeResponderLoja) return NextResponse.json({ error: "Sem permissao." }, { status: 403 });

  const corpo = (await request.json().catch(() => null)) as { respostas?: unknown } | null;
  const lista = Array.isArray(corpo?.respostas) ? corpo.respostas : [];

  const limpas = (lista as { atalho?: unknown; texto?: unknown }[])
    .map((resposta) => ({
      atalho: texto(resposta.atalho).slice(0, 24).toLowerCase().replace(/\s+/g, "-"),
      texto: texto(resposta.texto).slice(0, 900),
    }))
    .filter((resposta) => resposta.atalho && resposta.texto)
    .slice(0, 40);

  const admin = createAdminClient();
  const { error } = await admin
    .from("profiles")
    .update({ chat_quick_replies: limpas })
    .eq("id", acesso.tenantIds[0]);

  if (error) return NextResponse.json({ error: error.message }, { status: 400 });

  return NextResponse.json({ ok: true, itens: limpas });
}
