"use client";

import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import Container from "@/components/Forms/Container";
import Input from "@/components/Forms/Input";
import InputGroup from "@/components/Forms/InputGroup";
import InputSelectComponent from "@/components/Forms/InputSelect";
import ReactTable from "@/components/ReactTable/ReactTable";
import { Button } from "@/components/ui/button";
import { cadastrarMeta } from "@/requests/CRM/Metas/cadastrarMetas";
import { deletarMetas } from "@/requests/CRM/Metas/deletarMetas";
import { editarMeta } from "@/requests/CRM/Metas/editarMetas";
import {
  cancelarMeta,
  finalizarMeta,
} from "@/requests/CRM/Metas/finalizarMetas";
import {
  gravacaoGraficosMeta,
  listarMetas,
  listarNiveldeMetas,
  listarObjetivosMetas,
} from "@/requests/CRM/Metas/listarMetas";
import { useAuth } from "@/src/contexts/authContext";
import { useScreenContext } from "@/src/contexts/ScreenContext";
import { GetForm } from "@/utils";
import { useCallback, useEffect, useState } from "react";
import { FieldValues } from "react-hook-form";
import {
  MdDelete,
  MdOutlineAssignmentTurnedIn,
  MdOutlineCancel,
} from "react-icons/md";
import { toast } from "react-toastify";
import Swal from "sweetalert2";
import * as yup from "yup";
import FormCadastroMetas from "./FormCadastroMetas";

export const STATUS_META: Record<string, { label: string; className: string }> =
  {
    "1": {
      label: "Planejada",
      className: "bg-[#fdf0c2] text-[#8e4b10] border-[#8e4b10]",
    },
    "2": {
      label: "Em Andamento",
      className: "bg-[#b4dded] text-[#266c94] border-[#266c94]",
    },
    "3": {
      label: "Atingida",
      className: "bg-[#e0facd] text-[#429e12] border-[#429e12]",
    },
    "4": {
      label: "Não Atingida",
      className: "bg-[#ffc0c0] text-[#ff0a0a] border-[#ff0a0a]",
    },
    "5": {
      label: "Cancelada",
      className: "bg-[#e4e4e7] text-[#52525b] border-[#52525b]",
    },
  };

const PoliticaMetas = ({ disabledFields, children, ...rest }: any) => {
  const [yupSchema, setYupSchema] = useState<
    yup.ObjectSchema<{}, yup.AnyObject, {}, "">
  >(yup.object().shape({}));
  const { handleSubmit, ...form } = GetForm(yupSchema, setYupSchema);
  const [filtroPeriodo, setFiltroPeriodo] = useState<string | null>(null);
  const [filtroObjetivo, setFiltroObjetivo] = useState<string | null>(null);
  const [filtroNivel, setFiltroNivel] = useState<string | null>(null);
  const [filtroDataInicio, setFiltroDataInicio] = useState<string | null>(null);
  const [filtroDataFim, setFiltroDataFim] = useState<string | null>(null);
  const [filtroStatus, setFiltroStatus] = useState<string | null>(null);

  const { isMobile } = useScreenContext();
  const [metas, setMetas] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [openModalEdit, setOpenModalEdit] = useState(false);
  const [objetivoMeta, setObjetivosMeta] = useState<any[]>([]);
  const [openModalCadMetas, setOpenModalCadMetas] = useState(false);
  const [relistarMetas, setRelistarMetas] = useState<any>(0);
  const [selectedMeta, setSelectedMeta] = useState<any>([]);
  const [defaultValues, setDefaultValue] = useState<any[]>([]);
  const { valuesSession, usuario, perfil } = useAuth();
  const { session } = valuesSession();
  const [metasOriginais, setMetasOriginais] = useState<any[]>([]);

  const handleFinalizarMeta = async (meta: any) => {
    const id = meta.id_meta_politica;

    const result = await Swal.fire({
      title: "Finalizar Meta?",
      html: `Deseja finalizar a meta <b>${meta.nome_meta_politica}</b> e gravar o resultado?`,
      icon: "question",
      showCancelButton: true,
      confirmButtonText: "Finalizar",
      confirmButtonColor: "#429e12",
      cancelButtonText: "Voltar",
      cancelButtonColor: "#3085d6",
    });
    if (!result.isConfirmed) return false;

    setIsLoading(true);
    try {
      const res: any = await finalizarMeta({
        id_meta_politica: id,
        id_usuario: session.id_usuario,
      });
      if (res?.message) toast.success(res.message);
      setRelistarMetas((prev: any) => prev + 1);
      return true;
    } finally {
      setIsLoading(false);
    }
  };

  const handleCancelarMeta = async (meta: any) => {
    const result = await Swal.fire({
      title: "Cancelar Meta?",
      html: `Deseja cancelar a meta <b>${meta.nome_meta_politica}</b>?`,
      icon: "warning",
      showCancelButton: true,
      confirmButtonText: "Sim, cancelar",
      confirmButtonColor: "#d33",
      cancelButtonText: "Voltar",
      cancelButtonColor: "#3085d6",
    });
    if (!result.isConfirmed) return;

    setIsLoading(true);
    cancelarMeta({
      id_meta_politica: meta.id_meta_politica,
      id_usuario: session.id_usuario,
    })
      .then((res: any) => {
        if (res?.message) toast.success(res.message);
        setRelistarMetas((prev: any) => prev + 1);
      })
      .finally(() => setIsLoading(false));
  };

  async function onSubmitFunction(data: FieldValues) {
    const existingMetas = await listarMetas();
    const metaExists = existingMetas.some(
      (meta: any) =>
        meta.nome_meta_politica === data.nome_meta_politica &&
        meta.periodo_meta_politica === data.periodo_meta_politica,
    );

    if (metaExists) {
      toast.error("Meta já cadastrada!");
      return;
    }

    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) {
      return toast.error(
        "O valor máximo dos campos Limite Crítico e Limite Aceitável é 99%, corrija os valores.",
      );
      // return;
    }

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

    data["id_usuario"] = session.id_usuario;

    // Item 01: o ReactTable só relista o GRID quando esta promise resolve, então
    // ela precisa englobar a gravação — antes retornava antes do fim do POST e o
    // GRID recarregava sem a política recém-criada.
    setIsLoading(true);
    try {
      await cadastrarMeta(data);
      setOpenModalCadMetas(false);
    } finally {
      setIsLoading(false);
    }
  }

  const editMeta = async (data: any) => {
    data["id_meta_politica"] = data.id_meta_politica;
    data["id_usuario"] = session.id_usuario;

    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 01: o ReactTable relista o GRID quando esta promise resolve, então
    // ela precisa englobar a gravação (antes retornava antes do fim do POST e o
    // GRID recarregava com os dados antigos).
    setIsLoading(true);
    try {
      await editarMeta(data);
      await gravacaoGraficosMeta({
        ...data,
        id_meta_politica_dashboard_meta: data.id_meta_politica,
        tipo_grafico_dashboard_meta: "Barra",
      });
      setOpenModalEdit(false);
    } finally {
      setIsLoading(false);
    }
  };

  // Item 01: a relistagem feita pelo ReactTable depois de salvar também
  // atualiza o estado da página (base dos filtros), evitando uma segunda
  // chamada à listagem — que é custosa por recalcular todas as metas.
  const listarMetasSincronizado = useCallback(async () => {
    const res = await listarMetas();
    setMetas(res);
    setMetasOriginais(res);
    return res;
  }, []);

  useEffect(() => {
    // O fechamento das metas vencidas foi transferido para o programa
    // "Finalizar Metas Em Andamento" (CXESCRM024).
    listarMetas().then((res) => {
      setMetas(res);
      setMetasOriginais(res);
    });
  }, [relistarMetas]);
  const [nivelMeta, setNivelMeta] = useState<any>([]);
  useEffect(() => {
    if (selectedMeta) {
      const metaEncontrada = metas.find(
        (meta) => meta.id_meta_politica === selectedMeta,
      );
      setDefaultValue(metaEncontrada);
    }
  }, [selectedMeta, metas]);

  const periodo = [
    { label: "Semanal", value: "1" },
    { label: "Quinzenal", value: "2" },
    { label: "Mensal", value: "3" },
    { label: "Trimestral", value: "4" },
    { label: "Semestral", value: "5" },
    { label: "Anual", value: "6" },
  ];

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

  const getPeriodoLabel = (value: any) => {
    const item = periodo.find((periodo) => periodo.value == value);
    return item ? item.label : "";
  };

  const handleDeleteMetas = async (meta: any) => {
    Swal.fire({
      title: "Excluir " + meta.nome_meta_politica,
      text: "Deseja excluir a meta selecionada?",
      icon: "warning",
      showCancelButton: true,
      confirmButtonText: "Sim",
      confirmButtonColor: "#d33",
      cancelButtonText: "Cancelar",
      cancelButtonColor: "#3085d6",
    }).then((result: any) => {
      if (result.isConfirmed) {
        meta["id_usuario"] = session.id_usuario;
        deletarMetas(meta).then(() => {
          setRelistarMetas(relistarMetas + 1);
        });
      }
    });
  };
  // Itens 08 e 09: o valor objetivo, a Meta e o Realizado seguem o tipo do
  // objetivo (0 = número, 1 = monetário, 2 = percentual).
  const formatarPorObjetivo = (valor: any, tipoObjetivo: any): string => {
    const numero = Number(valor || 0);
    switch (Number(tipoObjetivo)) {
      case 1:
        return numero.toLocaleString("pt-BR", {
          style: "currency",
          currency: "BRL",
        });
      case 2:
        return `${numero.toLocaleString("pt-BR", {
          maximumFractionDigits: 2,
        })}%`;
      default:
        return numero.toLocaleString("pt-BR", { maximumFractionDigits: 2 });
    }
  };

  const formatFunction = (data: any) => {
    return data.map((item: any) => {
      const status = String(item.status_meta_politica);
      const statusInfo = STATUS_META[status] ?? STATUS_META["2"];

      // Lido antes de o objetivo virar nome logo abaixo
      const tipoObjetivo = objetivoMeta.find(
        (a: any) => a.id_objetivo_meta === item["objetivo_meta_politica"],
      )?.tipo_objetivo_meta;

      // Preserva valores brutos para a lógica de finalização/cancelamento
      item["status_raw"] = status;
      item["dataFinal_raw"] = item["dataFinal_meta_politica"];

      item["periodo_meta_politica"] =
        periodo.find((a: any) => a.value === item["periodo_meta_politica"])
          ?.label || item["periodo_meta_politica"];

      item["objetivo_meta_politica"] =
        objetivoMeta.find(
          (a: any) => a.id_objetivo_meta === item["objetivo_meta_politica"],
        )?.nome_objetivo_meta || item["objetivo_meta_politica"];
      // Somente valores primitivos no grid (JSX aqui vira "[object Object]");
      // a estilização fica no `cell` da coluna
      item["status_meta_politica"] = statusInfo.label;

      const realizado = item["realizado_meta_politica"];
      const percentual = item["percentual_meta_politica"];

      // Item 08: Qtde do Nível é o número de registros relacionados na política
      // (o "(4)" do cadastro) e a Meta é Qtde do Nível x Valor Objetivo.
      const qtdeNivel = Number(item["quantidadeNivel_meta_politica"]) || 1;
      const valorObjetivo = Number(item["valorObjetivo_meta_politica"]) || 0;
      item["quantidadeNivel_fmt"] = qtdeNivel.toLocaleString("pt-BR");
      item["valorObjetivo_fmt"] = formatarPorObjetivo(
        valorObjetivo,
        tipoObjetivo,
      );
      item["meta_fmt"] = formatarPorObjetivo(
        Number(item["metaTotal_meta_politica"]) || valorObjetivo * qtdeNivel,
        tipoObjetivo,
      );

      item["realizado_fmt"] =
        realizado === null || realizado === undefined
          ? "-"
          : formatarPorObjetivo(realizado, tipoObjetivo);
      item["percentual_fmt"] =
        percentual === null || percentual === undefined
          ? "-"
          : `${Number(percentual).toLocaleString("pt-BR", {
              maximumFractionDigits: 1,
            })}%`;

      item["nivel_meta_politica"] = nivelMeta.find(
        (a: any) => a.id_nivel_meta === item["nivel_meta_politica"],
      )?.nome_nivel_meta;
      item["dataInicial_meta_politica"] = formatarDataBrasileira(
        item["dataInicial_meta_politica"],
      );
      item["dataFinal_meta_politica"] = formatarDataBrasileira(
        item["dataFinal_meta_politica"],
      );

      return item;
    });
  };
  const formatarDataBrasileira = (data: string): string => {
    if (!data) return "";

    const [ano, mes, dia] = data.split("-");
    return `${dia}/${mes}/${ano}`;
  };
  const columns = [
    {
      header: "ID",
      accessorKey: "id_meta_politica",
    },
    {
      header: "Status",
      accessorKey: "status_meta_politica",
      cell: ({ row }: any) => {
        const statusInfo =
          STATUS_META[String(row.original.status_raw)] ?? STATUS_META["2"];
        return (
          <span
            className={`justify-center text-center ${statusInfo.className} border flex items-center px-2 py-0.5 font-semibold text-sm rounded-full`}
          >
            {statusInfo.label}
          </span>
        );
      },
    },
    {
      header: "Nome",
      accessorKey: "nome_meta_politica",
    },
    {
      header: "Objetivo",
      accessorKey: "objetivo_meta_politica",
    },
    {
      header: "Nível",
      accessorKey: "nivel_meta_politica",
    },
    {
      header: "Periodo",
      accessorKey: "periodo_meta_politica",
    },

    {
      header: "Qtde",
      accessorKey: "quantidade_meta_politica",
    },
    {
      header: "Início Meta",
      accessorKey: "dataInicial_meta_politica",
    },
    {
      header: "Fim Meta",
      accessorKey: "dataFinal_meta_politica",
    },
    {
      header: "Valor Objetivo da Meta",
      accessorKey: "valorObjetivo_fmt",
    },
    // Item 08: Qtde do Nível e Meta (Qtde do Nível x Valor Objetivo da Meta)
    {
      header: "Qtde do Nível",
      accessorKey: "quantidadeNivel_fmt",
    },
    {
      header: "Meta",
      accessorKey: "meta_fmt",
    },
    {
      header: "Realizado",
      accessorKey: "realizado_fmt",
    },
    {
      // Item 09: % Atingido = Realizado / Meta
      header: "% Atingido",
      accessorKey: "percentual_fmt",
      cell: ({ row, getValue }: any) => {
        const percentual = row.original.percentual_meta_politica;
        if (percentual === null || percentual === undefined) return "-";
        const cor =
          Number(percentual) >= 100
            ? "text-[#429e12]"
            : Number(percentual) >=
                Number(row.original.limiteAceitavel_meta_politica || 0)
              ? "text-[#266c94]"
              : "text-[#ff0a0a]";
        return (
          <span className={`font-semibold ${cor}`}>{String(getValue())}</span>
        );
      },
    },
    {
      header: "Limíte Crítico (%)",
      accessorKey: "limiteCritico_meta_politica",
    },
    {
      header: "Limíte Aceitável (%)",
      accessorKey: "limiteAceitavel_meta_politica",
    },
  ];
  const aplicarFiltro = () => {
    const metasFiltradas = metasOriginais.filter((meta: any) => {
      const matchPeriodo =
        !filtroPeriodo ||
        filtroPeriodo.length === 0 ||
        filtroPeriodo.includes(meta.periodo_meta_politica);

      const matchStatus =
        !filtroStatus ||
        filtroStatus.length === 0 ||
        filtroStatus.includes(meta.status_meta_politica);

      const matchObjetivo =
        !filtroObjetivo ||
        filtroObjetivo.length === 0 ||
        filtroObjetivo.includes(meta.objetivo_meta_politica);

      const matchNivel =
        !filtroNivel ||
        filtroNivel.length === 0 ||
        filtroNivel.includes(meta.nivel_meta_politica);
      const [anoIni, mesIni, diaIni] = meta.dataInicial_meta_politica
        .split("-")
        .map(Number);
      const inicio = new Date(anoIni, mesIni - 1, diaIni);

      const [ano, mes, dia] = meta.dataFinal_meta_politica
        .split("-")
        .map(Number);
      const fim = new Date(ano, mes - 1, dia);

      const matchDataInicio =
        !filtroDataInicio || inicio >= new Date(filtroDataInicio);
      const matchDataFim = !filtroDataFim || fim <= new Date(filtroDataFim);

      return (
        matchStatus &&
        matchPeriodo &&
        matchObjetivo &&
        matchNivel &&
        matchDataInicio &&
        matchDataFim
      );
    });

    setMetas(metasFiltradas);
  };

  return (
    <>
      <Breadcrumb pageName="Cadastro das Política de Metas" />
      <Container>
        <InputGroup>
          <InputSelectComponent
            label="Período"
            options={periodo}
            isMulti
            onChange={(value: any) =>
              setFiltroPeriodo(value.map((a: any) => a.value))
            }
          />

          <InputSelectComponent
            label="Objetivo"
            options={objetivoMeta.map((a: any) => ({
              label: a.nome_objetivo_meta,
              value: a.id_objetivo_meta,
            }))}
            isMulti
            onChange={(value: any) =>
              setFiltroObjetivo(value.map((a: any) => a.value))
            }
          />

          <InputSelectComponent
            label="Nível"
            options={nivelMeta.map((a: any) => ({
              label: a.nome_nivel_meta,
              value: a.id_nivel_meta,
            }))}
            isMulti
            onChange={(value: any) =>
              setFiltroNivel(value.map((a: any) => a.value))
            }
          />

          <Input
            type="date"
            label="Início da Meta"
            onChange={(e: any) => setFiltroDataInicio(e.target.value)}
          />

          <Input
            type="date"
            label="Fim da Meta"
            onChange={(e: any) => setFiltroDataFim(e.target.value)}
          />
          <InputSelectComponent
            label="Status"
            options={[
              { label: "Planejada", value: "1" },
              { label: "Em Andamento", value: "2" },
              { label: "Atingida", value: "3" },
              { label: "Não Atingida", value: "4" },
              { label: "Cancelada", value: "5" },
            ]}
            isMulti
            onChange={(value: any) => {
              const valores = value.map((a: any) => a.value).flat();
              setFiltroStatus(valores);
            }}
          />
        </InputGroup>
        <InputGroup align="center">
          <Button
            className="px-9 text-sm bg-success hover:bg-success hover:bg-opacity-90"
            onClick={aplicarFiltro}
          >
            Filtrar
          </Button>
        </InputGroup>
        <ReactTable
          pageName={"Politica de Metas"}
          columns={columns}
          listFunction={listarMetasSincronizado}
          formatFunction={formatFunction}
          canEdit
          createFunction={onSubmitFunction}
          editFunction={editMeta}
          Form={FormCadastroMetas}
          deleteFunction={handleDeleteMetas}
          data={metas}
          idCol="id_meta_politica"
          canDelete
          actionButtons={(
            data: any,
            updateTable: any,
            setIsLoading: any,
            { idCol, pageName, editFunction }: any,
          ) => {
            const buttons = [];
            const statusRow = String(data?.status_raw);
            const encerrada = statusRow === "3" || statusRow === "4";
            const cancelada = statusRow === "5";

            // Finalizar: disponível enquanto a meta estiver Planejada/Em Andamento
            if (!encerrada && !cancelada) {
              buttons.push({
                className: `navButton bg-success text-white`,
                title: "Finalizar meta",
                onClick: () => handleFinalizarMeta(data),
                content: <MdOutlineAssignmentTurnedIn />,
              });
            }

            // Cancelar: disponível enquanto não estiver encerrada nem cancelada
            if (!encerrada && !cancelada) {
              buttons.push({
                className: `navButton bg-warning text-white`,
                title: "Cancelar meta",
                onClick: () => handleCancelarMeta(data),
                content: <MdOutlineCancel />,
              });
            }

            buttons.push({
              className: `navButton  bg-historicoNotas text-white`,
              onClick: (e: any) => {
                const rowData: any = data;
                const newData: any = {};
                newData[idCol] = rowData[idCol];

                handleDeleteMetas(rowData);
              },
              content: <MdDelete />,
            });
            return buttons;
          }}
        />
      </Container>
    </>
  );
};

export default PoliticaMetas;
