import useLocalStorage from "@/hooks/useLocalStorage";
import { listarPerfil } from "@/requests/CRUD/Perfil/listarPerfil";
import { listarUsuarioPeloId } from "@/requests/CRUD/Usuario/listarUsuarios";
import { checkIsPublicRoute } from "@/utils/check-is-public-route";
import { decryptData, encryptData } from "@/utils/cryptoUtils";
import equal from "fast-deep-equal";
import { usePathname, useRouter } from "next/navigation";
// import { useRouter } from "next/router";
import {
  ReactNode,
  createContext,
  useContext,
  useEffect,
  useState,
} from "react";
export const TOKEN_KEY = "@userSession";
export const TIME_KEY = "@userSession-Time";

interface AuthContextProps {
  valuesSession: () => any;
  validateSession: () => boolean;
  checkUserAuthenticated: () => boolean;
  authLogin: (token: string) => void;
  logout: () => void;
  perfil: Perfil;
  usuario: any;
  localToken: any;
  obterDadosSecao(session: any): Promise<[any, any]>;
  relistarPerfil(): Promise<void>;
  obterDadosUsuario(id_usuario: string | number): Promise<any>;
  setStorageToken: (newUserData: any, newPerfilData: any) => void;
  updateSession: (partial: Partial<StoredToken>) => void;
}

// interface para perfil (TESTE)
export interface Perfil {
  [x: string]: string | number | null;
  cancelar_contrato_perfil: string | number | null;
  cancelar_proposta_perfil: string | number | null;
  cargo_perfil: string | number | null;
  configura_metas: string | number | null;
  cria_documentos_personalizados: string | number | null | null;
  cria_documentos_personalizados_perfil: string | number | null;
  edita_cfgGerais_perfil: string | number | null;
  edita_contato_perfil: string | number | null;
  edita_funis_perfil: string | number | null;
  edita_performance_ratio_perfil: string | number | null;
  edita_precificacoes_proposta_perfil: string | number | null;
  edita_sombreamento_perfil: string | number | null;
  editar_data_finalizacao_venda_perfil: string | number | null;
  engenharia_perfil: string | number | null;
  estornar_pagamento_perfil: string | number | null;
  estornar_venda_perfil: string | number | null;
  finalizar_pagamento_perfil: string | number | null;
  finalizar_vendas_perfil: string | number | null;
  id_perfil: string | number | null;
  nome_perfil: string | number | null;
  permissoes_etapas_perfil: string | null;
  permissoes_funis_perfil: string | null;
  permissoes_graficos_perfil: string | null;
  permissoes_perfil: string | null;
  permite_agendar_instalacoes_perfil: string | number | null;
  permite_alterar_responsaveis: string | number | null;
  permite_alterar_valorTarifa: string | number | null;
  permite_aprovar_contrato_perfil: string | number | null;
  permite_aprovar_proposta_perfil: string | number | null;
  permite_apurar_comissoes_perfil: string | number | null;
  permite_concluir_instalacoes_perfil: string | number | null;
  permite_editar_contato_perfil: string | number | null;
  permite_estornar_agendamento_instalacoes_perfil: string | number | null;
  permite_estornar_apuracao_comissoes_perfil: string | number | null;
  permite_estornar_compra_materiais_perfil: string | number | null;
  permite_estornar_conclusao_instalacoes_perfil: string | number | null;
  permite_estornar_pagamento_comissoes_perfil: string | number | null;
  permite_estornar_pagamento_instalacoes_perfil: string | number | null;
  permite_estornar_pendencia_engenharia_perfil: string | number | null;
  permite_estornar_pre_apuracao_comissoes_perfil: string | number | null;
  permite_finalizar_compra_materiais_perfil: string | number | null;
  permite_finalizar_pendencia_engenharia_perfil: string | number | null;
  permite_lancamento_manual_comissoes_perfil: string | number | null;
  permite_gerar_contrato_perfil: string | number | null;
  permite_gerar_proposta_perfil: string | number | null;
  permite_lixeira_perfil: string | number | null;
  permite_pagar_comissoes_perfil: string | number | null;
  permite_pagar_instalacoes_perfil: string | number | null;
  permite_pre_apurar_comissoes_perfil: string | number | null;
  status_perfil: string | number | null;
  vendedor_perfil: string | number | null;
  visualiza_acoes_card_perfil: string | number | null;
  visualiza_config_etapa_perfil: string | number | null;
  visualiza_historico_geral_perfil: string | number | null;
  visualiza_precificacoes_ocultas_proposta_perfil: string | number | null;
  visualiza_preco_kit_perfil: string | number | null;
  visualiza_simulador_financeiro_perfil: string | number | null;
  visualiza_pendencias_realizadas_perfil: string | number | null;
  visualiza_todas_agendas_perfil: string | number | null;
  visualiza_todos_contatos_perfil: string | number | null;
  visualiza_todos_funis_perfil: string | number | null;
  permite_realizar_entrega_kit: string | number | null;
  visualiza_total_negocios_etapa_perfil: string | number | null;
  visualiza_total_valores_etapa_perfil: string | number | null;
  visualiza_totalizadores_fluxo: string | number | null;
  alterar_validade_proposta_perfil: string | number | null;
  excluir_contrato_perfil: string | number | null;
  alterar_datas_contrato_perfil: string | number | null;
}

const AuthContext = createContext<AuthContextProps | undefined>(undefined);

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

interface AuthProviderProps {
  children: ReactNode;
}
export interface StoredToken {
  id_usuario: string;
  nome_usuario: string;
  email_usuario: string;
  login_usuario?: string;
  telefone1_usuario: string;
  perfil_usuario: string;
  desconto_usuario: string; // pode ser string ou number, se quiser converter
  funil_favorito_usuario: string;
  id_loja_usuario: string; // contém múltiplos IDs separados por vírgula
  loja_padrao_usuario: string;
  loja_usuario: string;
  sigla: string;
  corAvatar: string;
  primeiro_login: string; // "0" ou "1"
}

export function AuthProvider({ children }: AuthProviderProps) {
  const [storedToken, setStoredToken] = useState<any>(() => {
    try {
      if (typeof window !== "undefined") {
        const item = window.localStorage.getItem(TOKEN_KEY);

        return item ? decryptData(item) : "";
      }
    } catch (error) {
      // //(error);
      return "";
    }
  });
  const [storedTokenTime, setStoredTokenTime] = useLocalStorage(TIME_KEY, "");
  const [perfil, setPerfilusuario] = useState<any>(null);
  const [usuario, setUsuario] = useState<any>(null);
  const [localToken, setLocalToken] = useState<any>(() => {
    try {
      if (typeof window !== "undefined") {
        const item = window.localStorage.getItem(TOKEN_KEY);

        return item ? decryptData(item) : "";
      }
    } catch (error) {
      // //(error);
      return "";
    }
  });

  const setToken = (token: string) => {
    window.localStorage.setItem(TOKEN_KEY, token);
    if (!equal(localToken, decryptData(token))) {
      setLocalToken(decryptData(token));
    }
  };

  const setStorageToken = (newUserData: any, newPerfilData: any) => {
    const currentSession = storedToken;
    const updatedSession = {
      ...currentSession,
      id_usuario: newUserData.id_usuario,
      nome_usuario: newUserData["nome_usuario"] ?? currentSession?.nome_usuario,
      perfil_usuario: newUserData.perfil_usuario,
      id_perfil: newPerfilData.id_perfil,
      primeiro_login:
        newUserData["primeiro_login_usuario"] ??
        currentSession?.primeiro_login_usuario,
      id_loja_usuario:
        newUserData["loja_usuario"] ?? currentSession?.loja_usuario,
      loja_padrao_usuario: newUserData["loja_padrao_usuario"]
        ? newUserData["loja_padrao_usuario"]
        : newUserData["loja_usuario"]
          ? newUserData["loja_usuario"]?.split(",")[0]
          : currentSession["loja_padrao_usuario"]
            ? currentSession["loja_padrao_usuario"]
            : currentSession["loja_usuario"]?.split(",")?.[0],
      email_usuario:
        newUserData["email_usuario"] ?? currentSession?.email_usuario,
      telefone1_usuario:
        newUserData["telefone1_usuario"] ?? currentSession?.telefone1_usuario,
      // sigla: $dados["sigla_cliente_linksun"],
      desconto_usuario:
        newUserData["max_desconto_usuario"] ??
        currentSession?.max_desconto_usuario,
      corAvatar:
        newUserData["cor_avatar_usuario"] ?? currentSession?.cor_avatar_usuario,
      funil_favorito_usuario:
        newUserData["funil_favorito_usuario"] ??
        currentSession?.funil_favorito_usuario,
      // token: $token,
    };

    // Criptografa e armazena a nova sessão
    const encryptedSession = encryptData(JSON.stringify(updatedSession));
    window.localStorage.setItem(TOKEN_KEY, encryptedSession.toString());
    if (!equal(localToken, updatedSession)) {
      setStoredToken(updatedSession);
      setLocalToken(updatedSession);
    }
  };

  const updateSession = (partial: Partial<StoredToken>) => {
    if (!storedToken || typeof window === "undefined") return;
    const updatedSession = { ...storedToken, ...partial };
    const encryptedSession = encryptData(JSON.stringify(updatedSession));
    window.localStorage.setItem(TOKEN_KEY, encryptedSession.toString());
    if (!equal(localToken, updatedSession)) {
      setStoredToken(updatedSession);
      setLocalToken(updatedSession);
    }
  };

  const pathname = usePathname();
  const route = useRouter();
  const isPublicRoute = checkIsPublicRoute(pathname!);

  if (!isPublicRoute && storedToken == "") {
    route.push("/");
  }

  const authLogin = (token: string) => {
    setStoredToken(decryptData(token));
    setToken(token);
    const currentTime = new Date();
    currentTime.setHours(currentTime.getHours() + 12);
    const updatedTime = currentTime.toISOString();
    setStoredTokenTime(updatedTime);
  };
  const checkUserAuthenticated = () => {
    return !!storedToken;
  };

  const valuesSession = () => {
    const session = storedToken;
    return { session };
  };

  const validateSession = () => {
    const currentTime = new Date();
    const storedTime = new Date(storedTokenTime);
    if (currentTime > storedTime) {
      logout();
      return false;
    } else {
      return true;
    }
  };

  async function validateUserSession() {
    if (!checkUserAuthenticated()) {
      logout();
      return;
    }

    const { session }: any = valuesSession();
    await obterDadosSecao(session);
  }

  // const route = useRouter();
  const logout = () => {
    // Redireciona para a página inicial
    route.push("/");

    // Remove completamente o token do localStorage
    window.localStorage.removeItem(TOKEN_KEY);
    setLocalToken("");

    // Limpa tokens armazenados no estado
    setStoredToken("");
    setStoredTokenTime("");

    // Limpa sessionStorage (se estiver sendo usado)
    sessionStorage.clear();

    // Reseta o histórico do navegador
    history.replaceState(null, "", "/");

    // Limpa o cache do navegador
    if ("caches" in window) {
      caches.keys().then((names) => {
        names.forEach((name) => caches.delete(name));
      });
    }

    // Remove cookies (se necessário)
    document.cookie.split(";").forEach((cookie) => {
      document.cookie = cookie
        .replace(/^ +/, "")
        .replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/");
    });

    window.location.reload();
  };

  useEffect(() => {
    if (localToken) {
      const { session }: any = valuesSession();
      obterDadosSecao(session);
    } else {
    }
  }, [localToken]);

  useEffect(() => {
    if (pathname === "/") return;

    if (!isPublicRoute && storedToken == "") {
      route.push("/");
    }
    !isPublicRoute && validateUserSession();
  }, [pathname, isPublicRoute, storedToken]);

  useEffect(() => {
    const interval = setInterval(
      () => {
        if (!checkUserAuthenticated()) {
          logout();
          return;
        }
      },
      15 * 60 * 1000,
    );
    return () => clearInterval(interval);
  }, []);

  async function obterDadosSecao(session: any): Promise<[any, any]> {
    const usuarioRes = await listarUsuarioPeloId(session.id_usuario);
    if (usuarioRes?.status_usuario == 0 || usuarioRes?.status_usuario == "0") {
      logout();
      return [null, null];
    }
    setUsuario(usuarioRes);

    let perfilRes = null;
    if (usuarioRes?.perfil_usuario !== session?.perfil_usuario) {
      perfilRes = await listarPerfil(usuarioRes?.perfil_usuario);
      if (perfilRes?.status_perfil == 0 || perfilRes?.status_perfil == "0") {
        logout();
        return [usuarioRes, null];
      }
      if (perfilRes?.id_perfil !== session?.id_perfil) {
        // Atualiza a sessão com o novo perfil e usuário
        setStorageToken(usuarioRes, perfilRes);
      }
      setPerfilusuario(perfilRes);
    } else {
      obterDadosUsuario(session.id_usuario);
      // perfilRes = null;
    }

    return [usuarioRes, perfilRes];
  }

  async function obterDadosUsuario(id_usuario: string | number) {
    return listarUsuarioPeloId(id_usuario).then(async (res) => {
      if (res?.status_usuario == 0 || res?.status_usuario == "0") {
        logout();
        return;
      }
      setUsuario(res);

      return listarPerfil(res?.perfil_usuario).then((resPerfil) => {
        if (resPerfil?.status_perfil == 0 || resPerfil?.status_perfil == "0") {
          logout();
          return;
        }
        setPerfilusuario(resPerfil);
        setStorageToken(res, resPerfil);
        return { ...res, ...resPerfil };
      });
    });
  }

  async function relistarPerfil() {
    obterDadosSecao(usuario);
  }

  const contextValue = {
    valuesSession,
    validateSession,
    checkUserAuthenticated,
    authLogin,
    logout,
    perfil,
    localToken,
    usuario,
    obterDadosSecao,
    relistarPerfil,
    obterDadosUsuario,
    setStorageToken,
    updateSession,
  };

  return (
    <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>
  );
}
