import LoaderSun from "@/components/common/Loader/LoaderSun";
import { handleSweetAlert } from "@/components/Modal/SweetAlertConfirm";
import { listarLojas } from "@/requests/CRUD/Lojas/listarLojas";
import { listarParametros } from "@/requests/CRUD/ParametrosComerciais/listarParametros";
import { useAuth } from "@/src/contexts/authContext";
import {
  aplicarSugestaoDeslocamento,
  exigeDeslocamento,
  isCustoExtraDeslocamento,
  montarMsgDeslocamentoObrigatorio,
  paraNumero,
} from "@/utils/deslocamento";
import { useEffect, useRef, useState } from "react";
import { obterCustosExtras } from "../CXESSIM002";
import FormMarkupCustosExtras from "../CXESSIM002/FormMarkupCustosExtras";

const MarkupCustosExtrasProposta = ({
  form,
  blockNextStep,
  defaultValues,
  dadosAmpliacao,
  lastProposalInfo,
  valorColeta,
  dadosCard,
  dadosCliente,
  camposPersonalizados,
  setNextStepAction,
  camposPersonalizadosData,
}: any) => {
  const [custosExtras, setCustosExtras] = useState<any[]>(
    form.control._formValues?.custos_extras || [],
  );
  const [isLoaded, setIsLoaded] = useState(false);
  // Parâmetros de deslocamento do tipo de negócio da proposta.
  const [parametroDeslocamento, setParametroDeslocamento] = useState<any>(null);
  // Espelho em ref: a validação de avanço é registrada uma única vez no
  // stepper e precisa ler o valor mais recente sem recriar o callback.
  const parametroDeslocamentoRef = useRef<any>(null);

  const { usuario } = useAuth();

  const distanciaLojaKm = paraNumero(dadosCard?.distanciaLoja_coleta) ?? 0;

  // Os parâmetros de deslocamento precisam estar carregados ANTES dos custos
  // extras: é o que permite já marcar o DESLOCAMENTO e sugerir os Kms.
  useEffect(() => {
    blockNextStep(true);

    listarParametros()
      .then((parametros: any) => {
        const tipoNegocio = String(dadosCard?.tipoNegocio_coleta ?? "");
        return parametros?.deslocamento?.[tipoNegocio] || null;
      })
      .catch(() => null)
      .then((parametro: any) => {
        parametroDeslocamentoRef.current = parametro;
        setParametroDeslocamento(parametro);
        return obterCustosExtrasProposta(parametro);
      })
      .finally(() => setIsLoaded(true));
  }, []);
  function convertName(name: string) {
    return (
      name
        .normalize("NFD")
        .replace(/[\u0300-\u036f]/g, "")
        .replace(/\s+/g, "_") + "_cp"
    );
  }
  /**
   * Bloqueia o avanço para a etapa de PRECIFICAÇÃO quando a proposta exige a
   * cobrança de DESLOCAMENTO e o custo extra não está marcado.
   * O aviso aparece somente neste momento — a aba de Custos Extras não exibe
   * nenhuma mensagem para não alterar o tamanho da tela.
   */
  const validarDeslocamento = async () => {
    const custosExtrasAtuais = form.control._formValues?.custos_extras || [];

    if (
      !exigeDeslocamento(parametroDeslocamentoRef.current, distanciaLojaKm)
    ) {
      return true;
    }

    const deslocamentoMarcado = (custosExtrasAtuais || []).some(
      (custoExtra: any) =>
        isCustoExtraDeslocamento(custoExtra) && custoExtra.isChecked,
    );

    if (deslocamentoMarcado) return true;

    await handleSweetAlert({
      icon: "warning",
      title: "Atenção!",
      showDenyButton: false,
      confirmButtonText: "Ok",
      html: montarMsgDeslocamentoObrigatorio(
        distanciaLojaKm,
        parametroDeslocamentoRef.current?.kmMinimoDeslocamento_parametro,
      ),
    });

    // Rejeita para impedir a troca de etapa (o stepper avança apenas quando a
    // ação de próximo passo resolve).
    throw new Error("Proposta exige cobrança de DESLOCAMENTO");
  };

  useEffect(() => {
    if (!setNextStepAction || !form?.trigger) return;

    setNextStepAction(() => async () => {
      await validarDeslocamento();

      // Validar apenas os campos personalizados obrigatórios do step atual
      const camposCpObrigatoriosDoStep = (camposPersonalizadosData || [])
        .filter((campo: any) => campo.obrigatorio_campo_personalizado === "1")
        .map((campo: any) => convertName(campo.nome_campo_personalizado));

      // Se não houver campos personalizados obrigatórios neste step, validação passa
      if (camposCpObrigatoriosDoStep.length === 0) {
        return true;
      }

      const isValid = await form.trigger(camposCpObrigatoriosDoStep);
      return isValid;
    });
  }, [JSON.stringify(camposPersonalizadosData)]);
  async function obterCustosExtrasProposta(parametroDeslocamentoAtual?: any) {
    const parametroDesloc =
      parametroDeslocamentoAtual ?? parametroDeslocamentoRef.current;
    let loja = form.control._formValues?.loja;
    if (!loja) {
      await listarLojas().then((lojas) => {
        loja = lojas.find(
          (loj: any) => loj.id_loja == dadosCard?.id_loja_coleta,
        );
        form.setValue("loja", loja);
      });
    }
    const potenciaInversor =
      dadosCard?.tipoNegocio_coleta === "3"
        ? form?.control?._formValues?.potencia_inversores
          ? Number(form?.control?._formValues?.potencia_inversores)
          : Number(lastProposalInfo.potenciaSistema_proposta)
        : form?.control?._formValues?.potencia_inversores
          ? Number(form?.control?._formValues?.potencia_inversores)
          : Number(
              form?.control?._formValues?.componentesKit
                ? form?.control?._formValues?.componentesKit?.find(
                    (componente: any) => componente.tipo_item == "8",
                  )?.potencia_item
                : 0,
            );
    const qtdModulos =
      dadosCard?.tipoNegocio_coleta === "3"
        ? form?.control?._formValues?.quantidade_modulos_ampliacao
        : form?.control?._formValues?.totalModulos;
    const novosParametrosPrecificacao: any = {
      origem_contato: dadosCliente?.origem_cliente,
      tipo_negocio: dadosCard?.tipoNegocio_coleta,
      tipo_telhado:
        form?.control?._formValues?.telhado?.value ||
        dadosAmpliacao?.tipoTelhado_ampliacao ||
        lastProposalInfo?.telhado_proposta,
      distribuidor: form?.control?._formValues?.distribuidor?.id_distribuidor
        ? form?.control?._formValues?.distribuidor?.id_distribuidor
        : form?.control?._formValues?.kitEscolhido?.distribuidor
          ? Number(form?.control?._formValues?.kitEscolhido?.distribuidor)
          : "0",
      valor_kit: valorColeta,
      // Distância Aproximada da Loja (Km, somente IDA) calculada na aba
      // "Endereço da Instalação" do card. Usada para sugerir os KMs de
      // DESLOCAMENTO (ida e volta) e para a validação de obrigatoriedade.
      distanciaLoja_coleta: distanciaLojaKm,
      // Recarrega os custos extras quando a parametrização de deslocamento
      // do tipo de negócio muda.
      exigirDeslocamento_parametro:
        parametroDesloc?.exigirDeslocamento_parametro ?? "0",
      kmMinimoDeslocamento_parametro:
        parametroDesloc?.kmMinimoDeslocamento_parametro ?? 0,
      potencia_sistema: form?.control?._formValues?.potenciaKwp || "0",
      qtd_modulos: qtdModulos || "0",
      qtd_ucs: form?.control?._formValues?.ucs?.length,
      potencia_modulo: form?.control?._formValues?.potencia_modulo,
      usuario_logado: usuario?.id_usuario,
      vendedor: dadosCard?.responsaveis["Vendedor"],
      loja: dadosCard?.id_loja_coleta,
      comissao_preVendedor_loja: dadosCard?.comissao_preVendedor_loja,
      comissao_gerente_loja: dadosCard?.comissao_gerente_loja,
      comissao_indicacao_loja: dadosCard?.comissao_indicacao_loja,
      potencia_inversor: Number(potenciaInversor),
    };

    function setarPoliticaPrecoProposta(politica_preco: any) {
      form.setValue("politicaPreco", politica_preco);
    }

    // Sempre recarrega nesta etapa para garantir a sugestão atualizada de
    // DESLOCAMENTO (Km ida e volta + marcado), mesmo se os parâmetros de
    // precificação não mudaram desde a última visita ao step.
    return obterCustosExtras(
      {
        ...{
          ...novosParametrosPrecificacao,
          responsaveis: dadosCard?.responsaveis,
        },
        loja,
        parametroDeslocamento: parametroDesloc,
      },
      setarPoliticaPrecoProposta,
    )
      .then((res) => {
        const comSugestao = (res || []).map((custoExtra: any) =>
          aplicarSugestaoDeslocamento(
            custoExtra,
            parametroDesloc,
            distanciaLojaKm,
          ),
        );
        setCustosExtras(comSugestao);
      })
      .catch(() => {
        setCustosExtras([]);
      })
      .finally(() =>
        form.setValue("parametrosPrecificacao", novosParametrosPrecificacao),
      );
  }

  useEffect(() => {
    const { politicaPreco } = form.control._formValues;

    form.setValue("custos_extras", custosExtras);
    form.setValue("parametrosPrecificacao", {
      ...form.control._formValues.parametrosPrecificacao,
      politicaPreco,
    });
  }, [custosExtras]);

  return (
    <>
      {isLoaded ? (
        <div className="">
          <div className="w-full flex flex-col items-center justify-center mb-4">
            <FormMarkupCustosExtras
              formColeta={form}
              custosExtras={custosExtras}
              defaultValues={defaultValues}
              setCustosExtras={setCustosExtras}
              setBlockNextStep={blockNextStep}
              parametroDeslocamento={parametroDeslocamento}
              distanciaLoja={distanciaLojaKm}
            />
          </div>
          {camposPersonalizados}
        </div>
      ) : (
        <div className="flex justify-center">
          <LoaderSun />
        </div>
      )}
    </>
  );
};

export default MarkupCustosExtrasProposta;
