import Button from "@/components/Forms/Button";
import Input from "@/components/Forms/Input";
import InputGroup from "@/components/Forms/InputGroup";
import InputSelectComponent from "@/components/Forms/InputSelect";
import { listarUsuarios } from "@/requests/CRM/Dashboard/listarDashboard";
import {
  listarNiveldeMetas,
  listarObjetivosMetas,
  listarPeriodosMetas,
} from "@/requests/CRM/Metas/listarMetas";
import { listarLojas } from "@/requests/CRUD/Lojas/listarLojas";
import { listarPerfis } from "@/requests/CRUD/Perfil/listarPerfis";
import { listarTiposNegocios } from "@/requests/CRUD/TiposNegocios/listarTiposNegocios";
import { GetForm } from "@/utils";
import { useEffect, useState } from "react";
import { toast } from "react-toastify";
import * as yup from "yup";

// Item 10: aviso do campo "Valor Objetivo da Meta"
const AVISO_VALOR_OBJETIVO =
  "ATENÇÃO!! O valor informado aqui, refere-se a quantidade ou valor desejado de forma individual do Nivel da Meta cadastrado, ou seja, se for por USUÁRIO, cada usuário relacionado deverá atingir em cada período este valor.";

// Item 11: o campo é digitado formatado (R$ 1.234,56 / 12,50% / 1.234) e o
// back-end grava um número, então o valor volta para o formato numérico antes
// do envio.
export const valorObjetivoNumerico = (valor: any): string => {
  if (valor === null || valor === undefined) return "";

  const texto = String(valor)
    .replace(/[^\d,.-]/g, "")
    .trim();
  if (!texto) return "";

  const numero = Number(texto.replace(/\./g, "").replace(",", "."));
  return isNaN(numero) ? "" : String(numero);
};

const FormCadastroMetas = ({
  defaultValues,
  onSubmitFunction,
  isLoading,
  ...rest
}: any) => {
  const [yupSchema, setYupSchema] = useState<
    yup.ObjectSchema<{}, yup.AnyObject, {}, "">
  >(yup.object().shape({}));
  const { handleSubmit, ...form } = GetForm(yupSchema, setYupSchema);
  const [sugerirEdicao, setSugerirEdicao] = useState(true);

  const [selectedObjetivoTipo, setSelectedObjetivoTipo] = useState<number>(0);
  const [validadeLabel, setValidadeLabel] = useState<string>("Quantidade ");
  const [nivelSelecionado, setNivelSelecionado] = useState<number>(
    defaultValues?.nivel_meta_politica || 0,
  );
  const [inicioMeta, setInicioMeta] = useState<string>(
    defaultValues["dataInicial_meta_politica"],
  );
  const [selectedPeriodo, setSelectedPeriodo] = useState<string>(
    defaultValues["periodo_meta_politica"],
  );
  const [limiteAceitavel, setLimiteAceitavel] = useState<number>(0);
  const [limiteCritico, setLimiteCritico] = useState<number>(0);
  const [objetivoMeta, setObjetivosMeta] = useState<any[]>([]);
  const [tiposNegocio, setTiposNegocio] = useState<any[]>([]);
  const [validadeMeta, setValidadeMeta] = useState<number>();
  const [periodoMeta, setPeriodosMeta] = useState<any[]>([]);
  const [nivelMeta, setNivelMeta] = useState<any[]>([]);
  const [usuarios, setUsuarios] = useState<any[]>([]);
  const [perfils, setPerfils] = useState<any[]>([]);
  const [lojas, setLojas] = useState<any[]>([]);

  const handlePeriodoChange = (value: string) => {
    setSelectedPeriodo(value);
    switch (value) {
      case "1":
        setValidadeLabel("Quantidade de semanas");
        break;
      case "2":
        setValidadeLabel("Quantidade de Quinzenas");
        break;
      case "3":
        setValidadeLabel("Quantidade de Meses");
        break;
      case "4":
        setValidadeLabel("Quantidade de Trimestres");
        break;
      case "5":
        setValidadeLabel("Quantidade de Semestres");
        break;
      case "6":
        setValidadeLabel("Quantidade de Anos");
        break;
      default:
        setValidadeLabel("Validade Meta");
        break;
    }
  };
  useEffect(() => {
    if (defaultValues?.valorObjetivo_meta_politica) {
      let formattedValue = defaultValues.valorObjetivo_meta_politica;

      switch (Number(selectedObjetivoTipo)) {
        case 0: // Numérico
          formattedValue = Number(formattedValue).toLocaleString("pt-BR", {
            maximumFractionDigits: 0,
          });
          break;
        case 1: // Monetário
          // Item 11: toLocaleString pt-BR já devolve "1.234,56"; o replace
          // anterior trocava o separador de milhar por vírgula ("1,234,56").
          formattedValue = Number(formattedValue).toLocaleString("pt-BR", {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          });
          break;
        case 2: // Porcentagem
          formattedValue =
            `${Number(formattedValue).toLocaleString("pt-BR", {
              minimumFractionDigits: 2,
              maximumFractionDigits: 2,
            })}` + "%";
          break;
      }

      form.setValue("valorObjetivo_meta_politica", formattedValue);
    }
  }, [selectedObjetivoTipo]);

  // Item 11: na edição o tipo do objetivo (numérico / monetário / percentual)
  // precisa ser conhecido já na abertura, senão o campo abre sem a máscara de
  // R$ da meta gravada.
  useEffect(() => {
    const idObjetivo = defaultValues?.objetivo_meta_politica;
    if (!idObjetivo || objetivoMeta.length === 0) return;

    const objetivo = objetivoMeta.find(
      (obj: any) => String(obj.id_objetivo_meta) === String(idObjetivo),
    );
    setSelectedObjetivoTipo(Number(objetivo?.tipo_objetivo_meta) || 0);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [objetivoMeta]);
  useEffect(() => {
    if (defaultValues && defaultValues["dataFinal_meta_politica"]) {
      form.setValue(
        "dataFinal_meta_politica",
        defaultValues["dataFinal_meta_politica"],
      );
    }
  }, []);
  const handleValidadeChange = (value: string) => {
    setValidadeMeta(Number(value));
  };

  const handleInicioMetaChange = (value: string) => {
    setInicioMeta(value);
  };

  const handleNivelChange = (value: any) => {
    setNivelSelecionado(Number(value));
  };

  const handleLimiteCriticoChange = (value: string) => {
    let numValue = parseInt(value);

    if (numValue > 100) {
      form.setValue("limiteCritico_meta_politica", 99);
      numValue = 99;
    }

    setLimiteCritico(numValue);

    if (numValue == 99) {
      form.setValue("limiteAceitavel_meta_politica", "-", {
        shouldDirty: true,
      });
    }
  };

  const handleLimiteAceitavelChange = (value: string) => {
    let numValue = parseInt(value);

    if (numValue > 100) {
      form.setValue("limiteAceitavel_meta_politica", 99);
      numValue = 99;
    }

    setLimiteAceitavel(numValue);
  };
  function formatDateToLocalISO(date: Date) {
    const tzOffset = date.getTimezoneOffset() * 60000; // offset in ms
    const localISO = new Date(date.getTime() - tzOffset)
      .toISOString()
      .split("T")[0];
    return localISO;
  }

  const calcularFimMeta = () => {
    if (inicioMeta && validadeMeta && selectedPeriodo) {
      const [ano, mes, dia] = inicioMeta.split("-").map(Number);
      const inicio = new Date(ano, mes - 1, dia); // mês começa do zero

      let fim: Date;

      switch (selectedPeriodo) {
        case "1": // Semanal
          fim = new Date(
            inicio.setDate(inicio.getDate() + validadeMeta * 7 - 1),
          );
          break;
        case "2": // Quinzenal
          fim = new Date(
            inicio.setDate(inicio.getDate() + validadeMeta * 15 - 1),
          );
          break;
        case "3": // Mensal
          const dataFimCalculada = new Date(inicio);

          dataFimCalculada.setMonth(dataFimCalculada.getMonth() + validadeMeta);

          dataFimCalculada.setDate(dataFimCalculada.getDate() - 1);

          fim = dataFimCalculada;

          break;
        case "4": // Trimestral
          const dataFimTriCalculada = new Date(inicio);
          dataFimTriCalculada.setMonth(
            dataFimTriCalculada.getMonth() + validadeMeta * 3,
          );
          dataFimTriCalculada.setDate(dataFimTriCalculada.getDate() - 1);
          fim = dataFimTriCalculada;
          break;
        case "5": // Semestral
          const dataFimSemCalculada = new Date(inicio);
          dataFimSemCalculada.setMonth(
            dataFimSemCalculada.getMonth() + validadeMeta * 6,
          );
          dataFimSemCalculada.setDate(dataFimSemCalculada.getDate() - 1);
          fim = dataFimSemCalculada;
          // fim = new Date(inicio.setMonth(inicio.getMonth() + validadeMeta * 6));
          break;
        case "6": // Anual
          const dataFimAnualCalculada = new Date(inicio);
          dataFimAnualCalculada.setFullYear(
            inicio.getFullYear() + validadeMeta,
          );
          dataFimAnualCalculada.setDate(dataFimAnualCalculada.getDate() - 1);
          fim = dataFimAnualCalculada;
          break;
        default:
          return;
      }
      form.setValue("dataFinal_meta_politica", formatDateToLocalISO(fim));
    }
  };

  useEffect(() => {
    listarPeriodosMetas().then((res) => {
      setPeriodosMeta(res);
    });
  }, []);

  useEffect(() => {
    listarObjetivosMetas().then((res) => {
      setObjetivosMeta(res);
    });
  }, []);

  useEffect(() => {
    listarNiveldeMetas().then((res) => {
      setNivelMeta(res);
    });
    listarLojas().then((res) => setLojas(res));
    listarTiposNegocios().then((res) => setTiposNegocio(res));
    listarPerfis().then((res) => setPerfils(res));
    listarUsuarios().then((res) => setUsuarios(res));
  }, []);
  const envio = (data: any) => {
    const limiteCritico = parseInt(data.limiteCritico_meta_politica, 10);
    const limiteAceitavel = parseInt(data.limiteAceitavel_meta_politica, 10);

    // Validação dos campos

    if (limiteCritico > 99 || limiteAceitavel > 99) {
      toast.error(
        "O valor máximo dos campos Limite Crítico e Limite Aceitável é 99%, corrija os valores."
      );
      return;
    }

    if (
      Number(data.limiteAceitavel_meta_politica) <=
      Number(data.limiteCritico_meta_politica)
    ) {
      toast.error("O valor aceitável deve ser maior que o Crítico!");
      return;
    }

    // Item 11: "R$ 1.234,56" -> "1234.56"
    data.valorObjetivo_meta_politica = valorObjetivoNumerico(
      data.valorObjetivo_meta_politica,
    );

    return onSubmitFunction(data);
  };
  useEffect(() => {
    calcularFimMeta();
  }, [inicioMeta, validadeMeta, selectedPeriodo]);
  useEffect(() => {
    if (!sugerirEdicao) return;

    const nome = form.watch("nome_meta_politica" as any);
    const nivel = form.watch("nivel_meta_politica" as any) as any;
    const periodo = form.watch("periodo_meta_politica" as any) as any;

    const descricaoGerada = gerarDescricao(nome, nivel?.label, periodo?.label);

    if (descricaoGerada) {
      form.setValue("descricao_meta_politica", descricaoGerada);
    }
  }, [
    form.watch("nome_meta_politica" as any),
    form.watch("nivel_meta_politica" as any),
    form.watch("periodo_meta_politica" as any),
    sugerirEdicao,
  ]);
  function gerarDescricao(nome: any, nivel: any, periodo: any) {
    if (!nome || !nivel || !periodo) return "";

    return `Meta ${nome} de ${nivel} com o período ${periodo}`;
  }
  const lojasSelecionadas = form.watch("lojas_meta_politica" as any) || [];
  const tiposNegocioSelecionados =
    form.watch("tiposNegocio_meta_politica" as any) || [];
  const perfisSelecionados = form.watch("perfis_meta_politica" as any) || [];
  const usuariosSelecionados = form.watch("usuarios_meta_politica" as any) || [];
  return (
    <form onSubmit={handleSubmit(envio)}>
      <InputGroup className=" mb-5">
        <Input
          name="nome_meta_politica"
          formulario={form}
          label="Nome da Meta"
          width="xl:w-1/2"
          required
          error="Preencha esse campo"
          defaultValue={defaultValues && defaultValues["nome_meta_politica"]}
        />
        <InputSelectComponent
          label="Período Meta"
          name="periodo_meta_politica"
          formulario={form}
          width="xl:w-1/2"
          options={periodoMeta.map((e) => ({
            label: e.nome_metas_periodo,
            value: e.id_metas_periodo,
          }))}
          value={selectedPeriodo}
          onChange={(e: any) => {
            const value = e?.target?.value || e?.value;
            handlePeriodoChange(value);
            if (["3", "4", "5", "6"].includes(value)) {
              const dataInici =
                form.control._formValues["dataInicial_meta_politica"];
              if (dataInici) {
                const [year] = dataInici.split("-").map(Number);
                let selectedDate;

                if (value === "6") {
                  // Sempre 01/01 do ano selecionado
                  selectedDate = new Date(year, 0, 1);
                } else {
                  // Primeiro dia do mês selecionado
                  const [, month] = dataInici.split("-").map(Number);
                  selectedDate = new Date(year, month - 1, 1);
                }

                form.setValue(
                  "dataInicial_meta_politica",
                  formatDateToLocalISO(selectedDate),
                );
              }
            }
          }}
          required
          defaultValue={defaultValues && defaultValues["periodo_meta_politica"]}
          error="Preencha esse campo"
        />
      </InputGroup>

      <InputGroup>
        <Input
          name="quantidade_meta_politica"
          formulario={form}
          width="xl:w-1/2"
          label={validadeLabel}
          mascara="numerico"
          required
          error="Preencha esse campo"
          defaultValue={
            defaultValues && defaultValues["quantidade_meta_politica"]
          }
          onChange={(e) => handleValidadeChange(e.target.value)}
        />

        <Input
          name="dataInicial_meta_politica"
          formulario={form}
          width="xl:w-1/2"
          label="Início da Meta"
          onChange={(e) => {
            if (["3", "4", "5", "6"].includes(selectedPeriodo)) {
              const [year] = e.target.value.split("-").map(Number);
              let selectedDate;

              if (selectedPeriodo === "6") {
                // Sempre 01/01 do ano selecionado
                selectedDate = new Date(year, 0, 1);
              } else {
                // Primeiro dia do mês selecionado
                const [, month] = e.target.value.split("-").map(Number);
                selectedDate = new Date(year, month - 1, 1);
              }

              form.setValue(
                "dataInicial_meta_politica",
                formatDateToLocalISO(selectedDate),
              );
            }

            handleInicioMetaChange(e.target.value);
          }}
          error="Preencha esse campo"
          defaultValue={
            defaultValues && defaultValues["dataInicial_meta_politica"]
          }
          // onChange={(e) => handleInicioMetaChange(e.target.value)}
          disabled={!selectedPeriodo || !validadeMeta}
          type="date"
        />

        <Input
          name="dataFinal_meta_politica"
          formulario={form}
          width="xl:w-1/2"
          label="Fim da Meta"
          error="Preencha esse campo"
          disabled
          type="date"
        />
      </InputGroup>

      <InputGroup>
        <InputSelectComponent
          label="Objetivo da Meta"
          name="objetivo_meta_politica"
          formulario={form}
          width="xl:w-1/2"
          options={objetivoMeta.map((e) => ({
            label: e.nome_objetivo_meta,
            value: e.id_objetivo_meta,
          }))}
          onChange={(e: any) => {
            const value = e?.target?.value || e?.value;
            const objetivo = objetivoMeta.find(
              (obj) => obj.id_objetivo_meta === value,
            );
            setSelectedObjetivoTipo(objetivo?.tipo_objetivo_meta || 0);
          }}
          required
          defaultValue={
            defaultValues && defaultValues["objetivo_meta_politica"]
          }
          error="Preencha esse campo"
        />

        <Input
          name="valorObjetivo_meta_politica"
          width="xl:w-1/2"
          formulario={form}
          // Item 10: explica que o valor é individual por registro do nível
          label={
            <span className="flex flex-row items-center gap-1">
              Valor Objetivo da Meta
              <span
                title={AVISO_VALOR_OBJETIVO}
                className="group relative inline-flex h-4 w-4 cursor-help items-center justify-center rounded-full border border-primary text-[10px] font-bold text-primary"
              >
                i
                <span className="pointer-events-none absolute left-0 top-5 z-9999 hidden w-[300px] max-w-[70vw] whitespace-normal rounded-md border border-stroke bg-white p-2 text-xs font-normal text-black shadow-default group-hover:block dark:border-strokedark dark:bg-boxdark dark:text-white">
                  {AVISO_VALOR_OBJETIVO}
                </span>
              </span>
            </span>
          }
          required
          error="Preencha esse campo"
          // Item 11: objetivo de valor usa máscara monetária com prefixo R$
          prefix={Number(selectedObjetivoTipo) === 1 ? "R$" : undefined}
          mascara={
            selectedObjetivoTipo == 0
              ? "numerico"
              : selectedObjetivoTipo == 1
                ? "monetario"
                : selectedObjetivoTipo == 2
                  ? "porcentagem"
                  : "letras"
          }
          defaultValue={
            defaultValues && defaultValues["valorObjetivo_meta_politica"]
          }
        />
      </InputGroup>

      <InputGroup>
        <InputSelectComponent
          label="Nivel da meta"
          width="xl:w-1/2"
          name="nivel_meta_politica"
          formulario={form}
          options={nivelMeta.map((e) => ({
            label: e.nome_nivel_meta,
            value: e.id_nivel_meta,
          }))}
          onChange={(e: any) => {
            const value = e?.target?.value || e?.value;
            handleNivelChange(value);
          }}
          defaultValue={defaultValues && defaultValues["nivel_meta_politica"]}
          required
          error="Preencha esse campo"
        />
        {nivelSelecionado == 1 && (
          <InputSelectComponent
            label={`Selecione as Lojas (${lojasSelecionadas.length})`}
            name="lojas_meta_politica"
            width="xl:w-1/2"
            formulario={form}
            isMulti
            options={[
              { value: String("*"), label: "Todos" },
              ...lojas.map((e) => ({
                label: e.nome_loja,
                value: e.id_loja,
              })),
            ]}
            onChange={(selectedOptions: any) => {
              const hasAllSelected = selectedOptions.some(
                (option: any) => option.value == "*",
              );

              form.setValue(
                "lojas_meta_politica" as never,
                (
                  hasAllSelected
                    ? [{ label: "Todas", value: "*" }]
                    : selectedOptions
                ) as never,
              );
            }}
            required
            error="Preencha esse campo"
            defaultValue={defaultValues?.["lojas_meta_politica"]}
          />
        )}

        {nivelSelecionado == 2 && (
          <InputSelectComponent
            label={`Selecione os Tipos de Negócio (${tiposNegocioSelecionados.length})`}
            name="tiposNegocio_meta_politica"
            width="xl:w-1/2"
            formulario={form}
            isMulti
            options={[
              { value: String("*"), label: "Todos" },
              ...tiposNegocio.map((e) => ({
                label: e.nome_tipo_negocio,
                value: e.id_tipo_negocio,
              })),
            ]}
            onChange={(selectedOptions: any) => {
              const hasAllSelected = selectedOptions.some(
                (option: any) => option.value == "*",
              );

              form.setValue(
                "tiposNegocio_meta_politica" as never,
                (
                  hasAllSelected
                    ? [{ label: "Todos", value: "*" }]
                    : selectedOptions
                ) as never,
              );
            }}
            required
            error="Preencha esse campo"
            defaultValue={defaultValues?.["tiposNegocio_meta_politica"]}
          />
        )}

        {nivelSelecionado == 3 && (
          <InputSelectComponent
            label={`Selecione os Perfis (${perfisSelecionados.length})`}
            name="perfis_meta_politica"
            width="xl:w-1/2"
            formulario={form}
            isMulti
            options={[
              { value: String("*"), label: "Todos" },
              ...perfils.map((e) => ({
                label: e.nome_perfil,
                value: e.id_perfil,
              })),
            ]}
            onChange={(selectedOptions: any) => {
              const hasAllSelected = selectedOptions.some(
                (option: any) => option.value == "*",
              );

              form.setValue(
                "perfis_meta_politica" as never,
                (
                  hasAllSelected
                    ? [{ label: "Todos", value: "*" }]
                    : selectedOptions
                ) as never,
              );
            }}
            required
            error="Preencha esse campo"
            defaultValue={defaultValues?.["perfis_meta_politica"]}
          />
        )}

        {nivelSelecionado == 4 && (
          <InputSelectComponent
            label={`Selecione os Usuários (${usuariosSelecionados.length})`}
            name="usuarios_meta_politica"
            isMulti
            width="xl:w-1/2"
            formulario={form}
            options={[
              { value: String("*"), label: "Todos" },
              ...usuarios.map((e) => ({
                label: e.nome_usuario,
                value: e.id_usuario,
              })),
            ]}
            onChange={(selectedOptions: any) => {
              const hasAllSelected = selectedOptions.some(
                (option: any) => option.value == "*",
              );

              form.setValue(
                "usuarios_meta_politica" as never,
                (
                  hasAllSelected
                    ? [{ label: "Todos", value: "*" }]
                    : selectedOptions
                ) as never,
              );
            }}
            required
            error="Preencha esse campo"
            defaultValue={defaultValues?.["usuarios_meta_politica"]}
          />
        )}
      </InputGroup>
      <InputGroup>
        <Input
          type="checkbox"
          checked={sugerirEdicao}
          label="Sugerir descrição"
          onChange={(e) => {
            setSugerirEdicao(!sugerirEdicao);
          }}
        />
      </InputGroup>
      <InputGroup>
        <Input
          label="Descrição"
          name="descricao_meta_politica"
          formulario={form}
          type="textarea"
          defaultValue={
            defaultValues && defaultValues["descricao_meta_politica"]
          }
          required
          error={"Preencha a Descrição"}
        />
      </InputGroup>
      <div className="mt-4 mb-4 text-center font-black text-lg">
        <p> Limites Percentuais de Atingimento (%) </p>
      </div>

      <InputGroup>
        <Input
          name="limiteCritico_meta_politica"
          formulario={form}
          label="Limite Crítico (%)"
          width="xl:w-1/2"
          required
          error="Preencha esse campo"
          mascara="numero"
          onChange={(e) => handleLimiteCriticoChange(e.target.value)}
          max={100}
          defaultValue={
            defaultValues && defaultValues["limiteCritico_meta_politica"]
          }
        />

        <Input
          name="limiteAceitavel_meta_politica"
          formulario={form}
          width="xl:w-1/2"
          label={"Limite Aceitável (%)"}
          required
          error="Preencha esse campo"
          mascara="numero"
          style={{ display: limiteCritico === 99 ? "none" : "block" }}
          onChange={(e) => handleLimiteAceitavelChange(e.target.value)}
          disabled={limiteCritico == 99}
          max={100}
          defaultValue={
            defaultValues && defaultValues["limiteAceitavel_meta_politica"]
          }
        />
      </InputGroup>

      <div className="flex flex-col justify-center items-center">
        <Button loading={isLoading}>Confirmar</Button>
      </div>
    </form>
  );
};

export default FormCadastroMetas;
