import type { ComputedRef, Ref } from "vue";
import type { ExtendedUser } from "~/types/auth";
import { computed, ref, watch, readonly } from "vue";

export interface UseUserInfoReturnType {
  // State
  isAuthenticated: ComputedRef<boolean>;
  isLoading: ComputedRef<boolean>;
  user: ComputedRef<ExtendedUser | null>;
  userRoles: ComputedRef<string[]>;
  clientRoles: ComputedRef<string[]>;
  accessToken: ComputedRef<string>;
  sessionExpires: ComputedRef<string | null>;
  isIdle: Ref<boolean>;

  // Raw data for debugging
  data: Ref<any>;
  status: Ref<string>;

  // Session data from [...].ts
  idToken: ComputedRef<string>;
  refreshToken: ComputedRef<string>;
  accessTokenPayload: ComputedRef<any>;
  expiresAt: ComputedRef<number | null>;
  sessionScope: ComputedRef<string>;
  jwtToken: ComputedRef<string>;

  // Role checking functions
  hasRole: (role: string) => boolean;
  hasClientRole: (role: string) => boolean;
  hasAnyRole: (roles: string[]) => boolean;
  isAdmin: ComputedRef<boolean>;

  // Session monitoring functions
  updateActivity: () => void;
  startSessionMonitoring: () => (() => void) | null;
  stopSessionMonitoring: () => void;

  // Authentication actions
  login: (provider?: string) => Promise<void>;
  logout: (options?: any) => Promise<void>;
  fullLogout: () => Promise<void>;
  refresh: () => Promise<void>;
  forceRefreshSession: () => Promise<void>;
  isKeycloakSessionActive: () => Promise<boolean>;
}

export const useUserInfo = (): UseUserInfoReturnType => {
  const { data, status, signIn, signOut, getSession } = useAuth();

  // Internal writable refs for manual setting
  const internalData = ref(data.value);
  const internalStatus = ref(status.value);

  // Sync internal refs with useAuth data and status
  watch(
    () => data.value,
    (newVal) => {
      internalData.value = newVal;
    },
    { immediate: true }
  );

  watch(
    () => status.value,
    (newVal) => {
      internalStatus.value = newVal;
    },
    { immediate: true }
  );

  // Session monitoring state
  const lastActivity = ref(Date.now());
  const isIdle = ref(false);
  const tabVisible = ref(true);

  // Constants
  const IDLE_TIMEOUT = 15 * 60 * 1000; // 15 menit
  const SESSION_CHECK_INTERVAL = 5 * 60 * 1000; // 5 menit
  const TAB_INACTIVE_THRESHOLD = 10 * 60 * 1000; // 10 menit

  // Basic computed properties
  const isAuthenticated = computed(
    () => internalStatus.value === "authenticated"
  );
  const isLoading = computed(() => internalStatus.value === "loading");

  // User info from session
  const user: ComputedRef<ExtendedUser | null> = computed(() => {
    if (internalData.value?.user) {
      return internalData.value.user as ExtendedUser;
    }
    return null;
  });

  // Session data dari [...].ts callbacks - INILAH DATA YANG AKAN DITAMPILKAN
  const idToken = computed(() => (internalData.value as any)?.id_token || "");

  const accessToken = computed(
    () => (internalData.value as any)?.access_token || ""
  );

  const refreshToken = computed(
    () => (internalData.value as any)?.refresh_token || ""
  );

  const accessTokenPayload = computed(
    () => (internalData.value as any)?.access_token_payload || null
  );

  const expiresAt = computed(
    () => (internalData.value as any)?.expires_at || null
  );

  const sessionScope = computed(() => (internalData.value as any)?.scope || "");

  const jwtToken = computed(() => (internalData.value as any)?.jwt || "");

  // User roles dari session
  const userRoles = computed(() => {
    return (internalData.value?.user as any)?.roles || [];
  });

  const clientRoles = computed(() => {
    return (internalData.value?.user as any)?.client_roles || [];
  });

  // Session expires
  const sessionExpires = computed(() => data.value?.expires || null);

  // Activity tracking functions
  const updateActivity = () => {
    if (process.client) {
      lastActivity.value = Date.now();
      isIdle.value = false;
    }
  };

  const checkIdleStatus = () => {
    if (!process.client) return;
    const now = Date.now();
    const timeSinceLastActivity = now - lastActivity.value;
    if (
      timeSinceLastActivity >= IDLE_TIMEOUT &&
      tabVisible.value &&
      isAuthenticated.value
    ) {
      isIdle.value = true;
      handleIdleTimeout();
    }
  };

  const handleIdleTimeout = async () => {
    if (!process.client) return;
    try {
      const session = await getSession();
      if (
        session &&
        session.expires &&
        new Date(session.expires) > new Date()
      ) {
        await navigateTo("/auth/login?reason=idle&continue=true");
      } else {
        await logout({ reason: "expired" });
      }
    } catch (error) {
      console.error("Idle timeout handling error:", error);
      await logout({ reason: "expired" });
    }
  };

  const handleVisibilityChange = async () => {
    if (!process.client) return;
    tabVisible.value = !document.hidden;
    if (!document.hidden) {
      updateActivity();
      const inactiveTime = Date.now() - lastActivity.value;
      if (inactiveTime >= TAB_INACTIVE_THRESHOLD && isAuthenticated.value) {
        await handleTabReactivation();
      }
    }
  };

  const handleTabReactivation = async () => {
    if (!process.client) return;
    try {
      const session = await getSession();
      if (
        session &&
        session.expires &&
        new Date(session.expires) > new Date()
      ) {
        await navigateTo("/auth/login?reason=tab_inactive&continue=true");
      } else {
        await navigateTo("/auth/login?reason=session_expired");
      }
    } catch (error) {
      console.error("Tab reactivation error:", error);
      await navigateTo("/auth/login?reason=error");
    }
  };

  const startSessionMonitoring = (): (() => void) | null => {
    if (!process.client) {
      console.warn("Session monitoring requires client-side environment");
      return null;
    }

    if (!isAuthenticated.value) {
      console.warn("Session monitoring requires authenticated user");
      return null;
    }

    const events = [
      "mousedown",
      "mousemove",
      "keydown",
      "scroll",
      "touchstart",
      "click"
    ];
    const activityHandler = () => updateActivity();

    events.forEach((event) => {
      document.addEventListener(event, activityHandler, { passive: true });
    });

    document.addEventListener("visibilitychange", handleVisibilityChange);

    const idleInterval = setInterval(checkIdleStatus, 60 * 1000);

    const sessionInterval = setInterval(async () => {
      if (isAuthenticated.value) {
        try {
          await getSession();
        } catch (error) {
          console.error("Session check failed:", error);
          clearInterval(sessionInterval);
          await logout({ reason: "expired" });
        }
      }
    }, SESSION_CHECK_INTERVAL);

    return () => {
      events.forEach((event) => {
        document.removeEventListener(event, activityHandler);
      });
      document.removeEventListener("visibilitychange", handleVisibilityChange);
      clearInterval(idleInterval);
      clearInterval(sessionInterval);
    };
  };

  // **PERBAIKAN: Stop Session Monitoring Function**
  const stopSessionMonitoring = (): void => {
    // Implementation bisa ditambahkan jika diperlukan
    //console.log("Stopping session monitoring...");
  };

  // Role checking functions
  const hasRole = (role: string): boolean => {
    return userRoles.value.includes(role);
  };

  const hasClientRole = (role: string): boolean => {
    return clientRoles.value.includes(role);
  };

  const hasAnyRole = (roles: string[]): boolean => {
    return roles.some((role) => userRoles.value.includes(role));
  };

  const isAdmin = computed(
    () => hasRole("admin") || hasRole("super_admin") || hasRole("realm-admin")
  );

  // Login function
  const login = async (provider = "keycloak") => {
    try {
      const currentUrl = window.location.pathname;
      const callbackUrl = currentUrl !== "/auth/login" ? currentUrl : "/";

      const result = await signIn(provider, {
        callbackUrl,
        redirect: true
      });

      if (result?.error) {
        throw new Error(result.error);
      }

      // **PERBAIKAN: Update activity setelah login berhasil**
      updateActivity();
      await getSession();
    } catch (error) {
      throw error;
    }
  };

  // Enhanced Logout function dengan reason support
  const logout = async (options?: {
    redirect?: string;
    clearStorage?: boolean;
    confirmDialog?: boolean;
    reason?: "manual" | "expired" | "admin" | "idle";
  }) => {
    const defaultOptions = {
      redirect: "/auth/login",
      clearStorage: true,
      confirmDialog: false,
      reason: "idle" as const,
      ...options
    };

    try {
      //console.log("Logout called with options:", defaultOptions);

      // Menghilangkan pemanggilan fullLogout manual sesuai permintaan

      if (defaultOptions.clearStorage && process.client) {
        //console.log("Clearing localStorage and sessionStorage");
        localStorage.removeItem("user-preferences");
        localStorage.removeItem("app-state");
        sessionStorage.clear();
      }

      // Memanggil API logout server untuk menghandle logout Keycloak dan pembersihan session
      if (process.client) {
        // Mengambil keycloakIssuer dan redirectUri dari public runtime config
        const config = useRuntimeConfig();
        const keycloakIssuer = config.public.keycloakIssuer;
        const origin = window.location.origin;
        const redirectUri = `${origin}/auth/login`;

        let logoutUrl = `${keycloakIssuer}/protocol/openid-connect/logout?post_logout_redirect_uri=${encodeURIComponent(
          redirectUri
        )}`;
        if (idToken.value) {
          logoutUrl += `&id_token_hint=${encodeURIComponent(idToken.value)}`;
        }

        //console.log("Calling Keycloak logout URL:", logoutUrl);

        await fetch("/api/auth/logout", {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify({ id_token_hint: idToken.value })
        });

        // Bersihkan local storage setelah logout server
        //console.log("Clearing localStorage and sessionStorage after server logout");
        localStorage.removeItem("user-preferences");
        localStorage.removeItem("app-state");
        sessionStorage.clear();
      }

      try {
        await signOut({
          callbackUrl: `${defaultOptions.redirect}?reason=idle`,
          redirect: true
        });
      } catch (csrfError) {
        // Jika CSRF token error, tetap redirect ke login page
        console.warn("CSRF token error during signOut, redirecting manually:", csrfError);
        if (process.client) {
          window.location.href = `${defaultOptions.redirect}?reason=idle`;
        }
      }
    } catch (error) {
      console.error("Logout failed:", error);
      // Fallback redirect jika logout gagal
      if (process.client) {
        window.location.href = `${defaultOptions.redirect}?reason=error`;
      }
      throw new Error("Logout failed. Please try again.");
    }
  };

  // Perbaikan fullLogout - simplified dan menggunakan logout yang sudah ada
  const fullLogout = async () => {
    try {
      console.log("Full logout initiated");

      // 1. Stop session monitoring terlebih dahulu
      stopSessionMonitoring();
      console.log("Session monitoring stopped");
      console.log(process);

      if (process.client) {
        // 2. Clear all storage before logout
        console.log("Clearing all storage before logout");

        // Clear localStorage
        localStorage.removeItem("user-preferences");
        localStorage.removeItem("app-state");
        localStorage.clear();

        // Clear sessionStorage
        sessionStorage.clear();

        // Log cookies and sessionStorage before clearing
        console.log("Cookies before clearing:", document.cookie);
        console.log(
          "SessionStorage before clearing:",
          JSON.stringify(sessionStorage)
        );

        // Clear cookies if any
        const cookies = document.cookie.split(";");
        const domain = window.location.hostname;
        cookies.forEach((c, index) => {
          const eqPos = c.indexOf("=");
          const name = eqPos > -1 ? c.substr(0, eqPos).trim() : c.trim();

          console.log(`Clearing cookie [${index}]:`, name);

          // Clear cookie for current path
          document.cookie =
            name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";

          // Clear cookie for current path and domain
          document.cookie =
            name +
            `=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${domain}`;

          // Clear cookie for current path and domain with leading dot (for subdomains)
          if (domain.indexOf(".") !== -1) {
            const domainWithDot = "." + domain;
            document.cookie =
              name +
              `=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${domainWithDot}`;
          }

          // Explicitly clear Keycloak cookies if present
          const keycloakCookies = [
            "KEYCLOAK_SESSION",
            "KEYCLOAK_IDENTITY",
            "KEYCLOAK_IDENTITY_LEGACY",
            "KEYCLOAK_REMEMBER_ME",
            "KEYCLOAK_REMEMBER_ME_LEGACY"
          ];
          if (keycloakCookies.includes(name)) {
            console.log(`Explicitly clearing Keycloak cookie: ${name}`);
            document.cookie =
              name +
              `=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${domain}`;
            if (domain.indexOf(".") !== -1) {
              const domainWithDot = "." + domain;
              document.cookie =
                name +
                `=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${domainWithDot}`;
            }
          }
          console.log("Cleared cookie:", name);
        });
      }

      // 3. Call server API to get the correct logout URL
      const response = await $fetch("/api/auth/logout", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          id_token_hint: idToken.value
        })
      });

      if (response.success && response.logoutUrl && process.client) {
        console.log("Redirecting to Keycloak logout:", response.logoutUrl);
        localStorage.removeItem("user-preferences");
        localStorage.removeItem("app-state");
        localStorage.clear();
        sessionStorage.clear();

        // Append query parameters to logoutUrl
        let logoutUrlWithParams = response.logoutUrl;
        // 4. Redirect directly to Keycloak logout endpoint with appended params
        window.location.href = logoutUrlWithParams;
        return;
      }

      // Fallback to signOut if server API fails

      // Clear local data and update status to logged out
      if (process.client) {
        // Clear localStorage and sessionStorage again to be sure
        localStorage.clear();
        sessionStorage.clear();

        // Reset data and status to reflect logged out state
        internalData.value = null;
        internalStatus.value = "unauthenticated";
      }

      return;
    } catch (error) {
      console.error("Full logout failed:", error);
      // Emergency fallback - manual logout to Keycloak
      if (process.client) {
        try {
          console.log("Executing emergency logout");
          const config = useRuntimeConfig();
          const keycloakIssuer = config.public.keycloakIssuer;
          const origin = window.location.origin;
          const redirectUri = `${origin}/auth/login?reason=emergency`;
          // Clear all storage again to ensure
          localStorage.clear();
          sessionStorage.clear();
          // Build logout URL with client_id as fallback
          let emergencyLogoutUrl = `${keycloakIssuer}/protocol/openid-connect/logout?post_logout_redirect_uri=${encodeURIComponent(
            redirectUri
          )}`;
          // Add id_token_hint if available
          if (idToken.value) {
            emergencyLogoutUrl += `&id_token_hint=${encodeURIComponent(
              idToken.value
            )}`;
          } else {
            // Use client_id as alternative if id_token_hint is missing
            const clientId = config.public.keycloakClientId || "your-client-id";
            emergencyLogoutUrl += `&client_id=${encodeURIComponent(
              String(clientId)
            )}`;
          }
          console.log("Emergency logout URL:", emergencyLogoutUrl);
          window.location.href = emergencyLogoutUrl;
        } catch (emergencyError) {
          console.error("Emergency logout failed:", emergencyError);
          // Last resort - force redirect and clear storage
          if (process.client) {
            localStorage.clear();
            sessionStorage.clear();
            window.location.href = "/auth/login?reason=force";
          }
        }
      }
    }
  };

  // Force refresh session
  const forceRefreshSession = async () => {
    try {
      await getSession();
    } catch (error) {
      console.error("Force refresh session error:", error);
    }
  };

  // New method to check if Keycloak session is active
  const isKeycloakSessionActive = async (): Promise<boolean> => {
    if (!process.client) return false;

    try {
      const session = await getSession();
      if (
        session &&
        session.expires &&
        new Date(session.expires) > new Date()
      ) {
        return true;
      }
      return false;
    } catch (error) {
      console.error("Error checking Keycloak session active status:", error);
      return false;
    }
  };

  // Add computed property for accessTokenPayload
  // **PERBAIKAN: Return semua fungsi yang diperlukan termasuk session monitoring**
  return {
    // State
    isAuthenticated,
    isLoading,
    user,
    userRoles,
    clientRoles,
    accessToken,
    sessionExpires,
    isIdle: readonly(isIdle),

    // Raw data untuk debugging
    data: internalData,
    status: internalStatus,

    // Session data dari [...].ts
    idToken,
    refreshToken,
    accessTokenPayload,
    expiresAt,
    sessionScope,
    jwtToken,

    // Role checking functions
    hasRole,
    hasClientRole,
    hasAnyRole,
    isAdmin,

    // Session monitoring functions
    updateActivity,
    startSessionMonitoring,
    stopSessionMonitoring,

    // Authentication actions
    login,
    logout,
    fullLogout,
    refresh: async () => {
      await getSession();
    },
    forceRefreshSession,
    isKeycloakSessionActive
  };
};
