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 {
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { obterCosip } from "@/requests/CRUD/ParametrosComerciais/Cosip/obterCosip";
import { salvarCosip } from "@/requests/CRUD/ParametrosComerciais/Cosip/salvarCosip";
import { useKanbanContext } from "@/src/contexts/kanbanContext";
import {
  FormatFields,
  GetForm,
  getObjectDepth,
  proximoNumero,
  tamanhoDaLacuna,
  validarRanges,
} from "@/utils";
import { Upload, X } from "lucide-react";
import { Fragment, useEffect, useMemo, useState } from "react";
import { RiErrorWarningFill } from "react-icons/ri";
import { toast } from "react-toastify";

export const minRange = "de_consumo_cosip";
export const maxRange = "ate_consumo_cosip";

function SkeletonBlock({ className = "" }: { className?: string }) {
  return (
    <div
      className={`animate-pulse rounded-md bg-slate-200 dark:bg-slate-700 ${className}`}
    />
  );
}

function TableSkeletonRows({
  rows,
  columnsCount,
}: {
  rows: number;
  columnsCount: number;
}) {
  return (
    <>
      {Array.from({ length: rows }).map((_, r) => (
        <TableRow key={`sk-row-${r}`}>
          {Array.from({ length: columnsCount }).map((__, c) => (
            <TableCell className="p-2" key={`sk-cell-${r}-${c}`}>
              <SkeletonBlock className="h-5 w-full" />
            </TableCell>
          ))}
        </TableRow>
      ))}
    </>
  );
}

export default function CosipManager({}: any) {
  const [valuesKey, setValuesKey] = useState(0);
  const [intersecoesRanges, setIntersecoesRanges] = useState<any>({});
  const [tabelaCosip, setTabelaCosip] = useState<any[]>([]);
  const [estadosSelecionados, setEstadosSelecionados] = useState<
    number | string | null
  >(null);
  const [cidadesSelecionadas, setCidadesSelecionadas] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [tabelaCosipGeral, setTabelaCosipGeral] = useState<any[]>([]);
  const [selecionados, setSelecionados] = useState<number[]>([]);
  const [cidadeSelecionadas, setCidadeSelecionadas] = useState<number[]>([]);
  const [alterado, setAlterado] = useState(false);

  const { cidades, estados } = useKanbanContext();
  const formCosip = GetForm();

  const columns = useMemo(
    () => [
      {
        header: `Estado`,
        accessorKey: "__estado_cosip",
        rowSpan: 2,
      },
      {
        header: `Cidade`,
        accessorKey: "__cidade_cosip",
        rowSpan: 2,
      },
      {
        header: `Consumo mensal de (kWh)`,
        accessorKey: minRange,
        rowSpan: 2,
      },
      {
        header: `Consumo mensal até (kWh)`,
        accessorKey: maxRange,
        rowSpan: 2,
      },
      {
        header: "Valor (em R$)",
        columns: [
          {
            header: "Consumidor Residencial",
            accessorKey: "valor_residencial_cosip",
          },
          {
            header: "Consumidor Não Residencial",
            accessorKey: "valor_nao_residencial_cosip",
          },
        ],
      },
    ],
    [],
  );

  const totalLeafColumns = useMemo(() => {
    const flattenLeaves = (cols: any[]): number =>
      cols.reduce((acc, col) => {
        if (col.columns) return acc + flattenLeaves(col.columns);
        return acc + 1;
      }, 0);
    return 2 + flattenLeaves(columns); // +2 = checkbox e ações
  }, [columns]);

  useEffect(() => {
    if (estadosSelecionados) {
      const cidadesDoEstado = cidades
        .filter((cidade: any) => cidade.estado_cidade === estadosSelecionados)
        .map((cidade: any) => ({
          ...cidade,
          label: cidade.nome_cidade,
          value: cidade.id_cidade,
        }));
      formCosip.setValue("cidades", []);
      setCidadesSelecionadas([]);
    }
  }, [estadosSelecionados]);

  useEffect(() => {
    const temCidadeUnica =
      cidadesSelecionadas.length > 0 &&
      !cidadesSelecionadas.some((c: any) => c.value === "*");

    if (temCidadeUnica) {
      setIsLoading(true);
      obterCosip({
        cidade: cidadesSelecionadas.map((a: any) => a.id_cidade).join(","),
      })
        .then((res) => {
          const resultado = res.filter((c: any) => {
            if (estadosSelecionados === "*") return true;
            return c.estado_cidade == estadosSelecionados;
          });
          setTabelaCosip(resultado || []);
          setTabelaCosipGeral(resultado || []);
        })
        .finally(() => setIsLoading(false));
    }

    if (cidadesSelecionadas.some((c: any) => c.value === "*")) {
      setIsLoading(true);

      obterCosip()
        .then((res) => {
          const resultado = res.filter((c: any) => {
            if (estadosSelecionados === "*") return true;
            return c.estado_cidade == estadosSelecionados;
          });
          setTabelaCosip(resultado || []);
          setTabelaCosipGeral(resultado || []);
        })
        .finally(() => setIsLoading(false));
    }
  }, [cidadesSelecionadas]);

  useEffect(() => {
    const ranges = tabelaCosip.map((contribuicao) => [
      Number(contribuicao[minRange]),
      Number(contribuicao[maxRange]),
    ]);
    const intersecoes = validarRanges(ranges);
    setIntersecoesRanges(intersecoes);
  }, [tabelaCosip]);

  return (
    <div className={`flex mt-8 flex-col gap-3`}>
      <div className=" mb-5 w-full flex border items-center  bg-[#fff5ea]  gap-2 px-4 p-4 rounded-md border-[#fcdcaa] shadow-sm">
        <div className="rounded-full p-1 shadow-md bg-[#fef9f6]">
          <RiErrorWarningFill size={20} color="#ffb747" />
        </div>
        <p className="text-black text-sm">
          Selecione <b>Estado</b> e <b>Cidades</b> para trazer as que existem,
          para uma nova contribuição, selecione apenas uma cidade e então clique
          em <b>Nova Contribuição</b>, ao mudar valores clique em <b>Salvar</b>.
          Estes valores serão usados no cálculo de <b>UCS de consumo</b> no
          negócio do cliente.
        </p>
      </div>
      <InputGroup
        align="center"
        className="border rounded-md p-2 pt-5 flex relative flex-col gap-3 min-w-[300px]"
      >
        <span className="absolute -top-3 text-black font-semibold bg-white px-2 ">
          Filtros COSIP
        </span>

        <div className="w-1/4">
          <InputSelectComponent
            name="estados"
            label="Estados"
            formulario={formCosip}
            width="w-full"
            options={[
              {
                label: "Todas",
                value: "*",
              },
              ...estados.map((estado: any) => ({
                ...estado,
                label: `${estado.uf_estado} - ${estado.nome_estado}`,
                value: estado.id_estado,
              })),
            ]}
            onChange={(e: any) => setEstadosSelecionados(e?.value ?? null)}
            disabled={isLoading}
          />
        </div>

        {!!estadosSelecionados && (
          <div className="w-1/4">
            <InputSelectComponent
              name="cidades"
              label="Cidades"
              width="w-full"
              formulario={formCosip}
              options={[
                {
                  label: "Todas",
                  value: "*",
                },
                ...cidades
                  .filter((cidade: any) => {
                    if (estadosSelecionados === "*") return true;
                    return cidade.estado_cidade === estadosSelecionados;
                  })
                  .map((cidade: any) => ({
                    ...cidade,
                    label: cidade.nome_cidade,
                    value: cidade.id_cidade,
                  })),
              ]}
              isMulti
              onChange={(e: any) => setCidadesSelecionadas(e || [])}
              disabled={isLoading}
            />
          </div>
        )}
      </InputGroup>

      <div className="flex-1 relative">
        <div className={`flex flex-row gap-2 justify-between pb-4`}>
          <div className="flex flex-col justify-end">
            <Button
              type="button"
              className="bg-primary"
              disabled={
                isLoading ||
                !(
                  cidadesSelecionadas.length === 1 &&
                  !cidadesSelecionadas.some((c: any) => c.value === "*")
                ) 
                // ||
                // tabelaCosip.some(
                //   (t) => t.cod_cidade_cosip == cidadesSelecionadas[0].value,
                // )
              }
              onClick={() => {
                const cidadeUnica =
                  cidadesSelecionadas.length === 1 &&
                  !cidadesSelecionadas.some((c: any) => c.value === "*");

                if (!cidadeUnica) {
                  toast.error(
                    "Selecione exatamente uma cidade para criar a contribuição.",
                  );
                  return;
                }

                const cidadeId = cidadesSelecionadas[0].id_cidade;

                const rangesAtuais = tabelaCosip.map((registro: any) => [
                  Number(registro[minRange]),
                  Number(registro[maxRange]),
                ]);

                const proximo = proximoNumero(rangesAtuais);
                const lacuna = Math.max(tamanhoDaLacuna(rangesAtuais) - 1, 1);

                const novoRegistroBase = columns.reduce(
                  (acc: any, col: any) => {
                    if (col.columns) {
                      for (let i = 0; i < col.columns.length; i++) {
                        const c = col.columns[i];
                        acc[c.accessorKey] = 0.0;
                      }
                    } else if (col.accessorKey) {
                      acc[col.accessorKey] =
                        col.accessorKey === minRange
                          ? proximo
                          : col.accessorKey === maxRange
                            ? proximo + lacuna
                            : 0.0;
                    }
                    return acc;
                  },
                  {},
                );

                const novoRegistro = {
                  ...novoRegistroBase,
                  cod_cidade_cosip: cidadeId,
                };

                setTabelaCosip((prev: any[]) => [...prev, novoRegistro]);
                setAlterado(true);
                setValuesKey((prev) => prev + 1);
              }}
            >
              Nova Contribuição
            </Button>
          </div>

          <div className="flex gap-5">
            {selecionados.length > 0 && (
              <Button
                type="button"
                className="bg-error text-white flex flex-row gap-1"
                disabled={isLoading}
                onClick={() => {
                  setTabelaCosip((prev) =>
                    prev.filter((_, i) => !selecionados.includes(i)),
                  );
                  setSelecionados([]);
                  setAlterado(true);
                  setValuesKey((prev) => prev + 1);
                }}
              >
                <X /> Excluir Selecionados ({selecionados.length})
              </Button>
            )}
            <Button
              type="button"
              className={`flex flex-row gap-1 ${(!alterado || isLoading) && "cursor-not-allowed"}`}
              disabled={!alterado || isLoading}
              onClick={async () => {
                if (!alterado || isLoading) return;

                try {
                  setIsLoading(true);
                  await salvarCosip({
                    excluidos: cidadeSelecionadas,
                    cidades: (cidadesSelecionadas.some(
                      (cidade) => cidade.value == "*",
                    )
                      ? cidades.filter(
                          (cidade: any) =>
                            !estadosSelecionados ||
                            estadosSelecionados === cidade.estado_cidade,
                        )
                      : cidadesSelecionadas
                    ).map((cidade: any) => cidade.id_cidade),
                    tabelaCosip,
                  }).then(() => setCidadeSelecionadas([]));
                  setAlterado(false);
                  toast.success("COSIP salvo com sucesso!");
                } catch (e) {
                  toast.error("Erro ao salvar COSIP");
                } finally {
                  setIsLoading(false);
                }
              }}
            >
              <div>
                Salvar o COSIP para{" "}
                {cidadesSelecionadas.some((cidade) => cidade.value == "*") ||
                cidadesSelecionadas.length > 1
                  ? "as cidades selecionadas"
                  : "a cidade selecionada"}
              </div>
              <Upload />
            </Button>
          </div>
        </div>

        <div className="h-full overflow-hidden flex flex-col items-center">
          <div
            className="w-full shadow-md max-h-[50vh] overflow-auto flex flex-col items-center"
            aria-busy={isLoading}
          >
            <table className="w-full">
              <TableHeader className="sticky top-[-1px] bg-[#eee] dark:bg-[#141d27] z-9 hover:bg-[#eee] dark:hover:bg-[#1d2a39]">
                <TableRow className="bg-[#eee] dark:bg-[#141d27] z-9 hover:bg-[#eee] dark:hover:bg-[#1d2a39]">
                  <TableHead
                    className="font-bold py-2 px-1 border-b text-center"
                    rowSpan={getObjectDepth(columns)}
                  >
                    <input
                      type="checkbox"
                      disabled={isLoading || tabelaCosip.length === 0}
                      checked={
                        selecionados.length === tabelaCosip.length &&
                        tabelaCosip.length > 0
                      }
                      onChange={(e) => {
                        if (e.target.checked) {
                          setSelecionados(tabelaCosip.map((_, i) => i));
                          setCidadeSelecionadas(
                            tabelaCosip.map((_, i) => _.id_cosip),
                          );
                        } else {
                          setCidadeSelecionadas([]);
                          setSelecionados([]);
                        }
                      }}
                    />
                  </TableHead>
                  <TableHead
                    className="font-bold py-2 px-1 border-b text-center"
                    rowSpan={getObjectDepth(columns)}
                  >
                    Ações
                  </TableHead>
                  {columns.map((col, index) => (
                    <TableHead
                      key={index}
                      className="font-bold py-2 px-4 border-b text-center"
                      rowSpan={col.rowSpan || 1}
                      colSpan={col.columns ? col.columns.length : 1}
                    >
                      {col.header}
                    </TableHead>
                  ))}
                </TableRow>
                <TableRow>
                  {columns.map((col, index) => {
                    if (col.columns) {
                      return col.columns.map((c: any, i: number) => (
                        <TableHead
                          key={`${index}-${i}`}
                          className="font-bold py-2 px-4 border-b text-center"
                        >
                          {c.header}
                        </TableHead>
                      ));
                    }
                    return null;
                  })}
                </TableRow>
              </TableHeader>

              <tbody key={valuesKey}>
                {isLoading ? (
                  <TableSkeletonRows rows={6} columnsCount={totalLeafColumns} />
                ) : (
                  tabelaCosip
                    .sort((a: any, b: any) => {
                      const cidadeA = cidades.find(
                        (c: any) => c.id_cidade === a.cod_cidade_cosip,
                      );
                      const cidadeB = cidades.find(
                        (c: any) => c.id_cidade === b.cod_cidade_cosip,
                      );

                      const estadoA =
                        estados.find(
                          (e: any) => e.id_estado === cidadeA?.estado_cidade,
                        )?.nome_estado || "";
                      const estadoB =
                        estados.find(
                          (e: any) => e.id_estado === cidadeB?.estado_cidade,
                        )?.nome_estado || "";

                      return estadoA.localeCompare(estadoB, "pt", {
                        sensitivity: "base",
                      });
                    })
                    .map((contribuicao: any, indexContribuicao: number) => {
                      const cidadeReq = cidades.find(
                        (c: any) =>
                          c.id_cidade === contribuicao.cod_cidade_cosip,
                      );
                      const cidadeCell = cidadeReq?.nome_cidade;
                      const estadoCell = estados.find(
                        (e: any) => e.id_estado === cidadeReq?.estado_cidade,
                      )?.nome_estado;

                      return (
                        <Fragment key={indexContribuicao}>
                          <TableRow>
                            <TableCell className="text-center">
                              <input
                                type="checkbox"
                                disabled={isLoading}
                                checked={selecionados.includes(
                                  indexContribuicao,
                                )}
                                onChange={(e) => {
                                  if (e.target.checked) {
                                    setSelecionados((prev) => [
                                      ...prev,
                                      indexContribuicao,
                                    ]);
                                    setCidadeSelecionadas((prev) => [
                                      ...prev,
                                      contribuicao.id_cosip,
                                    ]);
                                  } else {
                                    setSelecionados((prev) =>
                                      prev.filter(
                                        (i) => i !== indexContribuicao,
                                      ),
                                    );
                                    setSelecionados((prev) =>
                                      prev.filter(
                                        (i) => i !== contribuicao.id_cosip,
                                      ),
                                    );
                                  }
                                }}
                              />
                            </TableCell>
                            <TableCell>
                              <div className="flex justify-around gap-1">
                                <button
                                  title="Remover"
                                  type="button"
                                  className="navButton bg-error text-white"
                                  disabled={isLoading}
                                  onClick={() => {
                                    setTabelaCosip((prev) => {
                                      const newTabela = [...prev];
                                      newTabela.splice(indexContribuicao, 1);
                                      return newTabela;
                                    });
                                    setAlterado(true);
                                    setCidadeSelecionadas((prev) => [
                                      ...prev,
                                      contribuicao.id_cosip,
                                    ]);
                                    setValuesKey((prev) => prev + 1);
                                  }}
                                >
                                  <X />
                                </button>
                                {/* {(+contribuicao[minRange] >
                                  +contribuicao[maxRange] ||
                                  intersecoesRanges[String(indexContribuicao)]
                                    ?.length > 0) && (
                                  <button
                                    type="button"
                                    className="navButton bg-warning text-white"
                                    onClick={() => {
                                      if (
                                        +contribuicao[minRange] >
                                        +contribuicao[maxRange]j
                                      ) {
                                        toast.error(
                                          `"De" não pode ser maior que "Até"!`
                                        );
                                      }
                                      if (
                                        intersecoesRanges[
                                          String(indexContribuicao)
                                        ]?.length > 0
                                      ) {
                                        toast.error(
                                          `O range faz intersecção com o(s) range(s): ${intersecoesRanges[
                                            String(indexContribuicao)
                                          ]
                                            .map(
                                              (interseccao: number) =>
                                                `${Number(
                                                  tabelaCosip[
                                                    Number(interseccao)
                                                  ][minRange]
                                                ).toFixed(0)} até ${Number(
                                                  tabelaCosip[
                                                    Number(interseccao)
                                                  ][maxRange]
                                                ).toFixed(0)}`
                                            )
                                            .join(", ")}`
                                        );
                                      }
                                    }}
                                  >
                                    <TriangleAlert />
                                  </button>
                                )} */}
                              </div>
                            </TableCell>

                            <TableCell className="p-1 text-center min-w-[120px]">
                              {estadoCell}
                            </TableCell>

                            <TableCell className="p-1 text-center min-w-[160px]">
                              {cidadeCell}
                            </TableCell>

                            {columns.map((col: any, index: number) => {
                              if (
                                col.accessorKey &&
                                !col.accessorKey.startsWith("__")
                              ) {
                                return (
                                  <InputCell
                                    key={`${indexContribuicao}-col-${index}`}
                                    contribuicao={contribuicao}
                                    col={col}
                                    index={index}
                                    onChange={() => setAlterado(true)}
                                    setTabelaCosip={setTabelaCosip}
                                    indexContribuicao={indexContribuicao}
                                    disabled={isLoading}
                                  />
                                );
                              } else if (col.columns) {
                                return col.columns.map((c: any, i: number) => (
                                  <InputCell
                                    key={`${indexContribuicao}-col-${index}-${i}`}
                                    onChange={() => setAlterado(true)}
                                    contribuicao={contribuicao}
                                    col={c}
                                    index={index}
                                    setTabelaCosip={setTabelaCosip}
                                    indexContribuicao={indexContribuicao}
                                    disabled={isLoading}
                                  />
                                ));
                              }
                              return null;
                            })}
                          </TableRow>
                        </Fragment>
                      );
                    })
                )}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  );
}

function InputCell({
  contribuicao,
  col,
  onChange,
  index,
  setTabelaCosip,
  indexContribuicao,
  disabled = false,
}: any) {
  return (
    <TableCell className="p-1 text-center">
      <div className="mx-auto flex flex-row gap-2 justify-center">
        <Input
          name="input"
          defaultValue={
            index > 1
              ? FormatFields.formatarNumero(contribuicao[col.accessorKey])
              : (+contribuicao[col.accessorKey]).toFixed(0)
          }
          mascara={index > 1 ? "numero" : "numerico"}
          width={`min-w-[130px] text-ellipsis`}
          onChange={(e: any) => {
            onChange();
            setTabelaCosip((prev: any[]) => {
              const newTabela = [...prev];
              newTabela.splice(indexContribuicao, 1, {
                ...prev[indexContribuicao],
                [col.accessorKey]: +FormatFields.desformatarNumeros(
                  e.target.value,
                ),
              });
              return newTabela;
            });
          }}
          prefix={
            ["valor_residencial_cosip", "valor_nao_residencial_cosip"].includes(
              col?.accessorKey,
            )
              ? "R$"
              : ""
          }
          maxLength={undefined}
          disabled={disabled}
        />
      </div>
    </TableCell>
  );
}
