import { NextResponse } from "next/server";
import { autenticar, carregarItens, carregarPedido, montarPainel } from "@/lib/orders/painel-de-producao.server";
import { planoValido } from "@/lib/orders/ficha-de-producao";

/**
 * O painel de produção de um pedido: previsto × real, etapa a etapa, item a
 * item.
 *
 *   GET  — o resumo: tempo por etapa, sessões do cronômetro (corrido e útil
 *          dentro do expediente), apontamentos por item com quem fez, perdas
 *          registradas e o previsto da ficha para comparar.
 *   POST — o apontamento por item: `iniciar_item`, `concluir_item`,
 *          `cancelar_item` (desfaz um início por engano); e `plano`, o plano
 *          de rodagem do item (quantas peças por folha desta vez, se a peça
 *          roda sozinha na bobina), gravado em `order_items.production_plan`
 *          — o gatilho do banco refaz a baixa de estoque com o plano novo.
 *          Devolve o painel atualizado, para a tela não precisar de uma
 *          segunda chamada.
 *
 * As perdas e o retrabalho têm rota própria em `../perdas`.
 */

export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
  try {
    const { id } = await params;
    const auth = await autenticar("orders.read");
    if (auth.erro) return auth.erro;

    const pedido = await carregarPedido(auth.contexto, id);
    if (pedido.erro) return pedido.erro;
    const itens = await carregarItens(auth.contexto, id);
    if (itens.erro) return itens.erro;

    const painel = await montarPainel(auth.contexto, pedido.order, itens.items);
    if (painel.erro) return painel.erro;
    return NextResponse.json(painel.painel);
  } catch (error) {
    const message = error instanceof Error ? error.message : "Erro ao carregar o painel de produção.";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}

export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
  try {
    const { id } = await params;
    const auth = await autenticar("orders.write");
    if (auth.erro) return auth.erro;
    const { contexto } = auth;

    const body = (await req.json().catch(() => null)) as { acao?: unknown; order_item_id?: unknown; insumos?: unknown } | null;
    const acao = typeof body?.acao === "string" ? body.acao : "";
    const orderItemId = typeof body?.order_item_id === "string" ? body.order_item_id : "";
    if (!["iniciar_item", "concluir_item", "cancelar_item", "plano"].includes(acao)) {
      return NextResponse.json({ error: "Ação inválida." }, { status: 400 });
    }
    if (!orderItemId) return NextResponse.json({ error: "Informe o item." }, { status: 400 });

    const pedido = await carregarPedido(contexto, id);
    if (pedido.erro) return pedido.erro;
    let itens = await carregarItens(contexto, id);
    if (itens.erro) return itens.erro;

    const item = itens.items.find((i) => i.id === orderItemId);
    if (!item) return NextResponse.json({ error: "Item não pertence a este pedido." }, { status: 404 });

    if (acao === "plano") {
      const plano = planoValido({ insumos: body?.insumos });
      const { error } = await contexto.admin
        .from("order_items")
        .update({ production_plan: Object.keys(plano).length > 0 ? plano : null })
        .eq("id", orderItemId)
        .eq("order_id", id);
      if (error) return NextResponse.json({ error: error.message }, { status: 400 });
      /* Relê os itens: a ficha do painel precisa do plano que acabou de entrar. */
      itens = await carregarItens(contexto, id);
      if (itens.erro) return itens.erro;
      const painel = await montarPainel(contexto, pedido.order, itens.items);
      if (painel.erro) return painel.erro;
      return NextResponse.json(painel.painel);
    }

    const { data: abertos, error: abertosError } = await contexto.admin
      .from("order_production_events")
      .select("id")
      .eq("order_id", id)
      .eq("kind", "item")
      .eq("order_item_id", orderItemId)
      .is("ended_at", null);
    if (abertosError) return NextResponse.json({ error: abertosError.message }, { status: 400 });
    const abertoIds = ((abertos || []) as { id: string }[]).map((a) => a.id);
    const nowIso = new Date().toISOString();

    if (acao === "iniciar_item") {
      if (abertoIds.length > 0) {
        return NextResponse.json({ error: "Este item já está em andamento." }, { status: 409 });
      }
      const { error } = await contexto.admin.from("order_production_events").insert({
        user_id: pedido.order.user_id,
        order_id: id,
        order_item_id: orderItemId,
        kind: "item",
        status: pedido.order.status,
        item_title: item.title,
        started_at: nowIso,
        started_by: contexto.userId,
      });
      if (error) return NextResponse.json({ error: error.message }, { status: 400 });
    } else if (acao === "concluir_item") {
      if (abertoIds.length === 0) {
        return NextResponse.json({ error: "Este item não está em andamento." }, { status: 409 });
      }
      const { error } = await contexto.admin
        .from("order_production_events")
        .update({ ended_at: nowIso, ended_by: contexto.userId })
        .in("id", abertoIds);
      if (error) return NextResponse.json({ error: error.message }, { status: 400 });
    } else {
      if (abertoIds.length === 0) {
        return NextResponse.json({ error: "Este item não está em andamento." }, { status: 409 });
      }
      const { error } = await contexto.admin.from("order_production_events").delete().in("id", abertoIds);
      if (error) return NextResponse.json({ error: error.message }, { status: 400 });
    }

    const painel = await montarPainel(contexto, pedido.order, itens.items);
    if (painel.erro) return painel.erro;
    return NextResponse.json(painel.painel);
  } catch (error) {
    const message = error instanceof Error ? error.message : "Erro ao registrar o apontamento.";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
