"use client";

import type { ErrorContext } from "aau-auth-kit/react";
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
import { AuthUIContext } from "../lib/auth-ui-provider";
import type { User } from "../types/auth-client";

export type UserAdmin = {
  id: string;
  name: string;
  email: string;
  role: string | string[];
  verified: boolean;
  status: string;
  createdAt: string;
};

export type SortDirection = "asc" | "desc";
export type SortField = "name" | "email" | "role" | "createdAt";

export type UserFilters = {
  searchQuery: string;
  filterRole: string | null;
  sortBy: SortField;
  sortDirection: SortDirection;
  currentPage: number;
  pageSize: number;
};

export type ErrorState = {
  code: string;
  message: string;
  action?: string;
  userId?: string;
  timestamp: number;
};

// Custom error messages
const ERROR_MESSAGES = {
  fetchUsers: "Failed to load users. Please try again.",
  banUser: "Unable to ban user. The operation failed.",
  unbanUser: "Unable to unban user. The operation failed.",
  removeUser: "Unable to remove user. The operation failed.",
  setRole: "Unable to change user role. The operation failed.",
  revokeSessions: "Unable to revoke user sessions. The operation failed.",
  invalidResponse: "The server returned an invalid response.",
  networkError:
    "Network connection error. Please check your internet connection.",
  serverError: "The server encountered an error. Please try again later.",
  unauthorized: "You don't have permission to perform this action.",
  rateLimited: "Too many requests. Please try again in a moment.",
  unknown: "An unexpected error occurred. Please try again.",
};

export type UserAction =
  | "ban"
  | "unban"
  | "remove"
  | "setRole"
  | "revokeSessions";

export function useAdminUsers(initialFilters: Partial<UserFilters> = {}) {
  const { authClient, toast } = useContext(AuthUIContext);

  // State
  const [users, setUsers] = useState<UserAdmin[]>([]);
  const [totalUsers, setTotalUsers] = useState(0);
  const [isLoading, setIsLoading] = useState(true);
  const [isRefetching, setIsRefetching] = useState(false); // Separate refetching state
  const [isActionPending, setIsActionPending] = useState(false);
  const [error, setError] = useState<ErrorState | null>(null);
  const [initialFetchDone, setInitialFetchDone] = useState(false); // Track initial fetch

  // Filters state with defaults
  const [filters, setFilters] = useState<UserFilters>({
    searchQuery: "",
    filterRole: null,
    sortBy: "createdAt",
    sortDirection: "desc",
    currentPage: 1,
    pageSize: 10,
    ...initialFilters,
  });

  // Derived values
  const totalPages = Math.ceil(totalUsers / filters.pageSize);
  const hasError = error !== null;

  // Query parameters for API call
  const queryParams = useMemo(() => {
    const params = {
      limit: filters.pageSize,
      offset: (filters.currentPage - 1) * filters.pageSize,
      sortBy: filters.sortBy,
      sortDirection: filters.sortDirection,
      search: "",
    };

    if (filters.searchQuery) {
      params.search = filters.searchQuery;
    }

    return params;
  }, [filters]);

  const e = useCallback(
    (
      errorMessage: string,
      errorCode: string,
      action: string,
      userId?: string
    ) => {
      // Create error state
      const errorState: ErrorState = {
        code: errorCode,
        message: errorMessage,
        action,
        userId,
        timestamp: Date.now(),
      };

      setError(errorState);

      toast({
        variant: "error",
        message: errorMessage,
      });

      return errorState;
    },
    [toast]
  );

  // Error handling helper
  const handleError = useCallback(
    (error: ErrorContext["error"], action: string, userId?: string) => {
      // Determine error code and message
      let errorCode = error?.code;
      let errorMessage = error.message;

      if (errorCode && errorMessage)
        return e(errorMessage, errorCode, action, userId);

      // Extract error details if available
      if (error.code) {
        errorCode = error.code;
      } else if (error.status) {
        errorCode = String(error.status);
      }
      // Map error codes to messages
      switch (errorCode) {
        case "NETWORK_ERROR":
          errorMessage = ERROR_MESSAGES.networkError;
          break;
        case "RATE_LIMITED":
        case "429":
          errorMessage = ERROR_MESSAGES.rateLimited;
          break;
        case "401":
        case "403":
          errorMessage = ERROR_MESSAGES.unauthorized;
          break;
        case "500":
        case "502":
        case "503":
        case "504":
          errorMessage = ERROR_MESSAGES.serverError;
          break;
        default:
          // Use action-specific error messages
          if (action === "fetchUsers") {
            errorMessage = ERROR_MESSAGES.fetchUsers;
          } else if (action === "banUser") {
            errorMessage = ERROR_MESSAGES.banUser;
          } else if (action === "unbanUser") {
            errorMessage = ERROR_MESSAGES.unbanUser;
          } else if (action === "removeUser") {
            errorMessage = ERROR_MESSAGES.removeUser;
          } else if (action === "setRole") {
            errorMessage = ERROR_MESSAGES.setRole;
          } else if (action === "revokeSessions") {
            errorMessage = ERROR_MESSAGES.revokeSessions;
          }
      }

      // Use error message from response if available
      if (error.message) {
        errorMessage = error.message;
      }
      return e(errorMessage, errorCode, action, userId);
    },
    [e]
  );

  // Clear error state
  const clearError = useCallback(() => {
    setError(null);
  }, []);

  // Fetch users - with optional silentRefetch parameter
  const fetchUsers = useCallback(
    async (options: { retryCount?: number; silentRefetch?: boolean } = {}) => {
      const { retryCount = 0, silentRefetch = false } = options;

      // Determine if this is a loading or refetching state
      if (!initialFetchDone || !silentRefetch) {
        setIsLoading(true);
      } else {
        setIsRefetching(true);
      }

      clearError();

      try {
        const response = await authClient.admin.listUsers({
          query: queryParams,
        });

        // Validate response
        if (
          !response ||
          !response.data ||
          !Array.isArray(response.data.users)
        ) {
          throw new Error(ERROR_MESSAGES.invalidResponse);
        }

        // Map the response to our User type
        const formattedUsers = response.data.users.map((user) => ({
          id: user.id,
          name: user.name || "N/A",
          email: user.email || "No email",
          role: user.role || "user",
          verified: !!user.emailVerified,
          status: user.banned ? "banned" : "active",
          createdAt: user.createdAt
            ? new Date(user.createdAt).toLocaleDateString()
            : "Unknown",
        })) as UserAdmin[];

        setUsers(formattedUsers);
        setTotalUsers(formattedUsers.length);
        setInitialFetchDone(true);
      } finally {
        setIsLoading(false);
        setIsRefetching(false);
      }
    },
    [authClient, queryParams, handleError, clearError, initialFetchDone]
  );

  // Update filters with optional silent update
  const updateFilters = useCallback(
    (newFilters: Partial<UserFilters>, silentRefetch = false) => {
      setFilters((prev) => ({
        ...prev,
        ...newFilters,
        currentPage: "currentPage" in newFilters ? newFilters.currentPage! : 1,
      }));

      if (silentRefetch) {
        return { silentRefetch: true };
      }

      return { silentRefetch: false };
    },
    []
  );

  // User actions
  const handleUserAction = useCallback(
    async (action: UserAction, userId: string, data?: any) => {
      if (isActionPending) return { success: false };

      setIsActionPending(true);
      clearError();

      try {
        // Validate userId
        if (!userId) {
          throw new Error("Invalid user ID");
        }

        // Perform the requested action
        switch (action) {
          case "ban":
            await authClient.admin.banUser(
              { userId },
              {
                onSuccess() {
                  toast({
                    variant: "success",
                    message: "User banned successfully",
                  });
                },
                onError(ctx) {
                  console.log({ ctx });
                  handleError(ctx?.error, `${action}User`, userId);
                },
              }
            );
            break;

          case "unban":
            await authClient.admin.unbanUser(
              {
                userId,
              },
              {
                onSuccess() {
                  toast({
                    variant: "success",
                    message: "User unbanned successfully",
                  });
                },
                onError(ctx) {
                  console.log({ ctx });
                  handleError(ctx?.error, `${action}User`, userId);
                },
              }
            );
            break;

          case "remove":
            await authClient.admin.removeUser(
              { userId },
              {
                onSuccess() {
                  toast({
                    variant: "success",
                    message: "User removed successfully",
                  });
                },
                onError(ctx) {
                  console.log({ ctx });
                  handleError(ctx?.error, `${action}User`, userId);
                },
              }
            );
            break;

          case "setRole":
            await authClient.admin.setRole(
              { userId, role: data.role },
              {
                onSuccess() {
                  toast({
                    variant: "success",
                    message: "User role updated successfully",
                  });
                },
                onError(ctx) {
                  console.log({ ctx });
                  handleError(ctx?.error, action, userId);
                },
              }
            );
            break;

          case "revokeSessions":
            await authClient.admin.revokeUserSessions(
              { userId },
              {
                onSuccess() {
                  toast({
                    variant: "success",
                    message: "User sessions revoked successfully",
                  });
                },
                onError(ctx) {
                  console.log({ ctx });
                  handleError(ctx?.error, action, userId);
                },
              }
            );
            break;

          default:
            throw new Error(`Unsupported action: ${action}`);
        }

        // Refresh user list after action
        fetchUsers({ silentRefetch: true });
        return { success: true };
      } catch (error) {
        return { success: false };
      } finally {
        setIsActionPending(false);
      }
    },
    [authClient, fetchUsers, isActionPending, toast, handleError, clearError]
  );

  // Retry the last failed operation
  const retry = useCallback(() => {
    if (!error) return;

    const { action, userId } = error;

    clearError();

    if (action === "fetchUsers") {
      fetchUsers({ retryCount: 1 });
    } else if (action?.endsWith("User") && userId) {
      // Extract the original action
      const originalAction = action.replace("User", "") as
        | "ban"
        | "unban"
        | "remove";
      handleUserAction(originalAction, userId);
    }
  }, [error, clearError, fetchUsers, handleUserAction]);

  // Fetch users when dependencies change
  useEffect(() => {
    fetchUsers({ silentRefetch: initialFetchDone });
  }, [fetchUsers, initialFetchDone]);

  return {
    // Data
    users,
    totalUsers,
    totalPages,

    // State
    isLoading,
    isRefetching, // New state for tracking silent refetches
    isActionPending,
    error,
    hasError,

    // Filters
    filters,
    updateFilters,

    // Actions
    fetchUsers,
    handleUserAction,
    retry,
    clearError,
  };
}
