"use client";

import { useCallback, useEffect, useState } from "react";
import { Building2, Clock3, Plus, Trash2, TriangleAlert, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { InfoTooltip } from "@/components/ui/info-tooltip";
import { formatMoneyInput, parseMoneyInput } from "@/utils/formatters";

/**
 * A aba de custos fixos, morando onde o dinheiro sai.
 *
 * Custo fixo é o que se paga mesmo vendendo zero. A fonte primária é o próprio
 * Contas a Pagar: a média dos últimos meses das categorias classificadas como
 * fixas — aberta por categoria, porque um agregado sozinho é um número que
 * ninguém confere. O complemento é o que se paga por fora do sistema
 * (pró-labore, aluguel no nome do sócio), declarado à mão.
 *
 * A entrada dos fixos nos preços é pela HORA DA ESTRUTURA: fixo de estrutura
 * mensal ÷ horas produtivas da empresa. Cada precificação carrega os fixos
 * proporcionais ao tempo da própria ficha — quem ocupa 3 horas de produção
 * paga mais aluguel que quem ocupa 2 minutos. Sem as horas informadas, os
 * fixos ficam fora do preço, cobertos pelo volume, com o Ponto de Equilíbrio
 * de guarda — que não muda em nenhum dos casos.
 *
 * (O rateio antigo, percentual da venda, foi aposentado: cobrava a mesma
 * fatia de qualquer peça e dependia de um chute de faturamento.)
 */

type Consolidado = {
  media_lancada: number;
  declarado_a_mao: number;
  total_mensal: number;
  producao_mensal: number;
  sem_classificacao: number;
  meses_considerados: number;
  meses_com_lancamento: number;
};

type Categoria = { id: string; name: string; cost_behavior: string | null };
type Declarado = { id: string; name: string; monthly_amount: number; active: boolean };
type MediaCategoria = { nome: string; media: number; producao?: boolean };
type HoraDaEstrutura = {
  configurada: boolean;
  horasMes: number;
  estruturaMensal: number;
  producaoMensal: number;
  taxa: number;
};

const dinheiro = (v: number) =>
  new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(v || 0);

const OPCOES = [
  { valor: "fixo", rotulo: "Fixo", dica: "Paga mesmo vendendo zero" },
  { valor: "fixo_producao", rotulo: "Fixo de produção", dica: "Salário de produção, energia e manutenção de máquina: já entra no preço pela hora de máquina/trabalho. Conta no equilíbrio; fica fora da hora da estrutura para não cobrar duas vezes." },
  { valor: "variavel", rotulo: "Variável", dica: "Só existe quando vende" },
  { valor: "nao_operacional", rotulo: "Não oper.", dica: "Retirada, investimento, empréstimo" },
];

function Numero({ rotulo, valor, destaque }: { rotulo: string; valor: number; destaque?: boolean }) {
  return (
    <div>
      <div className="text-xs text-[var(--ks-color-text-soft)]">{rotulo}</div>
      <div className={destaque
        ? "text-3xl font-black text-[var(--ks-color-text-primary)]"
        : "text-lg font-bold text-[var(--ks-color-text-primary)]"}>
        {dinheiro(valor)}
      </div>
    </div>
  );
}

export function CustosFixosTab({ podeEditar }: { podeEditar: boolean }) {
  const [consolidado, setConsolidado] = useState<Consolidado | null>(null);
  const [categorias, setCategorias] = useState<Categoria[]>([]);
  const [declarados, setDeclarados] = useState<Declarado[]>([]);
  const [mediaPorCategoria, setMediaPorCategoria] = useState<MediaCategoria[]>([]);
  const [horaDaEstrutura, setHoraDaEstrutura] = useState<HoraDaEstrutura | null>(null);
  const [horasInformadas, setHorasInformadas] = useState("");
  const [carregando, setCarregando] = useState(true);
  const [salvandoNovo, setSalvandoNovo] = useState(false);
  const [novo, setNovo] = useState({ name: "", monthly_amount: "" });
  const [erro, setErro] = useState("");

  const carregar = useCallback(async () => {
    const r = await fetch("/api/fixed-costs", { cache: "no-store" });
    const j = await r.json();
    if (r.ok) {
      setConsolidado(j.consolidado);
      setCategorias(j.categorias ?? []);
      setDeclarados(j.declarados ?? []);
      setMediaPorCategoria(j.mediaPorCategoria ?? []);
      setHoraDaEstrutura(j.horaDaEstrutura ?? null);
      setHorasInformadas(
        j.horaDaEstrutura?.horasMes > 0 ? String(j.horaDaEstrutura.horasMes).replace(".", ",") : ""
      );
    } else {
      setErro(j.error || "Falha ao carregar.");
    }
    setCarregando(false);
  }, []);

  useEffect(() => {
    void carregar();
  }, [carregar]);

  const classificar = async (id: string, comportamento: string) => {
    setCategorias((atual) =>
      atual.map((c) => (c.id === id ? { ...c, cost_behavior: comportamento } : c))
    );
    await fetch("/api/fixed-costs", {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ category_id: id, cost_behavior: comportamento }),
    });
    await carregar();
  };

  const salvarHoras = async () => {
    const valor = Number(horasInformadas.replace(",", ".")) || 0;
    /* Salvar o mesmo valor de novo so gastaria uma viagem. */
    if (valor === (horaDaEstrutura?.horasMes ?? 0)) return;
    await fetch("/api/fixed-costs", {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ productive_hours_month: valor > 0 ? valor : null }),
    });
    await carregar();
  };

  const adicionar = async () => {
    setErro("");
    setSalvandoNovo(true);
    try {
      const r = await fetch("/api/fixed-costs", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          name: novo.name,
          monthly_amount: parseMoneyInput(novo.monthly_amount),
        }),
      });
      const j = await r.json();
      if (!r.ok) {
        setErro(j.error || "Falha ao salvar.");
        return;
      }
      setNovo({ name: "", monthly_amount: "" });
      await carregar();
    } finally {
      setSalvandoNovo(false);
    }
  };

  const remover = async (id: string) => {
    await fetch(`/api/fixed-costs?id=${id}`, { method: "DELETE" });
    await carregar();
  };

  const semClassificar = categorias.filter((c) => !c.cost_behavior);
  const listaCategorias = [...semClassificar, ...categorias.filter((c) => c.cost_behavior)];

  if (carregando) {
    return (
      <div className="flex justify-center py-16">
        <Loader2 className="h-8 w-8 animate-spin text-[var(--ks-color-primary)]" />
      </div>
    );
  }

  return (
    <div className="space-y-4">
      {erro && (
        <div className="rounded-xl bg-[var(--ks-color-status-danger-soft)] px-4 py-3 text-sm text-[var(--ks-color-status-danger)]">
          {erro}
        </div>
      )}

      {/* O resumo e o rateio no mesmo cartao: o numero, e a decisao sobre ele. */}
      <section className="ks-surface rounded-2xl p-5 border border-[var(--ks-color-border-subtle)]">
        <div className="flex items-start gap-4 flex-wrap">
          <span className="ks-tile" style={{ background: "var(--ks-brand-600)" }}>
            <Building2 size={21} />
          </span>
          <div className="flex-1 min-w-0">
            <h2 className="ks-section-title inline-flex items-center">
              Custo fixo mensal
              <InfoTooltip text={`Média dos últimos ${consolidado?.meses_considerados ?? 3} meses fechados das contas em categorias FIXAS, mais o que você declarou pago por fora. É o que o faturamento precisa cobrir — e é com este valor que o Ponto de Equilíbrio é calculado.`} />
            </h2>
            <div className="mt-3 flex flex-wrap items-end gap-x-8 gap-y-3">
              <Numero rotulo="Total por mês" valor={consolidado?.total_mensal ?? 0} destaque />
              <Numero rotulo="Média do lançado aqui" valor={consolidado?.media_lancada ?? 0} />
              <Numero rotulo="Pago por fora" valor={consolidado?.declarado_a_mao ?? 0} />
            </div>

            {mediaPorCategoria.length > 0 && (
              <div className="mt-3 flex flex-wrap gap-1.5">
                {mediaPorCategoria.map((m) => (
                  <span
                    key={m.nome}
                    className="text-[11px] px-2.5 py-1 rounded-full bg-[var(--ks-color-bg-inset)] text-[var(--ks-color-text-muted)]"
                    title={m.producao ? "Fixo de produção: já entra no preço pela hora de máquina/trabalho" : undefined}
                  >
                    {m.nome} · <strong className="text-[var(--ks-color-text-primary)]">{dinheiro(m.media)}</strong>
                    {m.producao && <span className="ml-1 text-[var(--ks-color-text-soft)]">· produção</span>}
                  </span>
                ))}
              </div>
            )}

            {(consolidado?.sem_classificacao ?? 0) > 0.01 && (
              <div className="mt-3 flex items-start gap-2 rounded-xl bg-[var(--ks-color-status-warning-soft)] px-4 py-3">
                <TriangleAlert size={15} className="text-[var(--ks-color-status-warning)] mt-0.5 shrink-0" />
                <p className="text-xs text-[var(--ks-color-text-secondary)]">
                  <strong>{dinheiro(consolidado?.sem_classificacao ?? 0)}/mês</strong> em categorias
                  sem classificação ficam fora do total — e o ponto de equilíbrio sai otimista.
                  Classifique abaixo.
                </p>
              </div>
            )}
          </div>
        </div>

        {/* A hora da estrutura: um numero que a pessoa sabe (horas), e a taxa
            que sai dele. Sem switch: horas em branco = fixos fora do preco. */}
        <div className="mt-5 pt-5 border-t border-[var(--ks-color-border-subtle)]">
          <div className="flex items-center justify-between gap-3 flex-wrap">
            <div className="flex items-center gap-3">
              <span className="ks-tile ks-tile-sm shrink-0" style={{ background: "var(--ks-color-primary)" }}>
                <Clock3 size={18} />
              </span>
              <div>
                <h3 className="ks-section-title inline-flex items-center">
                  Custos fixos no preço, pela hora produtiva
                  <InfoTooltip text="Custo fixo de estrutura ÷ horas produtivas do mês = o que cada hora de produção precisa cobrir de aluguel, pró-labore e afins. A precificação multiplica essa taxa pelo tempo da ficha: quem ocupa 3 horas carrega mais fixo que quem ocupa 2 minutos. Sem as horas, os fixos ficam fora do preço — cobertos pelo volume, com o Ponto de Equilíbrio de guarda." />
                </h3>
                <p className="ks-section-hint mt-0.5">
                  {horaDaEstrutura?.configurada
                    ? `Cada hora de produção precificada carrega ${dinheiro(horaDaEstrutura.taxa)} de custos fixos.`
                    : "Informe as horas para os fixos entrarem nos preços pelo tempo de produção."}
                </p>
              </div>
            </div>
            <div className="text-right">
              <div className="text-[10px] uppercase tracking-wide text-[var(--ks-color-text-soft)]">
                Hora da estrutura
              </div>
              <div
                className="text-xl font-black leading-tight"
                style={{
                  color: horaDaEstrutura?.configurada
                    ? "var(--ks-color-primary)"
                    : "var(--ks-color-text-soft)",
                }}
              >
                {horaDaEstrutura?.configurada ? `${dinheiro(horaDaEstrutura.taxa)}/h` : "—"}
              </div>
            </div>
          </div>

          <div className="mt-3 max-w-md space-y-1">
            <label className="text-xs font-medium text-[var(--ks-color-text-soft)] inline-flex items-center">
              Horas produtivas por mês
              <InfoTooltip text="Quantas horas de produção a empresa entrega num mês, somando gente e máquina que trabalham em paralelo. Ex.: 2 pessoas × 8h × 22 dias ≈ 350h. Você sabe esse número muito melhor do que o faturamento futuro — e o erro fica proporcional ao tempo de cada peça, não espalhado em todos os preços." />
            </label>
            <Input
              inputMode="decimal"
              value={horasInformadas}
              placeholder="Ex: 176"
              disabled={!podeEditar}
              onChange={(e) => setHorasInformadas(e.target.value)}
              onBlur={() => void salvarHoras()}
            />
          </div>

          {(horaDaEstrutura?.producaoMensal ?? 0) > 0 && (
            <p className="mt-2 text-xs text-[var(--ks-color-text-muted)]">
              {dinheiro(horaDaEstrutura?.producaoMensal ?? 0)}/mês em categorias{" "}
              <strong>fixo de produção</strong> já entram no preço pela hora de máquina e de
              trabalho — contam no equilíbrio e ficam fora desta taxa.
            </p>
          )}
        </div>
      </section>

      <div className="grid grid-cols-1 xl:grid-cols-2 gap-4 items-start">
        {/* Classificacao: uma linha por categoria, sem cartoes empilhados. */}
        <section className="ks-surface rounded-2xl border border-[var(--ks-color-border-subtle)] overflow-hidden">
          <div className="p-5 pb-3">
            <h3 className="ks-section-title inline-flex items-center">
              Classificação das categorias
              <InfoTooltip text="É a classificação que decide o que entra na média: conta lançada em categoria FIXA soma no custo fixo; em VARIÁVEL, não. FIXO DE PRODUÇÃO soma no custo fixo do equilíbrio, mas fica fora da hora da estrutura — esse dinheiro já entra no preço pela hora de máquina/trabalho. Não operacional (retirada, empréstimo) fica fora de tudo." />
            </h3>
            <p className="ks-section-hint mt-0.5">
              {semClassificar.length > 0
                ? `${semClassificar.length} sem classificar — ${semClassificar.length === 1 ? "está" : "estão"} no topo.`
                : "Tudo classificado."}
            </p>
          </div>
          <div className="max-h-[440px] overflow-y-auto divide-y divide-[var(--ks-color-border-subtle)]">
            {listaCategorias.map((c) => (
              <div
                key={c.id}
                className={`flex items-center justify-between gap-3 px-5 py-2.5 ${
                  c.cost_behavior ? "" : "bg-[var(--ks-color-status-warning-soft)]"
                }`}
              >
                <span className="text-sm font-medium text-[var(--ks-color-text-primary)] truncate">
                  {c.name}
                </span>
                <div className="flex gap-1 shrink-0">
                  {OPCOES.map((o) => (
                    <button
                      key={o.valor}
                      type="button"
                      disabled={!podeEditar}
                      title={o.dica}
                      onClick={() => void classificar(c.id, o.valor)}
                      className="px-2 py-1 rounded-full text-[11px] font-semibold transition disabled:opacity-50"
                      style={
                        c.cost_behavior === o.valor
                          ? { background: "var(--ks-color-primary)", color: "#fff" }
                          : { background: "var(--ks-color-bg-inset)", color: "var(--ks-color-text-muted)" }
                      }
                    >
                      {o.rotulo}
                    </button>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </section>

        {/* Pago por fora: lista + formulario, no padrao das telas financeiras. */}
        <section className="ks-surface rounded-2xl border border-[var(--ks-color-border-subtle)] overflow-hidden">
          <div className="p-5 pb-3">
            <h3 className="ks-section-title inline-flex items-center">
              Pago por fora do sistema
              <InfoTooltip text="Pró-labore, aluguel no nome do sócio, contador em dinheiro: custos fixos reais que nunca viram lançamento aqui. Entram no ponto de equilíbrio e na hora da estrutura — nunca no custo direto dos produtos. Não declare aqui o que você também lança no Contas a Pagar: contaria duas vezes." />
            </h3>
            <p className="ks-section-hint mt-0.5">Uma linha por despesa, com o valor mensal.</p>
          </div>

          <div className="divide-y divide-[var(--ks-color-border-subtle)]">
            {declarados.length === 0 && (
              <p className="px-5 py-6 text-sm text-[var(--ks-color-text-muted)] text-center">
                Nada declarado — se você lança tudo no Contas a Pagar, é assim mesmo que fica.
              </p>
            )}
            {declarados.map((d) => (
              <div key={d.id} className="flex items-center gap-3 px-5 py-2.5">
                <span className="flex-1 text-sm font-medium text-[var(--ks-color-text-primary)] truncate">
                  {d.name}
                </span>
                <span className="text-sm font-bold">{dinheiro(Number(d.monthly_amount))}</span>
                {podeEditar && (
                  <Button size="icon" variant="ghost" title="Remover" onClick={() => void remover(d.id)}>
                    <Trash2 className="h-4 w-4 text-[var(--ks-color-text-soft)]" />
                  </Button>
                )}
              </div>
            ))}
          </div>

          {podeEditar && (
            <div className="p-5 pt-3 border-t border-[var(--ks-color-border-subtle)]">
              <div className="grid grid-cols-1 sm:grid-cols-[1fr_130px_auto] gap-2">
                <Input
                  placeholder="Nome da despesa — ex: Pró-labore"
                  value={novo.name}
                  onChange={(e) => setNovo((v) => ({ ...v, name: e.target.value }))}
                />
                <Input
                  placeholder="0,00"
                  inputMode="decimal"
                  value={novo.monthly_amount}
                  onChange={(e) => setNovo((v) => ({ ...v, monthly_amount: formatMoneyInput(e.target.value) }))}
                />
                <Button
                  onClick={() => void adicionar()}
                  disabled={salvandoNovo || !novo.name.trim() || parseMoneyInput(novo.monthly_amount) <= 0}
                  icon={salvandoNovo ? <Loader2 className="h-4 w-4 animate-spin" /> : <Plus size={16} />}
                >
                  Adicionar
                </Button>
              </div>
            </div>
          )}
        </section>
      </div>
    </div>
  );
}
