import { useEffect, useMemo, useState, useDeferredValue } from "react";
import { useLocalSearchParams } from "expo-router";
import { View, Text } from "react-native";

import { UserAccountsTable } from "@/components/features/users/UserAccountsTable";
import { UserModal } from "@/components/features/users/UserModal";
import { User } from "@/store/models/User.model";
import { LoadingSpinner } from "@/components/ui/LoadingSpinner";
import {
  useDeleteUserMutation,
  useGetUsersQuery,
  useLockUserMutation,
  useUpdateUserMutation,
  useDeleteUsersMutation,
  useCreateUserMutation,
} from "@/store/api/usersApi";
import { BulkDeleteUserModal } from "@/components/features/users/BulkDeleteUserModal";
import { LockUserModal } from "@/components/features/users/LockUserModal";
import { DeleteUserModal } from "@/components/features/users/DeleteUserModal";
import { NoData } from "@/components/ui/NoData";
import { TableSortDirection } from "@/constants/tableSortDirectionEnum";
import { RiskEnum } from "@/constants/riskEnum";
import { useAuthContext } from "@/auth/AuthContext";
import { OperationMode } from "@/constants/operationModeEnum";
import { useAppSelector } from "@/store/hooks";
import { selectIsMobile } from "@/store/screen/screenSizeSlice";
import { AppSnackbar } from "@/components/ui/AppSnackbar";

export const UsersPage = () => {
  const params = useLocalSearchParams<{ q?: string }>();
  const { user } = useAuthContext();
  const [page, setPage] = useState(0);
  const [itemsPerPage, setItemsPerPage] = useState(25);
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedRisks, setSelectedRisks] = useState<RiskEnum[]>([]);
  const [sortColumn, setSortColumn] = useState<string | null>(null);
  const [sortDirection, setSortDirection] = useState<TableSortDirection>(
    TableSortDirection.ASCENDING
  );
  const isMobile = useAppSelector(selectIsMobile);

  const deferredSearch = useDeferredValue(searchQuery);
  const [debouncedSearch, setDebouncedSearch] = useState(deferredSearch);
  useEffect(() => {
    const handler = setTimeout(
      () => setDebouncedSearch(deferredSearch.trim()),
      450
    );
    return () => clearTimeout(handler);
  }, [deferredSearch]);

  // Initialize search query from route param
  useEffect(() => {
    const qParam = (params.q ?? "").toString().trim();
    if (qParam && qParam !== searchQuery) {
      setSearchQuery(qParam);
      setPage(0);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [params.q]);

  const queryArgs = useMemo(() => {
    const allowedSorts = ["name", "email", "title", "risk"] as const;
    const sortBy = (allowedSorts as readonly string[]).includes(
      sortColumn || ""
    )
      ? (sortColumn as (typeof allowedSorts)[number])
      : undefined;
    const sortDir = sortDirection;
    const risks = selectedRisks.length ? selectedRisks : undefined;
    const searchParam =
      debouncedSearch && debouncedSearch.length >= 2
        ? debouncedSearch
        : undefined;
    return {
      roleType: "user" as const,
      page: page + 1,
      limit: itemsPerPage,
      search: searchParam,
      risks,
      sortBy,
      sortDir,
    };
  }, [
    page,
    itemsPerPage,
    debouncedSearch,
    selectedRisks,
    sortColumn,
    sortDirection,
  ]);

  const {
    data: usersPage,
    isLoading,
    error,
    refetch,
    isFetching,
  } = useGetUsersQuery(queryArgs, {
    refetchOnMountOrArgChange: true,
    refetchOnFocus: true,
    refetchOnReconnect: true,
  });

  const users = usersPage?.items ?? [];
  const totalItems = usersPage?.total ?? 0;
  const from = users.length ? page * itemsPerPage + 1 : 0;
  const to = users.length ? Math.min(from + users.length - 1, totalItems) : 0;

  const [deleteUser, { isLoading: isDeleting }] = useDeleteUserMutation();
  const [lockUser, { isLoading: isLocking }] = useLockUserMutation();
  const [updateUser, { isLoading: isUpdating }] = useUpdateUserMutation();
  const [createUser, { isLoading: isCreating }] = useCreateUserMutation();
  const [bulkDeleteUsers, { isLoading: isBulkDeleting }] =
    useDeleteUsersMutation();
  const [userModalVisible, setUserModalVisible] = useState(false);
  const [userModalMode, setUserModalMode] = useState<OperationMode>(
    OperationMode.ADD
  );
  const [deleteModalVisible, setDeleteModalVisible] = useState(false);
  const [bulkDeleteModalVisible, setBulkDeleteModalVisible] = useState(false);
  const [lockModalVisible, setLockModalVisible] = useState(false);
  const [currentUser, setCurrentUser] = useState<User | null>(null);
  const [selectedUsersIds, setSelectedUsersIds] = useState<string[]>([]);
  const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
  const [snackbarVisible, setSnackbarVisible] = useState(false);
  const [snackbarMessage, setSnackbarMessage] = useState("");

  const showSnackbar = (message: string) => {
    setSnackbarMessage(message);
    setSnackbarVisible(true);
  };

  const handleEdit = (user: User) => {
    setCurrentUser(user);
    setUserModalMode(OperationMode.EDIT);
    setUserModalVisible(true);
  };

  const handleAddUser = () => {
    setCurrentUser(null);
    setUserModalMode(OperationMode.ADD);
    setUserModalVisible(true);
  };

  const openDeleteModal = (user: User) => {
    setCurrentUser(user);
    setDeleteModalVisible(true);
  };

  const openLockModal = (user: User) => {
    setCurrentUser(user);
    setLockModalVisible(true);
  };

  const handleDeleteUser = async (user: User) => {
    try {
      await deleteUser(user.id).unwrap();
      if (selectedUsersIds.includes(user.id)) {
        setSelectedUsersIds(selectedUsersIds.filter((id) => id !== user.id));
      }
      refetch();
      showSnackbar(
        `${user.firstName} ${user.lastName} has been deleted successfully`
      );
      setDeleteModalVisible(false);
    } catch (error) {
      console.error(
        `Error deleting user ${user.firstName} ${user.lastName}:`,
        error
      );
      showSnackbar(`Error deleting ${user.firstName} ${user.lastName}`);
    }
  };

  const handleLockUser = async (user: User) => {
    const action = user.isLocked ? "unlock" : "lock";
    try {
      await lockUser(user.id).unwrap();
      refetch();
      showSnackbar(
        `${user.firstName} ${user.lastName} has been ${action}ed successfully`
      );
      setLockModalVisible(false);
    } catch (error) {
      console.error(
        `Error ${action}ing user ${user.firstName} ${user.lastName}:`,
        error
      );
      showSnackbar(`Error ${action}ing ${user.firstName} ${user.lastName}`);
    }
  };

  const handleBulkDeleteUsers = (users: User[]) => {
    if (users.length === 0) return;

    setSelectedUsersIds(users.map((user) => user.id));
    setSelectedUsers(users);
    setBulkDeleteModalVisible(true);
  };

  const confirmBulkDelete = async () => {
    if (selectedUsersIds.length === 0) return;

    try {
      const userIds = selectedUsersIds;
      const count = selectedUsersIds.length;
      await bulkDeleteUsers(userIds).unwrap();
      refetch();
      showSnackbar(`${count} users deleted successfully`);
      setBulkDeleteModalVisible(false);
      setSelectedUsersIds([]);
    } catch (error: any) {
      console.error(`Error deleting multiple users:`, error);
      const errorMessage =
        error?.data?.error ||
        error?.data?.details ||
        "Error deleting multiple users";
      showSnackbar(errorMessage);
    }
  };

  const handleSubmitUser = async (payload: Partial<User>) => {
    try {
      if (userModalMode === OperationMode.EDIT) {
        await updateUser(payload as User).unwrap();
        showSnackbar(
          `${payload.firstName} ${payload.lastName} updated successfully`
        );
      } else {
        const res = await createUser(payload).unwrap();
        showSnackbar(
          `${res.firstName} ${res.lastName} added successfully${
            !res.isActivated ? " and invitation sent" : ""
          }`
        );
      }
      setUserModalVisible(false);
      refetch();
    } catch (error) {
      console.error(`Error saving user:`, error);
      showSnackbar(`Error saving user`);
    }
  };

  useEffect(() => {
    // Refetch when auth user state changes (e.g., after activation/login)
    refetch();
  }, [user?.id, user?.isActivated, refetch]);

  return (
    <>
      <View
        className={`flex-1 bg-primaryPurpleLight ${isMobile ? "p-1" : "p-5"}`}
      >
        <Text
          className={`text-2xl font-bold ${
            isMobile ? "mb-1" : "mb-4"
          } text-white`}
        >
          Users manager
        </Text>

        <View
          className={`bg-lightGray rounded-lg ${
            isMobile ? "p-1" : "p-5"
          } flex-1`}
        >
          {isLoading ? (
            <View className="flex-1 justify-center items-center py-10">
              <LoadingSpinner />
              <Text className="mt-2">Loading users...</Text>
            </View>
          ) : error ? (
            <View className="flex-1 justify-center items-center py-10">
              <NoData
                message="Error loading users"
                onRetry={refetch}
                isRetrying={isFetching}
              />
            </View>
          ) : (
            <UserAccountsTable
              users={users}
              onSelect={setSelectedUsersIds}
              selectedUserIds={selectedUsersIds}
              onEdit={handleEdit}
              onAddUser={handleAddUser}
              onDelete={openDeleteModal}
              onLock={openLockModal}
              onBulkDelete={handleBulkDeleteUsers}
              page={page}
              itemsPerPage={itemsPerPage}
              totalItems={totalItems}
              from={from}
              to={to}
              searchQuery={searchQuery}
              selectedRisks={selectedRisks}
              sortColumn={sortColumn}
              sortDirection={sortDirection}
              onAddingUser={isCreating}
              onSearch={(q) => {
                setSearchQuery(q);
                setPage(0);
              }}
              onSelectRisks={(risks) => {
                setSelectedRisks(risks);
                setPage(0);
              }}
              onSort={(column) => {
                if (sortColumn === column) {
                  setSortDirection((d) =>
                    d === TableSortDirection.ASCENDING
                      ? TableSortDirection.DESCENDING
                      : TableSortDirection.ASCENDING
                  );
                } else {
                  setSortColumn(column);
                  setSortDirection(TableSortDirection.ASCENDING);
                }
                setPage(0);
              }}
              onItemsPerPageChange={(value) => {
                setItemsPerPage(value);
                setPage(0);
              }}
              onPageChange={(newPage) => setPage(newPage)}
            />
          )}
        </View>

        <UserModal
          visible={userModalVisible}
          mode={userModalMode}
          user={currentUser}
          onClose={() => setUserModalVisible(false)}
          onSubmit={handleSubmitUser}
          isLoading={isUpdating || isCreating}
        />

        <DeleteUserModal
          visible={deleteModalVisible}
          user={currentUser}
          onDismiss={() => setDeleteModalVisible(false)}
          onDelete={handleDeleteUser}
          isLoading={isDeleting}
        />

        <BulkDeleteUserModal
          visible={bulkDeleteModalVisible}
          users={selectedUsers}
          onDismiss={() => setBulkDeleteModalVisible(false)}
          onDelete={confirmBulkDelete}
          isLoading={isBulkDeleting}
        />

        <LockUserModal
          visible={lockModalVisible}
          user={currentUser}
          onDismiss={() => setLockModalVisible(false)}
          onLock={handleLockUser}
          isLoading={isLocking}
        />
      </View>

      <AppSnackbar
        visible={snackbarVisible}
        onDismiss={() => setSnackbarVisible(false)}
        action={{ label: "Close", onPress: () => setSnackbarVisible(false) }}
      >
        {snackbarMessage}
      </AppSnackbar>
    </>
  );
};
