import LoaderSun from "@/components/common/Loader/LoaderSun";
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 { handleSweetAlert } from "@/components/Modal/SweetAlertConfirm";
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 { useScreenContext } from "@/src/contexts/ScreenContext";
import {
  FormatFields,
  GetForm,
  getObjectDepth,
  proximoNumero,
  tamanhoDaLacuna,
  validarRanges,
} from "@/utils";
import { Download, TriangleAlert, Upload, X } from "lucide-react";
import { Fragment, useEffect, 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";

export default function CosipManager({}: any) {
  const [valuesKey, setValuesKey] = useState(0);
  const [intersecoesRanges, setIntersecoesRanges] = useState<any>({});
  const [tabelaCosip, setTabelaCosip] = useState<any[]>([]);
  const [tabelaViewCosip, setTabelaViewCosip] = useState<any[]>([]);
  const [estadosSelecionados, setEstadosSelecionados] = useState<any[]>([]);
  const [cidadesSelecionadas, setCidadesSelecionadas] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(false);

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

  useEffect(() => {
    if (formCosip.control._formValues?.cidades) {
      const cidadesDisponiveis = formCosip.control._formValues?.cidades.filter(
        (cidade: any) =>
          estadosSelecionados.some(
            (estado) =>
              estado.value == "*" || estado.id_estado == cidade.estado_cidade,
          ),
      );
      formCosip.setValue("cidades", cidadesDisponiveis);
      setCidadesSelecionadas(cidadesDisponiveis);
    }
  }, [estadosSelecionados]);

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

  useEffect(() => {
    // form.setValue("tabelaCosip" as never, tabelaCosip as never);
    const ranges = tabelaCosip.map((contribuicao) => [
      Number(contribuicao[minRange]),
      Number(contribuicao[maxRange]),
    ]);
    const intersecoes = validarRanges(ranges);
    setIntersecoesRanges(intersecoes);
    // setIntersecoesRanges(() => {

    //   return [];
    // });
  }, [tabelaCosip]);

  return (
    // <div className={`flex flex-${isMobile ? "col" : "row"} gap-3`}>
    <div className={`flex flex-col gap-3`}>
      <div className="border p-2 flex flex-col gap-3 min-w-[300px]">
        <div className=" mb-5 w-full flex flex-col border items-center  bg-[#fff5ea]  gap-2 px-4 p-4 rounded-md border-[#fcdcaa] shadow-sm">
          <div className="flex flex-row items-center gap-2">
            <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>Cidade</b> para obter as que existem,
              para uma nova contribuição clique em <b>Nova Contribuição</b>, ao
              mudar valores selecione as cidades que recebem estes valores então
              clique em <b>Salvar o COSIP</b>. Estes valores serão usados no
              cálculo de <b>UCS de consumo</b> no negócio do cliente.
            </p>
          </div>
          <div className="flex flex-row items-center gap-2">
            <div className="rounded-full p-1 shadow-md bg-[#fef9f6]">
              <RiErrorWarningFill size={20} color="#ffb747" />
            </div>
            <p className="text-black text-sm">
              Ao <b>Salvar o COSIP</b> a tabela COSIP abaixo será setada para
              todas as <b>Cidades</b> selecionadas.
            </p>
          </div>
        </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>
            <InputSelectComponent
              name="estados"
              label="Estados"
              formulario={formCosip}
              options={[
                {
                  label: "Todos",
                  value: "*",
                },
                ...estados.map((estado) => ({
                  ...estado,
                  label: `${estado.uf_estado} - ${estado.nome_estado}`,
                  value: estado.id_estado,
                })),
              ]}
              isMulti
              onChange={(e: any) => setEstadosSelecionados(e)}
            />
          </div>
          {estadosSelecionados.length > 0 && (
            <div>
              <div>
                <InputSelectComponent
                  name="cidades"
                  label="Cidades"
                  formulario={formCosip}
                  options={[
                    {
                      label: "Todas",
                      value: "*",
                    },
                    ...cidades
                      .filter((cidade) =>
                        estadosSelecionados.some(
                          (estado) =>
                            estado.value == "*" ||
                            estado.id_estado == cidade.estado_cidade,
                        ),
                      )
                      .map((cidade) => ({
                        ...cidade,
                        label: cidade.nome_cidade,
                        value: cidade.id_cidade,
                      })),
                  ]}
                  isMulti
                  onChange={(e: any) => setCidadesSelecionadas(e)}
                />
              </div>
            </div>
          )}
        </InputGroup>
        <div className="flex flex-col items-center justify-center">
          {cidadesSelecionadas.length > 0 && (
            <Button
              type="button"
              className="flex flex-row gap-1 bg-primary"
              onClick={() => {
                setIsLoading(true);
                obterCosip({
                  ...(cidadesSelecionadas.length > 1 ||
                  cidadesSelecionadas.some((cidade) => cidade.value == "*")
                    ? {
                        estados: estadosSelecionados
                          ?.map((estado) => estado?.value)
                          ?.join(),
                        cidades: cidadesSelecionadas
                          ?.map((cidade) => cidade.value)
                          ?.join(),
                      }
                    : { cidade: cidadesSelecionadas[0]?.value }),
                })
                  .then((res) => {
                    if (
                      cidadesSelecionadas.length > 1 ||
                      cidadesSelecionadas.some((cidade) => cidade.value == "*")
                    ) {
                      const viewColumns: any[] = [
                        ...[
                          {
                            header: `Estado`,
                            accessorKey: "__estado_cosip",
                            rowSpan: 2,
                          },
                          {
                            header: `Cidade`,
                            accessorKey: "__cidade_cosip",
                            rowSpan: 2,
                          },
                        ],
                        ...columns,
                      ];
                      const flattenLeaves = (cols: any[]): number =>
                        cols.reduce((acc, col) => {
                          if (col.columns)
                            return acc + flattenLeaves(col.columns);
                          return acc + 1;
                        }, 0);
                      const totalLeafColumns = flattenLeaves(columns);

                      handleSweetAlert({
                        icon: "info",
                        showDenyButton: false,
                        confirmButtonText: "Ok",
                        width: "70vw",
                        html: (
                          <div className="w-full shadow-md max-h-[50vh] overflow-auto flex flex-col items-center">
                            <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]">
                                  {viewColumns.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>
                                  {viewColumns.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}
                                  />
                                ) : (
                                  res
                                    .sort((a: any, b: any) => {
                                      const cidadeA = cidades.find(
                                        (c: any) =>
                                          c.id_cidade === a.cod_cidade_cosip,
                                      )?.nome_cidade;
                                      const cidadeB = cidades.find(
                                        (c: any) =>
                                          c.id_cidade === b.cod_cidade_cosip,
                                      )?.nome_cidade;

                                      // 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 cidadeA.localeCompare(
                                        cidadeB,
                                        "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="p-1 text-center min-w-[120px]">
                                                {estadoCell}
                                              </TableCell>

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

                                              {viewColumns.map(
                                                (col: any, index: number) => {
                                                  if (
                                                    col.accessorKey &&
                                                    !col.accessorKey.startsWith(
                                                      "__",
                                                    )
                                                  ) {
                                                    return (
                                                      <TableCell
                                                        key={`${indexContribuicao}-col-${index}`}
                                                        className="p-1 text-center"
                                                      >
                                                        <div className="mx-auto flex flex-row gap-2 justify-center">
                                                          {/* {
                                                            contribuicao[
                                                              col.accessorKey
                                                            ]
                                                          } */}
                                                          {index > 1
                                                            ? FormatFields.formatarNumero(
                                                                contribuicao[
                                                                  col
                                                                    .accessorKey
                                                                ],
                                                              )
                                                            : (+contribuicao[
                                                                col.accessorKey
                                                              ]).toFixed(0)}
                                                        </div>
                                                      </TableCell>

                                                      // <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) => (
                                                        <TableCell
                                                          key={`${indexContribuicao}-col-${index}-${i}`}
                                                          className="p-1 text-center"
                                                        >
                                                          <div className="mx-auto flex flex-row gap-2 justify-center">
                                                            {/* {
                                                              contribuicao[
                                                                c.accessorKey
                                                              ]
                                                            } */}
                                                            {index > 1
                                                              ? FormatFields.formatarNumero(
                                                                  contribuicao[
                                                                    c
                                                                      .accessorKey
                                                                  ],
                                                                )
                                                              : (+contribuicao[
                                                                  c.accessorKey
                                                                ]).toFixed(0)}
                                                          </div>
                                                        </TableCell>

                                                        // <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>
                        ),
                      });
                    } else {
                      setTabelaCosip(res);
                    }
                  })
                  .finally(() => setIsLoading(false));
              }}
            >
              {cidadesSelecionadas.length > 1 ||
              cidadesSelecionadas.some((cidade) => cidade.value == "*") ? (
                <div>{`Visualizar valores COSIP das cidades`}</div>
              ) : (
                <div>{`Obter valores COSIP da cidade`}</div>
              )}
              <Download />
            </Button>
          )}
        </div>
      </div>
      <div className="flex-1 relative">
        {isLoading && (
          <div className="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center bg-black-2/10 z-10">
            <LoaderSun />
          </div>
        )}
        <div className={`flex flex-row gap-2 justify-between pb-4`}>
          <div className="flex flex-col justify-end">
            <Button
              type="button"
              className="bg-primary"
              onClick={() => {
                setTabelaCosip((prev) => [
                  ...prev,
                  columns.reduce((acc: any, col) => {
                    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
                          ? proximoNumero(
                              tabelaCosip.map((registro: any) => [
                                Number(registro[minRange]),
                                Number(registro[maxRange]),
                              ]),
                            )
                          : col.accessorKey == maxRange
                            ? proximoNumero(
                                tabelaCosip.map((registro: any) => [
                                  Number(registro[minRange]),
                                  Number(registro[maxRange]),
                                ]),
                              ) +
                              (tamanhoDaLacuna(
                                tabelaCosip.map((registro: any) => [
                                  Number(registro[minRange]),
                                  Number(registro[maxRange]),
                                ]),
                              ) -
                                1 >
                              0
                                ? tamanhoDaLacuna(
                                    tabelaCosip.map((registro: any) => [
                                      Number(registro[minRange]),
                                      Number(registro[maxRange]),
                                    ]),
                                  ) - 1
                                : 1)
                            : 0.0;
                    }
                    return acc;
                  }, {}),
                ]);

                setValuesKey((prev) => prev + 1);
              }}
            >
              Nova Contribuição
            </Button>
          </div>
          <div>
            {cidadesSelecionadas.length > 0 && tabelaCosip.length > 0 && (
              <Button
                type="button"
                className="flex flex-row gap-1 "
                onClick={() => {
                  salvarCosip({
                    cidades: (cidadesSelecionadas.some(
                      (cidade) => cidade.value == "*",
                    )
                      ? cidades.filter((cidade) =>
                          estadosSelecionados.some(
                            (estado) =>
                              estado.value == "*" ||
                              estado.id_estado == cidade.estado_cidade,
                          ),
                        )
                      : cidadesSelecionadas
                    ).map((cidade) => cidade.id_cidade),
                    tabelaCosip,
                  });
                }}
              >
                <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">
            <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)}
                  >
                    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 className="">
                  {columns.map((col, index) => {
                    if (col.columns) {
                      return col.columns.map((c, i) => (
                        <TableHead
                          key={i}
                          className="font-bold py-2 px-4 border-b text-center"
                        >
                          {c.header}
                        </TableHead>
                      ));
                    }
                    // return (
                    //   <TableHead
                    //     key={index}
                    //     className="font-bold py-2 px-4 border-b text-center"
                    //   >
                    //     {col.header}
                    //   </TableHead>
                    // );
                  })}
                </TableRow>
              </TableHeader>
              <tbody key={valuesKey}>
                {tabelaCosip.map(
                  (contribuicao: any, indexContribuicao: number) => {
                    return (
                      <Fragment key={indexContribuicao}>
                        <TableRow>
                          <TableCell>
                            <div className="flex justify-around gap-1">
                              {/* <button
                                  title="Duplicar"
                                  className="navButton bg-primary text-white"
                                  type="button"
                                  onClick={() => {}}
                                >
                                  <Copy />
                                </button> */}
                              <button
                                title="Remover"
                                type="button"
                                className="navButton bg-error text-white  "
                                onClick={() => {
                                  setTabelaCosip((prev) => {
                                    const newTabela = [...prev];
                                    newTabela.splice(indexContribuicao, 1);
                                    return newTabela;
                                  });
                                  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]
                                    ) {
                                      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)}`,
                                            // `${
                                            //   metodoCustoExtra == "1"
                                            //     ? Number(
                                            //         tabelaCosip[
                                            //           Number(interseccao)
                                            //         ][minRange]
                                            //       ).toFixed(0)
                                            //     : FormatFields.formatarNumero(
                                            //         tabelaCosip[
                                            //           Number(interseccao)
                                            //         ][minRange]
                                            //       )
                                            // } até ${
                                            //   metodoCustoExtra == "1"
                                            //     ? Number(
                                            //         tabelaCosip[
                                            //           Number(interseccao)
                                            //         ][maxRange]
                                            //       ).toFixed(0)
                                            //     : FormatFields.formatarNumero(
                                            //         tabelaCosip[
                                            //           Number(interseccao)
                                            //         ][maxRange]
                                            //       )
                                            // }`
                                          )
                                          .join(", ")}`,
                                      );
                                    }
                                  }}
                                >
                                  <TriangleAlert />
                                </button>
                              )}
                            </div>
                          </TableCell>
                          {columns.map((col, index) => {
                            if (col.accessorKey) {
                              return (
                                <InputCell
                                  key={index}
                                  contribuicao={contribuicao}
                                  col={col}
                                  index={index}
                                  setTabelaCosip={setTabelaCosip}
                                  indexContribuicao={indexContribuicao}
                                />
                              );
                            } else if (col.columns) {
                              return col.columns.map((c, i) => (
                                <InputCell
                                  key={i}
                                  contribuicao={contribuicao}
                                  col={c}
                                  index={index}
                                  setTabelaCosip={setTabelaCosip}
                                  indexContribuicao={indexContribuicao}
                                />
                              ));
                            }
                          })}
                        </TableRow>
                      </Fragment>
                    );
                  },
                )}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  );
}

function InputCell({
  key,
  contribuicao,
  col,
  index,
  setTabelaCosip,
  indexContribuicao,
}: any) {
  return (
    <TableCell key={key} 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={`${index < 2 && `min-w-[130px] flex-1`} text-ellipsis`}
          width={`min-w-[130px] text-ellipsis`}
          onChange={(e: any) => {
            setTabelaCosip((prev: any[]) => {
              const newTabela = [...prev];
              newTabela.splice(indexContribuicao, 1, {
                ...prev[indexContribuicao],
                [col.accessorKey]: +FormatFields.desformatarNumeros(
                  e.target.value,
                ),
              });
              return newTabela;
            });
          }}
          prefix={index > 1 ? "R$" : ""}
          maxLength={undefined}
        />
      </div>
    </TableCell>
  );
}

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>
      ))}
    </>
  );
}

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