import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import LoaderSun from "@/components/common/Loader/LoaderSun";
import Button from "@/components/Forms/Button";
import Container from "@/components/Forms/Container";
import useHasVerticalScroll from "@/hooks/useHasVerticalScroll";
import { listarInclinacoesTelhado } from "@/requests/common/InclinacoesTelhado/listarInclinacoesTelhado";
import { listarOrientacoesSolares } from "@/requests/common/OrientacoesSolares/listarInclinacoesTelhado";
import { listarItensKitsPorTipo } from "@/requests/CRUD/ColetaDados/listarItenskitsDiversos";
import { listarFabricantes } from "@/requests/CRUD/Fabricante/listarFabricantes";
import { listarItensCompostos } from "@/requests/CRUD/ItemComposto/listarItem";
import {
  listarItensKitTabelaPreco,
  listarTabelasPrecosComponentes,
} from "@/requests/CRUD/TabelaPreco/tabelaPreco";
import { listarLojas } from "@/requests/CRUD/Lojas/listarLojas";
import { listarParametros } from "@/requests/CRUD/ParametrosComerciais/listarParametros";
import { listarPerdasMedias } from "@/requests/CRUD/PerdasMedias/listarPerdasMedias";
import { listarCustosExtras } from "@/requests/CRUD/Politica/listarCustosExtras";
import { obterPoliticaComissao } from "@/requests/CRUD/PoliticasComissoes/obterPoliticaComissao";
import { obterPoliticaPreco } from "@/requests/CRUD/PoliticasPreco/obterPoliticaPreco";
import {
  listarUsuarioPeloId,
  listarUsuarios,
} from "@/requests/CRUD/Usuario/listarUsuarios";
import { toast } from "@/services/toast";
import { useAuth } from "@/src/contexts/authContext";
import { FormatFields, GetForm, getDateTimeBrasil } from "@/utils";
import {
  aplicarImpostoNaPrecificacao,
  calcularValorFinalComComissoes,
} from "@/utils/calcules";
import { handleSweetAlert } from "@/components/Modal/SweetAlertConfirm";
import {
  aplicarSugestaoDeslocamento,
  calcularDistanciaKm,
  exigeDeslocamento,
  isCustoExtraDeslocamento,
  montarMsgDeslocamentoObrigatorio,
  obterCoordenadasLoja,
  paraNumero,
} from "@/utils/deslocamento";
import {
  Step,
  StepButton,
  StepConnector,
  stepConnectorClasses,
  StepLabel,
  Stepper,
  styled,
} from "@mui/material";
import { ApexOptions } from "apexcharts";
import { useEffect, useRef, useState } from "react";
import { useReactToPrint } from "react-to-print";
import ResumoProposta from "../CXESCRM005/ResumoProposta";
import ComponentesSimulador from "./ComponentesSimulador";
import FormMarkupCustosExtras from "./FormMarkupCustosExtras";
import FormSimuladorPreco from "./FormSimuladorPreco";
import KitsSimulador from "./KitsSimulador";
import Mapa from "./Mapa";
import ResultSimulador from "./ResultSimulador";
import { origemDadosConfiguracaoGeral } from "@/utils/origemDadosDefault";
interface ChartState {
  series: Array<{ name: string; data: number[] }>;
}
const PaginaSimuladorPreco = () => {
  const { valuesSession, perfil } = useAuth();
  const { session }: any = valuesSession();
  const [stepInicializado, setStepInicializado] = useState(false);

  // const [selectedLoja, setSelectedLoja] = useState();
  const [usuarios, setUsuarios] = useState<any[]>([]);
  const [lojas, setLojas] = useState<any[]>([]);
  const [perdasMedias, setPerdasMedias] = useState<any[]>([]);
  const [orientacoes, setOrientacoes] = useState<any[]>([]);
  const [inclinacoes, setInclinacoes] = useState<any[]>([]);
  const [itensCompostos, setItensCompostos] = useState<any>([]);
  const [itensKitTabelaPreco, setItensKitTabelaPreco] = useState<any[]>([]);
  const [tabelasPrecos, setTabelasPrecos] = useState<any[]>([]);
  const [itensComp, setItensComp] = useState<any>([]);
  const [stringboxes, setStringboxes] = useState<any>([]);

  const [resultadoSimulador, setResultadoSimulador] = useState<{
    [x: string]: any;
  }>({
    valor_kit: 0,
    potencia_inversor: 0,
    porcentagem_sobre_kit: 0,
    valor_sobre_total_kit: 0,
    porcentagem_lucro_produto: 0,
    porcentagem_encargos_produto: 0,
    porcentagem_lucro_encargos_produto: 0,
    markup_produto: 0,
    valor_produto: 0,
    valor_total_produto: 0,
    valor_fixo_servico: 0,
    obra_por_placa_servico: 0,
    qtd_modulos: 0,
    valor_obra_por_placa: 0,
    potencia_sistema: 0,
    obra_por_potencia_servico: 0,
    valor_obra_por_potencia: 0,
    valor_obra_servico: 0,
    porcentagem_servico: 0,
    valor_incluindo_porcentagem_servico: 0,
    lucro_servico: 0,
    encargos_servico: 0,
    porcentagem_lucro_encargos_servico: 0,
    markup_servico: 0,
    valor_servico: 0,
    valor_total_servico: 0,
    valor_extra: 0,
    valor_total_produto_servico_extra: 0,
    porcentagem_total: 0,
    valor_total_incluindo_porcentagem: 0,
    lucro_total: 0,
    encargos_total: 0,
    porcentagem_lucro_encargos_total: 0,
    markup_total: 0,
    valor_total: 0,
    preco_venda_sem_comissao: 0,
    preco_venda_final_sem_comissao: 0,
    preco_venda: 0,
    c_vendedor: null,
    c_pre_vendedor: null,
    c_gerente: null,
    c_indicacao: null,
    c_indicacao_bruto: null,
    valor_comissao: 0,
    id_politica_comissao: "",
    comissao_indicacao_loja: "0",
    comissao_preVendedor_loja: "0",
    comissao_gerente_loja: "0",
    comissao_supervisor_loja: "0",
    id_gerente: "",
  });
  const [refResultSimulador, setRefResultSimulador] = useState<any>();
  const [parametrosSimulador, setParametrosSimulador] = useState<any>({});
  const [custosExtras, setCustosExtras] = useState<any[]>([]);
  const [politicaPreco, setPoliticaPreco] = useState<any>({});
  const [keyCustosExtras, setKeyCustosExtras] = useState(0);
  // Deslocamento: distância aproximada da loja (Km, somente IDA) e tipo de
  // negócio da simulação, usados na validação dos Custos Extras.
  const [distanciaLojaSimulador, setDistanciaLojaSimulador] = useState(0);
  const [tipoNegocioSimulador, setTipoNegocioSimulador] = useState("");
  const [state, setState] = useState<ChartState>({ series: [] });
  const [rsiProposta, setRsiProposta] = useState<any>({});
  const [fabricantes, setFabricantes] = useState<any[]>([]);
  const [fabricantesDistribuidor, setFabricantesDistribuidor] = useState<any[]>(
    [],
  );

  const [apexOptionsGraficoGeracao, setApexOptionsGraficoGeracao] =
    useState<ApexOptions>({});
  const [apexSeriesGraficoGeracao, setApexSeriesGraficoGeracao] = useState<
    { name: string; data: number[] }[]
  >([]);
  const [options, setOptions] = useState<ApexOptions>({});
  const [isLoading, setIsLoading] = useState(false);

  const [step, setStep] = useState(0);
  const [blockNextStep, setBlockNextStep] = useState(false);
  // Rodapé de navegação apenas nas etapas cujo conteúdo passa da altura da tela.
  const { ref: conteudoStepRef, hasScroll } = useHasVerticalScroll<HTMLDivElement>(
    [step]
  );
  const [inversoresBD, setInversoresBD] = useState<any[]>([]);
  const { usuario } = useAuth();

  const [usuarioLogado, setUsuarioLogado] = useState<any>(usuario);
  const [defaultValues, setDefaultValues] = useState<any>();
  const formatarNumero = FormatFields.formatarNumero;
  const { handleSubmit, ...form } = GetForm();
  useEffect(() => {
    listarUsuarios().then(setUsuarios);
    listarItensKitsPorTipo("17").then(setItensCompostos),
      listarLojas().then(setLojas);
    listarItensKitTabelaPreco().then((res) =>
      setItensKitTabelaPreco(Array.isArray(res) ? res : []),
    );
    listarTabelasPrecosComponentes().then((res) =>
      setTabelasPrecos(Array.isArray(res) ? res : []),
    );
    // listarItemComposto().then(setItensCompostos),
    listarItensCompostos().then(setItensComp),
      listarItensKitsPorTipo("13").then(setStringboxes),
      listarItensKitsPorTipo("8").then(setInversoresBD),
      listarParametros().then((res) => setDefaultValues(res));
    listarOrientacoesSolares().then((res) => setOrientacoes(res)),
      listarInclinacoesTelhado().then((res) => setInclinacoes(res)),
      listarPerdasMedias().then((res: any) => {
        setPerdasMedias(res);
      });
  }, []);

  async function submitSimulador(data: any): Promise<void> {
    setUsuarioLogado(usuarios.find((u) => u.id_usuario == data.usuario_logado));
    setParametrosSimulador(data);
    setStep((ant) => ant + 1);
    return new Promise((resolve, reject) => resolve());
  }

  async function submitCustosExtras() {
    // Bloqueia o avanço para a Precificação quando a simulação exige a cobrança
    // de DESLOCAMENTO e o custo extra não está marcado.
    const parametroDeslocamento =
      defaultValues?.deslocamento?.[tipoNegocioSimulador];

    if (
      exigeDeslocamento(parametroDeslocamento, distanciaLojaSimulador) &&
      !custosExtras.some(
        (custoExtra: any) =>
          isCustoExtraDeslocamento(custoExtra) && custoExtra.isChecked,
      )
    ) {
      await handleSweetAlert({
        icon: "warning",
        title: "Atenção!",
        showDenyButton: false,
        confirmButtonText: "Ok",
        html: montarMsgDeslocamentoObrigatorio(
          distanciaLojaSimulador,
          parametroDeslocamento?.kmMinimoDeslocamento_parametro,
        ),
      });
      return;
    }

    setIsLoading(true);
    const dadosAtualizadosSimulador = {
      ...parametrosSimulador,
      politicaPreco,
      custos_extras: custosExtras,
    };

    setParametrosSimulador(dadosAtualizadosSimulador);

    return calcularPreco(dadosAtualizadosSimulador)
      .then((res) => {
        setStep((ant) => ant + 1);
        setResultadoSimulador(res);
        form.setValue(
          "valorFinalProposta",
          formatarNumero(res?.preco_venda_sem_comissao),
        );
        form.setValue("porcentagemValorFinal", formatarNumero("100,00"));
        form.setValue(
          "ajusteValorFinalProposta_formatado",
          formatarNumero(res?.preco_venda),
        );
        form.setValue("ajusteValorFinalProposta", res?.preco_venda);
      })
      .finally(() => setIsLoading(false));
  }

  function atualizarResultadoSimulador(parametros?: any) {
    const parametrosBaseAtualizados = {
      ...parametrosSimulador,
      politicaPreco,
      custos_extras: custosExtras,
    };

    calcularPreco({
      ...parametrosBaseAtualizados,
      ...parametros,
      preco_venda_final_sem_comissao:
        parametros?.preco_venda_final_sem_comissao ||
        resultadoSimulador?.preco_venda_final_sem_comissao,
      c_vendedor_ajuste: Object.keys(parametros).includes("c_vendedor_ajuste")
        ? parametros.c_vendedor_ajuste
        : Number((resultadoSimulador?.c_vendedor * 100).toFixed(2)),
      c_pre_vendedor_ajuste: Object.keys(parametros).includes(
        "c_pre_vendedor_ajuste",
      )
        ? parametros.c_pre_vendedor_ajuste
        : Number((resultadoSimulador?.c_pre_vendedor * 100).toFixed(2)),
      c_gerente_ajuste: Object.keys(parametros).includes("c_gerente_ajuste")
        ? parametros.c_gerente_ajuste
        : Number((resultadoSimulador?.c_gerente * 100).toFixed(2)),
      c_indicacao_ajuste: Object.keys(parametros).includes("c_indicacao_ajuste")
        ? parametros.c_indicacao_ajuste
        : Number((resultadoSimulador?.c_indicacao * 100).toFixed(2)),
      c_supervisor_ajuste: Object.keys(parametros).includes(
        "c_supervisor_ajuste",
      )
        ? parametros.c_supervisor_ajuste
        : Number((resultadoSimulador?.c_supervisor * 100).toFixed(2)),
    }).then((res) => {
      setResultadoSimulador(res);
    });
  }

  const {
    valor_kit,
    preco_venda,
    preco_venda_sem_comissao,
    valor_maximo_venda,
  } = resultadoSimulador;
  useEffect(() => {
    listarFabricantes().then((res) =>
      setFabricantes(
        res.filter((fabricante: any) => fabricante.status_fabricante == 1),
      ),
    );
  }, []);

  const contentRef = useRef<HTMLDivElement>(null);
  const handlePrint = useReactToPrint({
    content: () => contentRef.current,
  });

  let userVendedor = usuarios.filter(
    (res) => res.id_usuario == form.control._formValues?.vendedor?.value,
  )[0];

  const steps: {
    name: string;
    component: JSX.Element;
    submitFn?: (e: any) => Promise<any>;
  }[] =
    new Array(
      {
        name: "Endereço de Instalação",
        component: (
          <Mapa
            usuarios={usuarios}
            form={form}
            lojas={lojas}
            preco_venda={preco_venda}
            valor_kit={valor_kit}
            resultadoSimulador={resultadoSimulador}
          />
        ),
        submitFn: async (e: any) => {
          if (!form.control._formValues?.searchLngLat) {
            return toast.error("Selecione o endereço pra continuar");
          }
          setStep((prev) => prev + 1);
        },
      },
      {
        name: "Dados",
        component: (
          <FormSimuladorPreco
            defaultValues={defaultValues}
            inversoresBD={inversoresBD}
            usuarios={usuarios}
            perdasMedias={perdasMedias}
            usuarioLogado={usuario}
            fabricantes={fabricantes}
            lojas={lojas}
            form={form}
            setFabricantesDistribuidor={setFabricantesDistribuidor}
          />
        ),
        submitFn: (e: any) =>
          handleSubmit(async (data: any) => {
            if (data.kitProprio === "1" && !data?.distribuidor) {
              return toast.error("Selecione um distribuidor");
            }

            if (data.kitProprio === "9" && !data?.distribuidores) {
              return toast.error("Selecione um distribuidor");
            }
            if (
              (data.tipo_string_inversor === "inversor_off_grid" ||
                data.tipo_string_inversor === "inversor_hibrido") &&
              !data?.tipo_bateria
            ) {
              return toast.error("Selecione um tipo de bateria pra continuar");
            }
            if (!data.searchLngLat) {
              // setBlockNextStep(true);
              return toast.error("Selecione o endereço pra continuar");
            }
            setIsLoading(true);
            const {
              comissao_indicacao_loja,
              comissao_preVendedor_loja,
              comissao_gerente_loja,
              comissao_supervisor_loja,
            } = form.control._formValues.loja;
            data = {
              ...data,
              comissao_indicacao_loja,
              comissao_preVendedor_loja,
              comissao_gerente_loja,
              comissao_supervisor_loja,
            };
            return submitSimulador(data)
              .then(() => {
                // setStep(step + 1);
              })
              .catch((err) => {})
              .finally(() => setIsLoading(false));
          })(e),
      },

      {
        name: "Kits",
        component: (
          <div className="w-full flex flex-col items-center justify-center">
            <KitsSimulador
              form={form}
              setStepInicializado={setStepInicializado}
              blockNextStep={setBlockNextStep}
              defaultValues={defaultValues}
              itensCompostos={itensCompostos}
              itensComp={itensComp}
              stringboxes={stringboxes}
              // dadosCard={{}}
              camposPersonalizados={[]}
              imgTelhados={[]}
              // key={keyCustosExtras}
              // setCustosExtras={setCustosExtras}
              // setBlockNextStep={setBlockNextStep}
              // onSubmitFunction={submitCustosExtras}
              fabricantes={fabricantesDistribuidor}
            />
          </div>
        ),
        submitFn: async () => {
          setStep((ant) => ant + 1);
          return new Promise((resolve, reject) => resolve());
        },
      },
      {
        name: "Componentes",
        component: (
          <div className="w-full flex flex-col items-center justify-center">
            <ComponentesSimulador
              form={form}
              itensCompostos={itensCompostos}
              itensKitTabelaPreco={itensKitTabelaPreco}
              tabelasPrecos={tabelasPrecos}
              inversoresBD={inversoresBD}
              itensComp={itensComp}
              setStepInicializado={setStepInicializado}
              stepInicializado={stepInicializado}
              defaultValues={defaultValues}
              blockNextStep={setBlockNextStep}
              camposPersonalizados={[]}
            />
          </div>
        ),
        submitFn: async (e: any) =>
          handleSubmit(async (data: any) => {
            data = { ...parametrosSimulador, ...data };
            setIsLoading(true);
            const loja = lojas.find((loja) => loja.id_loja == data.loja);

            // Distância Aproximada da Loja (Km, somente IDA), usada pelos
            // Custos Extras para sugerir os Kms do DESLOCAMENTO.
            //
            // Prioriza o que o usuário informou na aba "Endereço de
            // Instalação". Se ele não mexeu no campo, recalcula aqui com a
            // loja REALMENTE escolhida na aba "Dados" (a aba do endereço vem
            // antes e usa a loja padrão como referência) e devolve o valor
            // para o form, para as duas abas mostrarem a mesma distância.
            const distanciaInformada = paraNumero(
              data.distanciaLoja_coleta ??
                form.control._formValues?.distanciaLoja_coleta,
            );
            const distanciaEditadaPeloUsuario = Boolean(
              data.distanciaLojaEditada_coleta ??
                form.control._formValues?.distanciaLojaEditada_coleta,
            );
            const distanciaCalculada =
              calcularDistanciaKm(
                obterCoordenadasLoja(loja) || { lat: null, lng: null },
                data.searchLngLat || data.center || { lat: null, lng: null },
              ) || 0;

            const distancia = distanciaEditadaPeloUsuario
              ? (distanciaInformada ?? 0)
              : distanciaCalculada || distanciaInformada || 0;

            setDistanciaLojaSimulador(distancia);
            form.setValue(
              "distanciaLoja_coleta",
              formatarNumero(distancia) as never,
            );
            data.distanciaLoja_coleta = distancia;
            setTipoNegocioSimulador(String(data.tipo_negocio ?? ""));

            return obterCustosExtras(
              {
                ...data,
                loja,
                distanciaLoja_coleta: distancia,
                parametroDeslocamento:
                  defaultValues?.deslocamento?.[
                    String(data.tipo_negocio ?? "")
                  ],
                valor_kit: data.valorColeta,
                potencia_inversor: data.potencia_inversores,
              },
              setPoliticaPreco,
            )
              .then((res) => {
                setKeyCustosExtras((prev) => prev + 1);
                setStep((ant) => ant + 1);
                form.setKey((prev) => prev + 1);
                setCustosExtras(res);
                setParametrosSimulador((prev: any) => ({
                  ...prev,
                  valor_kit: data.valorColeta,
                  potencia_inversor: data.potencia_inversores,
                }));
              })
              .catch((err) => {})
              .finally(() => setIsLoading(false));
          })(e),
      },
      {
        name: "Custos Extras",
        component: (
          <div className="w-full flex flex-col items-center justify-center">
            <FormMarkupCustosExtras
              key={keyCustosExtras}
              custosExtras={custosExtras}
              setCustosExtras={setCustosExtras}
              setBlockNextStep={setBlockNextStep}
              parametroDeslocamento={
                defaultValues?.deslocamento?.[tipoNegocioSimulador]
              }
              distanciaLoja={distanciaLojaSimulador}
              // onSubmitFunction={submitCustosExtras}
            />
          </div>
        ),
        submitFn: submitCustosExtras,
      },

      {
        name: "Precificação",
        component: (
          <ResultSimulador
            usuarios={usuarios}
            setRefResultSimulador={setRefResultSimulador}
            form={form}
            setOptions={setOptions}
            setApexOptionsGraficoGeracao={setApexOptionsGraficoGeracao}
            setApexSeriesGraficoGeracao={setApexSeriesGraficoGeracao}
            setRsiProposta={setRsiProposta}
            defaultValues={defaultValues}
            setState={setState}
            preco_venda={preco_venda}
            valor_kit={valor_kit}
            resultadoSimulador={resultadoSimulador}
            // setResultSimulador={setResultadoSimulador}
            atualizarResultadoSimulador={atualizarResultadoSimulador}
            blockNextStep={setBlockNextStep}
          />
        ),
      },
      {
        name: "Resumo",
        component: (
          <ResumoProposta
            {...{
              // Props que a Proposta passa e faltavam aqui:
              // - form: o Resumo lê distribuicaoDosModulos dele para a
              //   "Orientação:" no bloco Módulos (sem isso: "Não informado").
              // - tabela_rsi / payback: alimentam a Tabela do RSI e o Gráfico
              //   do RSI.
              // - performance_ratio_parametro / sombreamentos_coleta /
              //   perdaMedia / media_irradiacao_mensal: usados no popup da
              //   fórmula da geração.
              // - data_geracao_proposta / valor_simultaneidade_proposta /
              //   nome_tipoLigacao_proposta: campos que a Proposta sempre
              //   mostra no Resumo e que aqui não tinham equivalente, mesmo
              //   sendo calculáveis a partir do que o Simulador já coleta.
              form,
              tabela_rsi: rsiProposta?.tabela_rsi,
              payback: rsiProposta?.payback,
              performance_ratio_parametro:
                defaultValues?.performance_ratio_parametro,
              sombreamentos_coleta:
                form.control._formValues?.sombreamentos_coleta ??
                defaultValues?.sombreamento_parametro,
              media_irradiacao_mensal:
                form.control._formValues?.media_irradiacao_mensal,
              perdaMedia: perdasMedias.find(
                (perda: any) =>
                  perda.cod_orientacao_solar ==
                    defaultValues?.orientacao_parametro &&
                  perda.cod_inclinacao_telhado ==
                    defaultValues?.inclinacao_parametro
              )?.valor_perda,
              data_geracao_proposta: getDateTimeBrasil({
                day: "2-digit",
                month: "long",
                year: "numeric",
              }),
              valor_simultaneidade_proposta:
                defaultValues?.simultaneidade_proposta,
              nome_tipoLigacao_proposta:
                form.control._formValues?.tipoLigacao?.label,
              valorTotal_proposta:
                // form.control._formValues?.preco_venda_aplicando_comissao,
                form.control._formValues?.ajusteValorFinalProposta,
              valor_desconto: form.control._formValues?.valorDesconto || 0,
              valor_total_sem_desconto: valor_maximo_venda,
              valor_acrescimo: form.control._formValues?.valorAcrescimo || 0,
              valor_total_sem_acrescimo: valor_maximo_venda,
              nome_concessisonaria:
                form.control._formValues?.concessionaria_coleta?.label,
              tipo_kit: form.control._formValues?.kitProprio
                ? "Próprio"
                : "Distribuidor",
              nome_telhado: form.control._formValues?.tipo_telhado?.label,
              nome_distribuidor: form.control._formValues?.distribuidor?.label,
              nome_usuario: usuario?.nome_usuario,
              preco_tarifa: form?.control?._formValues?.precoTotal_tarifa,
              percentual_aumento_consumo:
                form.control._formValues?.porcentagemGeracao ??
                defaultValues?.margem_geracao_parametro,
              seguro_percentual: defaultValues?.seguro_rsi_parametro,
              isLoadedResumo: true,
              origem: "simulador",
              origem_dados_default: origemDadosConfiguracaoGeral(),
              parametros_politica_vigente: {
                id_preco_politica:
                  resultadoSimulador?.id_preco_politica || null,
                id_politica_comissao:
                  resultadoSimulador?.id_politica_comissao || null,
                qtd_custos_extras: Array.isArray(
                  resultadoSimulador?.custos_extras,
                )
                  ? resultadoSimulador.custos_extras.length
                  : null,
              },
              potencia_sistema: Number(
                form.control._formValues?.potencia_sistema?.replace(",", "."),
              ),
              refResultSimulador,
              consumoTotal:
                form.control._formValues.consumoTotal ||
                form.control._formValues.consumo_medio,
              estimativa_geracao: +form.control._formValues?.estimativaGeracao,
              abatimento: form.control._formValues?.abatimento,
              qtd_modulos: form.control._formValues.qtd_modulos,
              fiob_tarifa: form.control._formValues.fiob_tarifa,
              potencia_modulo: form.control._formValues?.potencia_modulo,
              modulo: form.control._formValues.modulo,
              fabricantes,
              tipoNegocio_coleta: "1",
              area_ocupada: form.control._formValues?.area_ocupada,
              apexOptionsGraficoGeracao,
              apexSeriesGraficoGeracao,
              apexOptionsGraficoRsi: options,
              apexSeriesGraficoRsi: state.series,
              area_modulo: form.control._formValues?.area_modulo,
              inversores_proposta:
                form.control._formValues?.inversores_proposta,
            }}
          />
        ),
      },
    ) || [];

  const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
    [`&.${stepConnectorClasses.alternativeLabel}`]: {
      top: 22,
    },
    [`&.${stepConnectorClasses.active}`]: {
      [`& .${stepConnectorClasses.line}`]: {
        backgroundImage:
          "linear-gradient( 95deg,rgb(71,148,250) 0%, rgb(29,120,186) 50%, rgb(60,80,224) 100%)",
      },
    },
    [`&.${stepConnectorClasses.completed}`]: {
      [`& .${stepConnectorClasses.line}`]: {
        backgroundImage:
          "linear-gradient( 95deg,rgb(71,148,250) 0%, rgb(29,120,186) 50%, rgb(60,80,224) 100%)",
      },
    },
    [`& .${stepConnectorClasses.line}`]: {
      height: 3,
      border: 0,
      backgroundColor: "#eaeaf0",
      borderRadius: 1,
      ...theme.applyStyles("dark", {
        backgroundColor: theme.palette.grey[800],
      }),
    },
  }));

  const ColorlibStepIconRoot = styled("div")<{
    ownerState: { completed?: boolean; active?: boolean };
  }>(({ theme }) => ({
    backgroundColor: "#ccc",
    zIndex: 1,
    color: "#fff",
    width: 50,
    height: 50,
    display: "flex",
    borderRadius: "50%",
    justifyContent: "center",
    alignItems: "center",
    ...theme.applyStyles("dark", {
      backgroundColor: theme.palette.grey[700],
    }),
    variants: [
      {
        props: ({ ownerState }) => ownerState.active,
        style: {
          backgroundImage:
            "linear-gradient( 136deg, rgb(71,148,250) 0%, rgb(29,120,186) 50%, rgb(60,80,224) 100%)",
          boxShadow: "0 4px 10px 0 rgba(0,0,0,.25)",
        },
      },
      {
        props: ({ ownerState }) => ownerState.completed,
        style: {
          backgroundImage:
            "linear-gradient( 136deg, rgb(71,148,250) 0%, rgb(29,120,186) 50%, rgb(60,80,224) 100%)",
        },
      },
    ],
  }));

  function ColorlibStepIcon(props: any, index: number) {
    const { active, completed, className } = props;

    return (
      <ColorlibStepIconRoot
        ownerState={{ completed, active }}
        className={className}
      >
        {index + 1}
      </ColorlibStepIconRoot>
    );
  }

  // Barra de navegação (Voltar/Próximo) reutilizada no topo e no rodapé.
  // O rodapé facilita a navegação em telas com rolagem (mobile).
  const renderNavButtons = (wrapperClassName: string) => (
    <div className={`flex w-full justify-between ${wrapperClassName}`}>
      <div>
        <Button
          type="button"
          className={`flex border-[1px] border-[#cbced4] bg-primary hover:brightness-90 px-9 h-9 items-center rounded-lg ${!(step > 0) && "hidden"}`}
          color="inherit"
          onClick={() => setStep((prev) => prev - 1)}
          loading={isLoading}
          sx={{ mr: 1 }}
        >
          Voltar
        </Button>
      </div>
      <Button
        className={`flex border-[1px] border-[#cbced4] bg-primary hover:brightness-90 px-9 h-9 items-center rounded-lg ${!(step < steps.length - 1) && "hidden"}`}
        type="button"
        disabled={blockNextStep}
        loading={isLoading}
        onClick={(e: any) => {
          if (steps[step]?.submitFn) {
            steps[step]?.submitFn?.(e);
          } else {
            setStep((prev) => prev + 1);
          }
        }}
        sx={{ mr: 1 }}
      >
        Próximo
      </Button>
    </div>
  );

  return (
    <>
      <Breadcrumb pageName="Simulador de Preço" />
      <Container>
        <div className="w-full overflow-x-auto">
          <Stepper
            alternativeLabel
            connector={<ColorlibConnector />}
            sx={{ minWidth: 560 }}
            activeStep={
            // isMobile
            //   ? activeStep == 0
            //     ? activeStep
            //     : activeStep == stepsOriginals.length - 1
            //       ? 2
            //       : 1
            //   :
            step
          }
          className="mb-2 "
        >
          {steps.map((s, index) => {
            return (
              <Step
                key={index}
                completed={index < step}
                // style={{
                //   display: steps.includes(label) ? "block" : "none",
                // }}
              >
                <StepButton
                  onClick={() => setStep(index)}
                  style={{
                    margin: "-10px",
                    padding: "10px",
                  }}
                >
                  <StepLabel
                    StepIconComponent={(e) => ColorlibStepIcon(e, index)}
                    className="text-black !text-xs dark:text-white "
                  >
                    {s.name}
                  </StepLabel>
                </StepButton>
              </Step>
            );
          })}
          </Stepper>
        </div>
        {renderNavButtons("pb-2")}
        {steps[step]?.name}
        <div ref={conteudoStepRef} className="w-full">
          {defaultValues ? (
            steps[step]?.component
          ) : (
            <div className="flex relative mt-[10%] overflow-hidden items-center justify-center">
              <LoaderSun />
            </div>
          )}
        </div>
        {/* Navegação no rodapé somente quando a etapa tem rolagem */}
        {defaultValues &&
          hasScroll &&
          renderNavButtons(
            "pt-3 mt-3 border-t border-stroke dark:border-strokedark"
          )}
      </Container>
    </>
  );
};

export default PaginaSimuladorPreco;

async function resolveLojaConfig(data: any) {
  if (
    data.loja &&
    typeof data.loja === "object" &&
    data.loja.calcular_comissao_por_loja !== undefined
  ) {
    return data.loja;
  }

  const lojaId = typeof data.loja === "object" ? data.loja?.id_loja : data.loja;

  if (!lojaId) {
    return null;
  }

  const lojas = await listarLojas();
  return (
    lojas.find((loja: any) => String(loja.id_loja) === String(lojaId)) || null
  );
}

export async function calcularPreco(data: any) {
  let resultado: any = {
    valor_kit: 0,
    potencia_inversor: 0,
    porcentagem_sobre_kit: 0,
    valor_sobre_total_kit: 0,
    porcentagem_lucro_produto: 0,
    porcentagem_encargos_produto: 0,
    porcentagem_lucro_encargos_produto: 0,
    markup_produto: 0,
    valor_produto: 0,
    valor_total_produto: 0,
    valor_fixo_servico: 0,
    obra_por_placa_servico: 0,
    qtd_modulos: 0,
    qtd_ucs: 0,
    valor_obra_por_placa: 0,
    potencia_sistema: 0,
    obra_por_potencia_servico: 0,
    valor_obra_por_potencia: 0,
    valor_obra_servico: 0,
    porcentagem_servico: 0,
    valor_incluindo_porcentagem_servico: 0,
    lucro_servico: 0,
    encargos_servico: 0,
    porcentagem_lucro_encargos_servico: 0,
    markup_servico: 0,
    valor_servico: 0,
    valor_total_servico: 0,
    custos_extras: [],
    valor_extra: 0,
    valor_total_extra: 0,
    valor_total_produto_servico_extra: 0,
    porcentagem_total: 0,
    valor_total_incluindo_porcentagem: 0,
    lucro_total: 0,
    encargos_total: 0,
    porcentagem_lucro_encargos_total: 0,
    markup_total: 0,
    valor_total: 0,
    preco_venda_sem_comissao: 0,
    preco_venda_final_sem_comissao: 0,
    preco_venda: 0,
    c_max: 0,
    c_vendedor: null,
    c_pre_vendedor: null,
    c_gerente: null,
    c_supervisor: null,
    c_indicacao: null,
    c_indicacao_bruto: null,
    valor_comissao: 0,
    id_politica_comissao: "",
    comissao_indicacao_loja: "",
    comissao_preVendedor_loja: "",
    comissao_gerente_loja: "",
    comissao_supervisor_loja: "",
    id_gerente: "",
  };
  // return obterPoliticaPreco(data)
  //   .then((res) => {
  //     if (!res) {
  //       toast.warning("Não foi encontrada política de preço");
  //       return resultado;
  //     }
  const res = data.politicaPreco;
  if (!res) {
    toast.error("Erro: Não foi encontrada Política de Preço!");
    return resultado;
  }

  const valor_kit = Number(data.valor_kit);
  const potencia_inversor = Number(data.potencia_inversor);
  const finalizarResultado = (partial: any) =>
    aplicarImpostoNaPrecificacao(partial, res, valor_kit);
  ///// Produto /////

  const {
    porcentagem_sobre_kit,
    valor_sobre_total_kit,
    porcentagem_lucro_produto,
    porcentagem_encargos_produto,
    porcentagem_lucro_encargos_produto,
    markup_produto,
    valor_produto,
    valor_total_produto,
  } = calcularValoresProduto({ valor_kit, politica_preco: res });

  // const porcentagem_sobre_kit = Number(res?.kit_produto_politica) / 100;
  // // % Sobre o Kit definido na política
  // // Valor do Kit * % Sobre o Kit
  // const valor_sobre_total_kit = valor_kit * porcentagem_sobre_kit;

  // // Markup do Produto
  // const porcentagem_lucro_produto =
  //   Number(res?.lucro_produto_politica) / 100;
  // const porcentagem_encargos_produto =
  //   Number(res?.encargos_produto_politica) / 100;
  // // = 1-(% Lucro + %  Encargos (Custo Fixo)): Ex: 1-(10% + 5%) = "79%"
  // const porcentagem_lucro_encargos_produto =
  //   1 - (porcentagem_lucro_produto + porcentagem_encargos_produto);

  // // = (Valor do Kit [R$] + % Sobre Kit [R$]) / % Markup) - (Valor do Kit [R$] + % Sobre Kit [R$])
  // const markup_produto =
  //   (valor_kit + valor_sobre_total_kit) /
  //     porcentagem_lucro_encargos_produto -
  //   (valor_kit + valor_sobre_total_kit);

  // // Valor a ser aplicado a nível de Produto
  // // = Valor R$ do % Sobre o Kit + Valor do Markup do Produto
  // const valor_produto = valor_sobre_total_kit + markup_produto;

  // const valor_total_produto = valor_kit + valor_produto;

  //////////

  ///// Serviço /////

  const {
    valor_fixo_servico,
    obra_por_placa_servico,
    qtd_modulos,
    qtd_ucs,
    valor_obra_por_placa,
    potencia_sistema,
    obra_por_potencia_servico,
    valor_obra_por_potencia,
    valor_obra_servico,
    porcentagem_servico,
    valor_incluindo_porcentagem_servico,
    lucro_servico,
    encargos_servico,
    porcentagem_lucro_encargos_servico,
    markup_servico,
    valor_servico,
    valor_total_servico,
  } = calcularValoresServico({ valor_kit, data, politica_preco: res });
  // const valor_fixo_servico = Number(res?.valor_fixo_servico_politica);

  // const obra_por_placa_servico = Number(
  //   res?.obra_por_placa_servico_politica
  // );
  // const qtd_modulos = Number(data.qtd_modulos);

  // const valor_obra_por_placa = obra_por_placa_servico * qtd_modulos;

  // const potencia_sistema = Number(data.potencia_sistema);

  // const obra_por_potencia_servico = Number(
  //   res?.obra_por_potencia_servico_politica
  // );

  // const valor_obra_por_potencia =
  //   potencia_sistema * obra_por_potencia_servico;

  // // = Somar o Valor Fixo + Valor Mão de Obra Placa + Valor Mão de Obra por Potência kWp:
  // const valor_obra_servico =
  //   valor_fixo_servico + valor_obra_por_placa + valor_obra_por_potencia;

  // const porcentagem_servico =
  //   Number(res?.porcentagem_servico_politica) / 100;

  // const valor_incluindo_porcentagem_servico =
  //   valor_obra_servico * porcentagem_servico;

  // const lucro_servico = Number(res?.lucro_servico_politica) / 100;
  // const encargos_servico = Number(res?.encargos_servico_politica) / 100;

  // const porcentagem_lucro_encargos_servico =
  //   1 - (lucro_servico + encargos_servico);

  // const markup_servico =
  //   (valor_obra_servico + valor_incluindo_porcentagem_servico) /
  //     porcentagem_lucro_encargos_servico -
  //   (valor_obra_servico + valor_incluindo_porcentagem_servico);

  // const valor_servico =
  //   valor_obra_servico +
  //   valor_incluindo_porcentagem_servico +
  //   markup_servico;

  // const valor_total_servico = valor_kit + valor_servico;

  //////////

  ///// Custos Extras /////

  const custos_extras = data.custos_extras || [];
  const valor_extra = custos_extras.reduce((acc: number, custo_extra: any) => {
    return custo_extra.isChecked ? (acc += custo_extra.value) : acc;
  }, 0);

  const valor_total_extra = valor_kit + valor_extra;

  //////////

  ///// Valor Total /////

  const valor_total_produto_servico_extra =
    valor_kit + valor_produto + valor_servico + valor_extra;

  const porcentagem_total = Number(res?.porcentagem_total_politica) / 100;

  const valor_total_incluindo_porcentagem =
    valor_total_produto_servico_extra * porcentagem_total;

  // Permite sobrescrever o % de Lucro da Empresa (ex: "Ajuste do Valor Final
  // da Proposta" resolvendo qual lucro_total bate um alvo), igual o padrão de
  // "_ajuste" já usado pra comissões.
  const lucro_total =
    data?.lucro_total_ajuste !== undefined && !isNaN(data?.lucro_total_ajuste)
      ? Number(data.lucro_total_ajuste) / 100
      : Number(res?.lucro_total_politica) / 100;
  const encargos_total = Number(res?.encargos_total_politica) / 100;

  const porcentagem_lucro_encargos_total = 1 - (lucro_total + encargos_total);

  const markup_total =
    (valor_total_produto_servico_extra + valor_total_incluindo_porcentagem) /
      porcentagem_lucro_encargos_total -
    (valor_total_produto_servico_extra + valor_total_incluindo_porcentagem);

  const valor_total = valor_total_incluindo_porcentagem + markup_total;

  //////////

  ///// Preço de venda da Politica de preço /////

  const preco_venda = Number(
    (
      data?.preco_venda_final_sem_comissao ||
      valor_total_produto_servico_extra + valor_total
    ).toFixed(2),
  );
  const preco_venda_sem_comissao =
    valor_total_produto_servico_extra + valor_total;

  //////////

  ///// Comissões /////
  resultado = {
    ...resultado,
    valor_kit,
    potencia_inversor,
    //
    porcentagem_sobre_kit,
    valor_sobre_total_kit,
    porcentagem_lucro_produto,
    porcentagem_encargos_produto,
    porcentagem_lucro_encargos_produto,
    markup_produto,
    valor_produto,
    valor_total_produto,
    //
    valor_fixo_servico,
    obra_por_placa_servico,
    qtd_modulos,
    qtd_ucs,
    valor_obra_por_placa,
    potencia_sistema,
    obra_por_potencia_servico,
    valor_obra_por_potencia,
    valor_obra_servico,
    porcentagem_servico,
    valor_incluindo_porcentagem_servico,
    lucro_servico,
    encargos_servico,
    porcentagem_lucro_encargos_servico,
    markup_servico,
    valor_servico,
    valor_total_servico,
    //
    custos_extras,
    valor_extra,
    valor_total_extra,
    //
    valor_total_produto_servico_extra,
    porcentagem_total,
    valor_total_incluindo_porcentagem,
    lucro_total,
    encargos_total,
    porcentagem_lucro_encargos_total,
    markup_total,
    valor_total,
    preco_venda_sem_comissao,
    //
    preco_venda,
    preco_venda_final_sem_comissao: preco_venda,
    //
    c_vendedor: null,
    c_pre_vendedor: null,
    c_gerente: null,
    c_supervisor: null,
    c_indicacao: null,
    c_indicacao_bruto: null,
    valor_comissao: 0,
    //
    valor_minimo_venda: preco_venda_sem_comissao,
    valor_maximo_venda: preco_venda_sem_comissao,
    //
    id_politica_comissao: "",
  };

  if (!isNaN(preco_venda)) {
    // O InputSelectComponent guarda a opção INTEIRA (objeto {value, label,
    // ...}) no valor do form, não o id puro. obterPoliticaComissao faz
    // FIND_IN_SET/WHERE com estes campos como escalares no PHP - passando o
    // objeto o match falha silenciosamente (só "loja" já era normalizado
    // aqui). Normaliza vendedor/origem_contato/tipo_negocio do mesmo jeito.
    const extrairId = (valor: any) =>
      valor && typeof valor === "object" ? valor?.value ?? valor : valor;
    const lojaIdComissao =
      typeof data.loja === "object" ? data.loja?.id_loja : data.loja;
    const vendedorIdComissao = extrairId(data.vendedor);
    const origemContatoIdComissao = extrairId(data.origem_contato);
    const tipoNegocioIdComissao = extrairId(data.tipo_negocio);
    return obterPoliticaComissao({
      ...data,
      loja: lojaIdComissao,
      vendedor: vendedorIdComissao,
      origem_contato: origemContatoIdComissao,
      tipo_negocio: tipoNegocioIdComissao,
      preco_venda,
    })
      .then((politicaComissao) => {
        console.log("politicaComissao", politicaComissao);
        if (politicaComissao) {
          return listarUsuarioPeloId(vendedorIdComissao)
            .then(async (dados_vendedor) => {
              const { id_politica_comissao } = politicaComissao;

              const comissao_preVendedor_loja =
                data["pre_vendedor_checked"] == "true" ||
                (data.responsaveis?.["Pré-Vendedor"] &&
                  data.responsaveis["Pré-Vendedor"] !== null &&
                  data.responsaveis["Pré-Vendedor"] !== "0" &&
                  data.responsaveis["Pré-Vendedor"] !== "")
                  ? data.comissao_preVendedor_loja
                  : "0";

              const comissao_gerente_loja =
                data["gerente_checked"] == "true" ||
                (data.responsaveis?.["Gerente"] &&
                  data.responsaveis["Gerente"] !== null &&
                  data.responsaveis["Gerente"] !== "0" &&
                  data.responsaveis["Gerente"] !== "")
                  ? data.comissao_gerente_loja
                  : "0";

              const comissao_indicacao_loja =
                data["indicacao_checked"] == "true" ||
                (data.codIndicador_coleta &&
                  data.codIndicador_coleta !== null &&
                  data.codIndicador_coleta !== "0" &&
                  data.codIndicador_coleta !== "")
                  ? data.comissao_indicacao_loja
                  : "0";

              const comissao_supervisor_loja =
                data["supervisor_checked"] == "true" ||
                (data.responsaveis?.["Supervisor"] &&
                  data.responsaveis["Supervisor"] !== null &&
                  data.responsaveis["Supervisor"] !== "0" &&
                  data.responsaveis["Supervisor"] !== "")
                  ? data.comissao_supervisor_loja
                  : "0";

              const gerente = data.responsaveis?.["Gerente"]
                ? data.responsaveis?.["Gerente"]
                : dados_vendedor?.supervisor_usuario != "0" &&
                    comissao_gerente_loja == "1"
                  ? dados_vendedor?.supervisor_usuario
                  : null;

              // Tolerância de arredondamento no teto da política.
              // A cascata de comissões em centavos
              // (PrecificacaoProposta.distribuirComissoesEmCentavos) devolve o %
              // de cada cargo como centavosArredondados / base — ex.: 1% de
              // R$ 20.980,83 = R$ 209,8083, arredondado para R$ 209,81, que de
              // volta em % dá 1,000008%. Com `toFixed(6)` essa sobra na 6ª casa
              // sobrevive e, comparada com `>` puro, disparava aviso falso de
              // "Comissão acima do padrão" a cada recálculo, mesmo com o usuário
              // dentro do padrão. Acima da tolerância = excesso real: avisa e capa.
              // Dentro da tolerância: capa em silêncio, para o resíduo não
              // acumular nos recálculos seguintes.
              const TOLERANCIA_TETO_COMISSAO = 0.001; // pontos percentuais
              const excedeTetoComissao = (valor: any, teto: number) =>
                (+valor || 0) - teto > TOLERANCIA_TETO_COMISSAO;

              const tetoPercentVendedor =
                +politicaComissao.comissao_vendedor_politica_comissao || 0;

              if (excedeTetoComissao(data?.c_vendedor_ajuste, tetoPercentVendedor)) {
                data.c_vendedor_ajuste =
                  politicaComissao.comissao_vendedor_politica_comissao;
                toast.error(
                  `Comissão vendedor acima do padrão. Máximo permitido: ${FormatFields.formatarNumero(politicaComissao.comissao_vendedor_politica_comissao)}%`,
                );
              } else if ((+data?.c_vendedor_ajuste || 0) > tetoPercentVendedor) {
                data.c_vendedor_ajuste = tetoPercentVendedor;
              }
              const valor_c_vendedor_bruto =
                Object.keys(data).includes("valor_c_vendedor") &&
                !isNaN(data?.valor_c_vendedor)
                  ? data?.valor_c_vendedor
                  : Number(
                      Number(
                        Number(
                          Object.keys(data).includes("c_vendedor_ajuste") &&
                            !isNaN(data?.c_vendedor_ajuste)
                            ? data?.c_vendedor_ajuste
                            : politicaComissao.comissao_vendedor_politica_comissao,
                        ),
                      ) / 100,
                    ) * preco_venda;

              // Teto da política vale para TODOS os caminhos. O clamp acima só
              // cobre c_vendedor_ajuste (%), e a linha seguinte dá prioridade
              // ao valor_c_vendedor (R$ absoluto, usado pela cascata de
              // comissões do "Ajuste do Valor Final da Proposta") - por ali a
              // comissão passava do % configurado na política sem nenhum aviso.
              // Só aplica o teto quando ele é conhecido de verdade: com a
              // política ainda não carregada (tetoPercentVendedor = 0) ou
              // preco_venda zerado na primeira renderização, capar zeraria a
              // comissão em vez de limitá-la.
              const podeAplicarTetoVendedor =
                tetoPercentVendedor > 0 && preco_venda > 0;
              const valorTetoVendedor = (tetoPercentVendedor / 100) * preco_venda;
              const valor_c_vendedor = podeAplicarTetoVendedor
                ? Math.min(valor_c_vendedor_bruto, valorTetoVendedor)
                : valor_c_vendedor_bruto;
              if (valor_c_vendedor_bruto - valor_c_vendedor > 0.01) {
                toast.error(
                  `Comissão vendedor acima do padrão. Máximo permitido: ${FormatFields.formatarNumero(politicaComissao.comissao_vendedor_politica_comissao)}%`
                );
              }

              const c_vendedor = valor_c_vendedor / (preco_venda || 1);

              const tetoPercentPreVendedor =
                Number(
                  politicaComissao.comissao_pre_vendedor_politica_comissao
                ) || 0;
              if (
                excedeTetoComissao(
                  data?.c_pre_vendedor_ajuste,
                  tetoPercentPreVendedor
                )
              ) {
                data.c_pre_vendedor_ajuste =
                  politicaComissao.comissao_pre_vendedor_politica_comissao;
                toast.error(
                  `Comissão pré-vendedor acima do padrão. Máximo permitido: ${FormatFields.formatarNumero(politicaComissao.comissao_pre_vendedor_politica_comissao)}%`,
                );
              } else if (
                (+data?.c_pre_vendedor_ajuste || 0) > tetoPercentPreVendedor
              ) {
                data.c_pre_vendedor_ajuste = tetoPercentPreVendedor;
              }
              const c_pre_vendedor =
                (data.responsaveis
                  ? data.responsaveis["Pré-Vendedor"]
                  : true) && comissao_preVendedor_loja == "1"
                  ? Number(
                      Object.keys(data).includes("c_pre_vendedor_ajuste")
                        ? data?.c_pre_vendedor_ajuste
                        : politicaComissao.comissao_pre_vendedor_politica_comissao,
                    ) / 100
                  : null;

              const tetoPercentGerente =
                Number(politicaComissao.comissao_gerente_politica_comissao) || 0;
              if (
                excedeTetoComissao(data?.c_gerente_ajuste, tetoPercentGerente)
              ) {
                data.c_gerente_ajuste =
                  politicaComissao.comissao_gerente_politica_comissao;
                toast.error(
                  `Comissão gerente acima do padrão. Máximo permitido: ${FormatFields.formatarNumero(politicaComissao.comissao_gerente_politica_comissao)}%`,
                );
              } else if ((+data?.c_gerente_ajuste || 0) > tetoPercentGerente) {
                data.c_gerente_ajuste = tetoPercentGerente;
              }
              const c_gerente_ajuste = Object.keys(data).includes(
                "c_gerente_ajuste",
              )
                ? data?.c_gerente_ajuste
                : politicaComissao.comissao_gerente_politica_comissao;
              const c_gerente =
                gerente != null && comissao_gerente_loja == "1"
                  ? Number(c_gerente_ajuste) / 100
                  : // Fallback: aplicar comissão da política mesmo sem gerente específico
                    comissao_gerente_loja == "1" && c_gerente_ajuste > 0
                    ? Number(c_gerente_ajuste) / 100
                    : null;

              const tetoPercentIndicacao =
                Number(politicaComissao.comissao_indicacao_politica_comissao) ||
                0;
              if (
                excedeTetoComissao(
                  data?.c_indicacao_ajuste,
                  tetoPercentIndicacao
                )
              ) {
                data.c_indicacao_ajuste =
                  politicaComissao.comissao_indicacao_politica_comissao;
                toast.error(
                  `Comissão indicação acima do padrão. Máximo permitido: ${FormatFields.formatarNumero(politicaComissao.comissao_indicacao_politica_comissao)}%`,
                );
              } else if (
                (+data?.c_indicacao_ajuste || 0) > tetoPercentIndicacao
              ) {
                data.c_indicacao_ajuste = tetoPercentIndicacao;
              }
              const c_indicacao =
                comissao_indicacao_loja == "1" &&
                (data.responsaveis ? data.codIndicador_coleta != null : true)
                  ? Number(
                      Object.keys(data).includes("c_indicacao_ajuste")
                        ? data.c_indicacao_ajuste
                        : politicaComissao.comissao_indicacao_politica_comissao,
                    ) / 100
                  : null;
              const c_indicacao_bruto =
                comissao_indicacao_loja == "1" &&
                (data.responsaveis ? data.codIndicador_coleta != null : true)
                  ? Number(
                      politicaComissao.comissao_indicacao_bruto_politica_comissao,
                    )
                  : null;

              const tetoPercentSupervisor =
                Number(politicaComissao.comissao_supervisor_politica_comissao) ||
                0;
              if (
                excedeTetoComissao(
                  data?.c_supervisor_ajuste,
                  tetoPercentSupervisor
                )
              ) {
                data.c_supervisor_ajuste =
                  politicaComissao.comissao_supervisor_politica_comissao;
                toast.error(
                  `Comissão supervisor acima do padrão. Máximo permitido: ${FormatFields.formatarNumero(politicaComissao.comissao_supervisor_politica_comissao)}%`,
                );
              } else if (
                (+data?.c_supervisor_ajuste || 0) > tetoPercentSupervisor
              ) {
                data.c_supervisor_ajuste = tetoPercentSupervisor;
              }
              const c_supervisor =
                (data.responsaveis ? data.responsaveis["Supervisor"] : true) &&
                comissao_supervisor_loja == "1" &&
                data.comissao_supervisor_loja == "1"
                  ? Number(
                      Object.keys(data).includes("c_supervisor_ajuste")
                        ? data?.c_supervisor_ajuste
                        : politicaComissao.comissao_supervisor_politica_comissao,
                    ) / 100
                  : null;

              const id_indicador = data.codIndicador_coleta || null;

              // Preparar percentuais de comissão para cálculo
              const percentuaisComissoes = [
                Number(c_vendedor || 0) * 100,
                Number(c_pre_vendedor || 0) * 100,
                Number(c_gerente || 0) * 100,
                Number(c_indicacao || 0) * 100,
                Number(c_supervisor || 0) * 100,
              ];

              // Obter modo de cálculo de comissão da loja
              const loja = await resolveLojaConfig(data);
              const calcular_comissao_por_loja =
                loja?.calcular_comissao_por_loja || "1";
              const acaoValorFinalProposta_loja =
                loja?.acaoValorFinalProposta_loja || "1";

              // Cada componente de comissão arredondado pra 2 casas ANTES de
              // somar - pra bater exatamente com o que aparece em cada linha
              // da tela (Valor Comissão X). Somar as frações cruas e
              // arredondar só o total no final dá um total sutilmente
              // diferente da soma das linhas já arredondadas mostradas ao
              // usuário (o "não fecha por 1 centavo" clássico).
              const valorComissaoVendedorR = Number(
                (valor_c_vendedor || 0).toFixed(2)
              );
              const valorComissaoPreVendedorR = Number(
                (preco_venda * (c_pre_vendedor || 0)).toFixed(2)
              );
              const valorComissaoGerenteR = Number(
                (preco_venda * (c_gerente || 0)).toFixed(2)
              );
              const valorComissaoIndicacaoR = Number(
                (preco_venda * (c_indicacao || 0)).toFixed(2)
              );
              const valorComissaoSupervisorR = Number(
                (preco_venda * (c_supervisor || 0)).toFixed(2)
              );
              const valorComissaoIndicacaoBrutoR = Number(
                (c_indicacao_bruto || 0).toFixed(2)
              );

              // Calcular valor_comissao e preco_venda_final baseado no modo
              let valor_comissao: number;
              let preco_venda_final_modo: number;

              if (
                String(calcular_comissao_por_loja) === "2" ||
                calcular_comissao_por_loja === 2
              ) {
                // Modo 2: Calcular sobre Valor Final da Proposta
                const { valorFinal, comissoesCalculadas } =
                  calcularValorFinalComComissoes(
                    preco_venda,
                    percentuaisComissoes,
                    Number(c_indicacao_bruto || 0),
                  );

                preco_venda_final_modo = valorFinal;
                valor_comissao = comissoesCalculadas;
              } else {
                // Modo 1: soma os componentes já arredondados, não as
                // frações cruas - garante que Total Custos Comissão bate
                // exatamente com a soma das linhas mostradas.
                valor_comissao = Number(
                  (
                    valorComissaoVendedorR +
                    valorComissaoPreVendedorR +
                    valorComissaoGerenteR +
                    valorComissaoIndicacaoR +
                    valorComissaoSupervisorR +
                    valorComissaoIndicacaoBrutoR
                  ).toFixed(2)
                );

                preco_venda_final_modo = Number(
                  (preco_venda + valor_comissao).toFixed(2)
                );
              }

              // Soma dos percentuais (fração) de todos os cargos exceto o Vendedor -
              // usada para achar o piso (vendedor = 0%) e o teto (vendedor = % máx da política)
              const outrosPercentuaisFrac =
                (c_pre_vendedor || 0) +
                (c_gerente || 0) +
                (c_indicacao || 0) +
                (c_supervisor || 0);
              const vendedorMaxFrac =
                Number(politicaComissao.comissao_vendedor_politica_comissao) /
                100;

              let valor_minimo_venda: number;
              let valor_maximo_venda: number;

              if (
                String(calcular_comissao_por_loja) === "2" ||
                calcular_comissao_por_loja === 2
              ) {
                // Modo 2: comissão sobre o próprio Valor Final (compounding) -
                // mesma fórmula de calcularValorFinalComComissoes, isolando o vendedor
                valor_minimo_venda =
                  preco_venda / (1 - Math.min(outrosPercentuaisFrac, 0.9999));
                valor_maximo_venda =
                  preco_venda /
                  (1 -
                    Math.min(
                      outrosPercentuaisFrac + vendedorMaxFrac,
                      0.9999
                    ));
              } else {
                // Mesmos componentes já arredondados usados em valor_comissao
                // acima - garante que TOTAL MÍNIMO + Comissão Vendedor bate
                // exatamente com o Preço de Venda Aplicando a Política de
                // Comissão (preco_venda_final_modo).
                valor_minimo_venda = Number(
                  (
                    preco_venda +
                    valorComissaoPreVendedorR +
                    valorComissaoGerenteR +
                    valorComissaoIndicacaoR +
                    valorComissaoSupervisorR +
                    valorComissaoIndicacaoBrutoR
                  ).toFixed(2)
                );

                valor_maximo_venda = Number(
                  (
                    valor_minimo_venda +
                    Number((vendedorMaxFrac * preco_venda).toFixed(2))
                  ).toFixed(2)
                );
              }

              // const valor_max_comissao =
              //   preco_venda_sem_comissao *
              //     (Number(
              //       politicaComissao.comissao_vendedor_politica_comissao
              //     ) /
              //       100) +
              //   preco_venda_sem_comissao *
              //     ((data.responsaveis
              //       ? data.responsaveis["Pré-Vendedor"]
              //       : true) && comissao_preVendedor_loja == "1"
              //       ? Number(
              //           politicaComissao.comissao_pre_vendedor_politica_comissao
              //         ) / 100
              //       : null)! +
              //   preco_venda_sem_comissao *
              //     (gerente != null && comissao_gerente_loja == "1"
              //       ? Number(
              //           politicaComissao.comissao_gerente_politica_comissao
              //         ) / 100
              //       : // Fallback: aplicar comissão da política mesmo sem gerente específico
              //         comissao_gerente_loja == "1" &&
              //           politicaComissao.comissao_gerente_politica_comissao > 0
              //         ? Number(
              //             politicaComissao.comissao_gerente_politica_comissao
              //           ) / 100
              //         : null)! +
              //   preco_venda_sem_comissao *
              //     (comissao_indicacao_loja == "1" &&
              //     (data.responsaveis ? data.codIndicador_coleta != null : true)
              //       ? Number(
              //           politicaComissao.comissao_indicacao_politica_comissao
              //         ) / 100
              //       : null)! +
              //   preco_venda_sem_comissao *
              //     ((data.responsaveis
              //       ? data.responsaveis["Supervisor"]
              //       : true) &&
              //     comissao_supervisor_loja == "1" &&
              //     data.comissao_supervisor_loja == "1"
              //       ? Number(
              //           politicaComissao.comissao_supervisor_politica_comissao
              //         ) / 100
              //       : null)! +
              //   c_indicacao_bruto!;

              const c_max =
                Number(politicaComissao.comissao_vendedor_politica_comissao) /
                  100 +
                ((data.responsaveis
                  ? data.responsaveis["Pré-Vendedor"]
                  : true) && comissao_preVendedor_loja == "1"
                  ? Number(
                      politicaComissao.comissao_pre_vendedor_politica_comissao,
                    ) / 100
                  : null)! +
                (gerente != null && comissao_gerente_loja == "1"
                  ? Number(
                      politicaComissao.comissao_gerente_politica_comissao,
                    ) / 100
                  : // Fallback: aplicar comissão da política mesmo sem gerente específico
                    comissao_gerente_loja == "1" &&
                      politicaComissao.comissao_gerente_politica_comissao > 0
                    ? Number(
                        politicaComissao.comissao_gerente_politica_comissao,
                      ) / 100
                    : null)! +
                (comissao_indicacao_loja == "1" &&
                (data.responsaveis ? data.codIndicador_coleta != null : true)
                  ? Number(
                      politicaComissao.comissao_indicacao_politica_comissao,
                    ) / 100
                  : null)! +
                ((data.responsaveis ? data.responsaveis["Supervisor"] : true) &&
                comissao_supervisor_loja == "1" &&
                data.comissao_supervisor_loja == "1"
                  ? Number(
                      politicaComissao.comissao_supervisor_politica_comissao,
                    ) / 100
                  : null)!;

              resultado = {
                ...resultado,
                c_vendedor,
                c_pre_vendedor,
                c_gerente,
                c_indicacao,
                c_indicacao_bruto,
                c_supervisor,
                valor_comissao,
                c_max,
                //
                preco_venda: preco_venda_final_modo,
                valor_minimo_venda,
                valor_maximo_venda,
                preco_venda_final_sem_comissao: preco_venda,
                calcular_comissao_por_loja,
                acaoValorFinalProposta_loja,
                id_politica_comissao,
                id_preco_politica: res?.id_preco_politica || "",
                //
                comissao_preVendedor_loja,
                comissao_gerente_loja,
                comissao_indicacao_loja,
                comissao_supervisor_loja,
                //
                id_gerente: gerente,
                id_pre_vendedor: data.responsaveis?.["Pré-Vendedor"] || null,
                id_indicador,
              };

              return finalizarResultado(resultado);
            })
            .catch((err) => {
              toast.error("Erro ao identificar as informações do usuário");
              return finalizarResultado(resultado);
            });
        } else {
          toast.error(
            <div>
              <div>
                Não foi encontrado uma política de comissão com os parâmetos
                informados:
              </div>
              <div className="text-error italic">
                <div>Valor da Proposta</div>
                <div>Vendedor do Negócio</div>
                <div>Origem do Contato</div>
                <div>Loja</div>
                <div>Tipo do negócio</div>
              </div>
              <div>O resultado não considerará VALORES DE COMISSÕES</div>
            </div>,
            // "Não foi encontrado uma política de comissão com os parâmetos informados: Valor da Proposta, "
          );

          return finalizarResultado(resultado);
          // setPrecoFinal(preco_venda);
        }
      })
      .catch((err) => {
        toast.error("Erro ao buscar por uma política de comissão");
        return finalizarResultado(resultado);
      });
  } else {
    toast.error("Resultado inválido");
    console.error("Resultado inválido", resultado);
    return finalizarResultado(resultado);
  }

  //////////
  // })
  // .catch(() => {
  //   toast.error("Erro ao tentar obter a política de preço");
  //   return resultado;
  // });
}

export function calcularValoresProduto({
  valor_kit,
  politica_preco,
}: {
  valor_kit: number;
  politica_preco: any;
}) {
  const porcentagem_sobre_kit =
    Number(politica_preco?.kit_produto_politica) / 100;
  // % Sobre o Kit definido na política
  // Valor do Kit * % Sobre o Kit
  const valor_sobre_total_kit = valor_kit * porcentagem_sobre_kit;

  // Markup do Produto
  const porcentagem_lucro_produto =
    Number(politica_preco?.lucro_produto_politica) / 100;
  const porcentagem_encargos_produto =
    Number(politica_preco?.encargos_produto_politica) / 100;
  // = 1-(% Lucro + %  Encargos (Custo Fixo)): Ex: 1-(10% + 5%) = "79%"
  const porcentagem_lucro_encargos_produto =
    1 - (porcentagem_lucro_produto + porcentagem_encargos_produto);

  // = (Valor do Kit [R$] + % Sobre Kit [R$]) / % Markup) - (Valor do Kit [R$] + % Sobre Kit [R$])
  const markup_produto =
    (valor_kit + valor_sobre_total_kit) / porcentagem_lucro_encargos_produto -
    (valor_kit + valor_sobre_total_kit);

  // Valor a ser aplicado a nível de Produto
  // = Valor R$ do % Sobre o Kit + Valor do Markup do Produto
  const valor_produto = valor_sobre_total_kit + markup_produto;

  const valor_total_produto = valor_kit + valor_produto;
  return {
    porcentagem_sobre_kit,
    valor_sobre_total_kit,
    porcentagem_lucro_produto,
    porcentagem_encargos_produto,
    porcentagem_lucro_encargos_produto,
    markup_produto,
    valor_produto,
    valor_total_produto,
  };
}

export function calcularValoresServico({
  valor_kit,
  data,
  politica_preco,
}: {
  valor_kit: number;
  data: any;
  politica_preco: any;
}) {
  const valor_fixo_servico = Number(
    data?.valor_servico || politica_preco?.valor_fixo_servico_politica,
  );

  const obra_por_placa_servico = Number(
    politica_preco?.obra_por_placa_servico_politica,
  );
  const qtd_modulos = Number(data.qtd_modulos);

  const qtd_ucs = Number(data.qtd_ucs) || 1;

  const valor_obra_por_placa = obra_por_placa_servico * qtd_modulos;

  const potencia_sistema = Number(data.potencia_sistema);

  const obra_por_potencia_servico = Number(
    politica_preco?.obra_por_potencia_servico_politica,
  );

  const valor_obra_por_potencia = potencia_sistema * obra_por_potencia_servico;

  // = Somar o Valor Fixo + Valor Mão de Obra Placa + Valor Mão de Obra por Potência kWp:
  const valor_obra_servico =
    valor_fixo_servico + valor_obra_por_placa + valor_obra_por_potencia;

  const porcentagem_servico =
    Number(politica_preco?.porcentagem_servico_politica) / 100;

  const valor_incluindo_porcentagem_servico =
    valor_obra_servico * porcentagem_servico;

  const lucro_servico = Number(politica_preco?.lucro_servico_politica) / 100;
  const encargos_servico =
    Number(politica_preco?.encargos_servico_politica) / 100;

  const porcentagem_lucro_encargos_servico =
    1 - (lucro_servico + encargos_servico);

  const markup_servico =
    (valor_obra_servico + valor_incluindo_porcentagem_servico) /
      porcentagem_lucro_encargos_servico -
    (valor_obra_servico + valor_incluindo_porcentagem_servico);

  const valor_servico =
    valor_obra_servico + valor_incluindo_porcentagem_servico + markup_servico;

  const valor_total_servico = valor_kit + valor_servico;
  return {
    valor_fixo_servico,
    obra_por_placa_servico,
    qtd_modulos,
    qtd_ucs,
    valor_obra_por_placa,
    potencia_sistema,
    obra_por_potencia_servico,
    valor_obra_por_potencia,
    valor_obra_servico,
    porcentagem_servico,
    valor_incluindo_porcentagem_servico,
    lucro_servico,
    encargos_servico,
    porcentagem_lucro_encargos_servico,
    markup_servico,
    valor_servico,
    valor_total_servico,
  };
}

export async function obterCustosExtras(
  data: any,
  savePoliticaFunction: (politica_preco: any) => void,
) {
  const loja = data.loja;
  return new Promise<any[]>((resolve, reject) => {
    obterPoliticaPreco({ ...data, loja: loja.id_loja })
      .then(async (res) => {
        if (!res) {
          toast.warning("Não foi encontrada política de preço");
          reject([]);
        }
        savePoliticaFunction(res);
        const valorKit = Number(data.valor_kit);
        const valoresProduto = calcularValoresProduto({
          valor_kit: valorKit,
          politica_preco: res,
        });

        const valoresServico = calcularValoresServico({
          valor_kit: valorKit,
          data,
          politica_preco: res,
        });

        return listarCustosExtras({ ...data, id_loja: loja.id_loja })
          .then((res) => {
            resolve(
              res
                .filter((custoExtra: any) => custoExtra.status_custo_extra == 1)
                .map((custoExtra: any) => {
                  let value = 0;
                  switch (custoExtra.metodo_custo_extra) {
                    case "2":
                    case "1":
                    case "6":
                      value = Number(
                        custoExtra.tabelaPrecos?.qtd_custo_extra_tabela,
                      );
                      break;

                    case "1":
                      value =
                        Number(
                          custoExtra.tabelaPrecos?.qtd_custo_extra_tabela,
                        ) * valoresServico.qtd_modulos;
                      break;

                    case "3":
                      value = Number(custoExtra.qtd_custo_extra);
                      break;

                    case "4":
                      switch (custoExtra.formula_custo_extra) {
                        case "1":
                          value = 1 * Number(custoExtra.qtd_custo_extra);
                          break;

                        case "2":
                          value =
                            Math.ceil(
                              valoresServico.qtd_modulos /
                                (Number(loja.modulosDia_loja) /
                                  Number(loja.instaladoresDia_loja)),
                            ) * Number(custoExtra.qtd_custo_extra);
                          break;
                        case "3":
                          value =
                            valoresServico.qtd_modulos *
                            Number(custoExtra.qtd_custo_extra);
                          break;

                        case "4":
                          value =
                            valoresServico.potencia_sistema *
                            Number(custoExtra.qtd_custo_extra);
                          break;

                        case "5":
                          value =
                            valoresServico.qtd_ucs *
                            Number(custoExtra.qtd_custo_extra);
                          break;

                        default:
                          break;
                      }
                      break;

                    case "5":
                      switch (custoExtra.percentualDe_custo_extra) {
                        case "1":
                          value =
                            valorKit * Number(custoExtra.qtd_custo_extra / 100);
                          break;

                        case "2":
                          value =
                            valoresProduto.valor_produto *
                            Number(custoExtra.qtd_custo_extra / 100);
                          break;

                        case "3":
                          value =
                            valoresServico.valor_servico *
                            Number(custoExtra.qtd_custo_extra / 100);
                          break;

                        default:
                          break;
                      }
                      break;

                    default:
                      break;
                  }
                  let value_digitado = Number(
                    custoExtra.tipo_custo_extra == "1"
                      ? "0"
                      : custoExtra.metodo_custo_extra == "3" ||
                          custoExtra.metodo_custo_extra == "4" ||
                          custoExtra.metodo_custo_extra == "5"
                        ? custoExtra.qtd_custo_extra
                        : "1.00",
                  );

                  // DESLOCAMENTO: quando a proposta exige a cobrança, o custo
                  // extra já vem MARCADO e com os KMs sugeridos (Distância
                  // Aproximada da Loja x 2, ida e volta). O usuário pode
                  // desmarcar ou alterar a quantidade.
                  return aplicarSugestaoDeslocamento(
                    {
                      ...custoExtra,
                      isChecked: custoExtra.tipo_custo_extra == "2",
                      // loja,
                      modulosDia_loja: Number(loja.modulosDia_loja),
                      instaladoresDia_loja: Number(loja.instaladoresDia_loja),
                      valorKit,
                      valoresProduto,
                      valoresServico,
                      value_digitado,
                      value,
                    },
                    data.parametroDeslocamento,
                    data.distanciaLoja_coleta,
                  );
                }),
            );
          })
          .catch((err) => {
            toast.error("Erro ao Obter Custos Extras");
            reject([]);
          });
      })
      .catch((err) => {
        toast.error("Erro ao Obter a política de preço");
        reject([]);
      });
  });
}
