"use client";

import { useState } from "react";

import {
  TABELA_DA_ENTIDADE,
  conferirValores,
  valoresDaLinha,
  type EntidadeDoCampo,
  type ValoresDosCampos,
} from "@/lib/campos-proprios";
import { getSupabaseClient } from "@/lib/supabase";

import { CamposDoFormulario, type ValoresEmEdicao } from "./campos-do-formulario";
import { CamposNaTela } from "./campos-na-tela";
import { useCamposProprios } from "./use-campos-proprios";

/*
  O quadro "Informações extras" das telas de detalhe (cliente, pedido): mostra
  os campos próprios e, para quem pode, abre a edição ali mesmo. Grava só a
  coluna campos_proprios da linha, relendo o que está no banco antes, para
  não apagar o que outra pessoa (ou o assistente) gravou enquanto isso.

  Some quando a empresa não tem campo para esta entidade e a linha não tem
  valor guardado.
*/

export function BlocoDeCamposProprios({
  entidade,
  registroId,
  valores,
  podeEditar,
  aoSalvar,
  titulo = "Informações extras",
  className = "rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] p-6",
}: {
  entidade: EntidadeDoCampo;
  registroId: string;
  valores: unknown;
  podeEditar: boolean;
  aoSalvar?: (valores: ValoresDosCampos) => void;
  titulo?: string;
  className?: string;
}) {
  const { definicoes, ativas, carregado } = useCamposProprios(entidade);
  const [editando, setEditando] = useState(false);
  const [rascunho, setRascunho] = useState<ValoresEmEdicao>({});
  const [erros, setErros] = useState<Record<string, string>>({});
  const [erro, setErro] = useState<string | null>(null);
  const [salvando, setSalvando] = useState(false);
  const [salvos, setSalvos] = useState<ValoresDosCampos | null>(null);

  const atuais = salvos ?? valoresDaLinha(valores);
  const temValor = Object.keys(atuais).length > 0;
  if (!carregado || (!ativas.length && !temValor)) return null;

  const abrir = () => {
    setRascunho({ ...atuais });
    setErros({});
    setErro(null);
    setEditando(true);
  };

  const salvar = async () => {
    setSalvando(true);
    setErro(null);
    try {
      const supabase = getSupabaseClient();
      const tabela = TABELA_DA_ENTIDADE[entidade];
      const { data, error } = await supabase.from(tabela).select("campos_proprios").eq("id", registroId).maybeSingle();
      if (error || !data) throw new Error("Não foi possível ler o cadastro agora.");
      const noBanco = valoresDaLinha((data as { campos_proprios?: unknown }).campos_proprios);
      /* Só o que a pessoa mudou vai por cima do que está no banco. */
      const mudados: ValoresEmEdicao = {};
      for (const def of ativas) {
        const antes = atuais[def.chave] ?? null;
        const agora = rascunho[def.chave] ?? null;
        if (antes !== agora) mudados[def.chave] = agora;
      }
      const conferido = conferirValores(definicoes, mudados, { atuais: noBanco, exigirObrigatorios: true });
      if (!conferido.ok) {
        setErros(conferido.erros);
        setErro("Confira os campos marcados.");
        return;
      }
      const { error: erroAoGravar } = await supabase.from(tabela).update({ campos_proprios: conferido.valores }).eq("id", registroId);
      if (erroAoGravar) throw new Error("Não foi possível salvar. Confira se você tem permissão para editar.");
      setSalvos(conferido.valores);
      aoSalvar?.(conferido.valores);
      setEditando(false);
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não foi possível salvar.");
    } finally {
      setSalvando(false);
    }
  };

  return (
    <div className={className}>
      <div className="flex flex-wrap items-center justify-between gap-2">
        <h3 className="text-lg font-semibold text-[var(--ks-color-text-primary)]">{titulo}</h3>
        {podeEditar && ativas.length > 0 && !editando ? (
          <button type="button" onClick={abrir} className="ks-button ks-button-ghost ks-button-sm">
            {temValor ? "Editar" : "Preencher"}
          </button>
        ) : null}
      </div>
      {editando ? (
        <div className="mt-4 space-y-4">
          <CamposDoFormulario
            definicoes={definicoes}
            valores={rascunho}
            erros={erros}
            prefixo={`cp-${entidade}`}
            desabilitado={salvando}
            aoMudar={(chave, valor) => {
              setRascunho((atual) => ({ ...atual, [chave]: valor }));
              setErros((atual) => {
                if (!atual[chave]) return atual;
                const resto = { ...atual };
                delete resto[chave];
                return resto;
              });
            }}
          />
          <div className="flex flex-wrap items-center justify-between gap-2">
            {erro ? <p className="text-xs font-semibold text-[var(--ks-color-status-danger)]">{erro}</p> : <span />}
            <span className="flex items-center gap-1.5">
              <button type="button" onClick={() => setEditando(false)} disabled={salvando} className="ks-button ks-button-ghost ks-button-sm">
                Cancelar
              </button>
              <button type="button" onClick={salvar} disabled={salvando} className="ks-button ks-button-primary ks-button-sm">
                {salvando ? "Salvando" : "Salvar"}
              </button>
            </span>
          </div>
        </div>
      ) : (
        <div className="mt-3">
          <CamposNaTela
            definicoes={definicoes}
            valores={atuais}
            vazio={<p className="text-sm text-[var(--ks-color-text-muted)]">Nada preenchido ainda.</p>}
          />
        </div>
      )}
    </div>
  );
}
