import { useEffect, useMemo, useState, useDeferredValue } from "react";
import { View, Text, ScrollView, GestureResponderEvent } from "react-native";

import { LoadingSpinner } from "@/components/ui/LoadingSpinner";
import { NoData } from "@/components/ui/NoData";
import {
  useGetUsersQuery,
  useCreateUserMutation,
  useUpdateUserMutation,
  useDeleteUserMutation,
  useResendInvitationMutation,
} from "@/store/api/usersApi";
import { AdminAccountsTableControls } from "@/components/features/admins/AdminAccountsTableControls";
import { DesktopAdminAccountsTable } from "@/components/features/admins/DesktopAdminAccountsTable";
import { MobileAdminAccountsTable } from "@/components/features/admins/MobileAdminAccountsTable";
import { TablePagination } from "@/components/shared/TablePagination";
import { useAppSelector } from "@/store/hooks";
import { selectIsMobile } from "@/store/screen/screenSizeSlice";
import { TableSortDirection } from "@/constants/tableSortDirectionEnum";
import { AdminModal } from "@/components/features/admins/AdminModal";
import { OperationMode } from "@/constants/operationModeEnum";
import { DeleteUserModal } from "@/components/features/users/DeleteUserModal";
import { User } from "@/store/models/User.model";
import { AppSnackbar } from "@/components/ui/AppSnackbar";

interface AdminAccountsTableProps {
  initialSearchQuery?: string;
}

export const AdminAccountsTable = ({
  initialSearchQuery = "",
}: AdminAccountsTableProps) => {
  const [page, setPage] = useState(0);
  const [itemsPerPage, setItemsPerPage] = useState(25);
  const [searchQuery, setSearchQuery] = useState("");
  const [sortColumn, setSortColumn] = useState<string | null>(null);
  const [sortDirection, setSortDirection] = useState<TableSortDirection>(
    TableSortDirection.ASCENDING
  );

  const deferredSearch = useDeferredValue(searchQuery);
  const [debouncedSearch, setDebouncedSearch] = useState("");

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

  const {
    data: adminsPageData,
    isLoading,
    error: fetchError,
    refetch,
    isFetching,
  } = useGetUsersQuery(queryArgs, { refetchOnMountOrArgChange: true });
  const adminUsers = adminsPageData?.items ?? [];
  const [createAdmin, { isLoading: isCreating }] = useCreateUserMutation();
  const [updateAdmin, { isLoading: isUpdating }] = useUpdateUserMutation();
  const [deleteAdmin, { isLoading: isDeleting }] = useDeleteUserMutation();
  const [resendInvitation, { isLoading: isResending }] =
    useResendInvitationMutation();

  const [menuVisible, setMenuVisible] = useState(false);
  const [menuAnchor, setMenuAnchor] = useState({ x: 0, y: 0 });
  const [addAdminModalVisible, setAddAdminModalVisible] = useState(false);
  const [editModalVisible, setEditModalVisible] = useState(false);
  const [deleteModalVisible, setDeleteModalVisible] = useState(false);
  const [currentAdmin, setCurrentAdmin] = useState<User | null>(null);
  const [snackbarMessage, setSnackbarMessage] = useState("");
  const [snackbarVisible, setSnackbarVisible] = useState(false);

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

  const totalItems = adminsPageData?.total ?? 0;
  const from = adminUsers.length ? page * itemsPerPage + 1 : 0;
  const to = adminUsers.length
    ? Math.min(from + adminUsers.length - 1, totalItems)
    : 0;

  const isMobile = useAppSelector(selectIsMobile);

  const handleSearch = (query: string) => {
    setSearchQuery(query);
    setPage(0);
  };

  const handleSort = (column: string) => {
    setSortColumn(column);
    setSortDirection(
      sortDirection === TableSortDirection.ASCENDING
        ? TableSortDirection.DESCENDING
        : TableSortDirection.ASCENDING
    );
    setPage(0);
  };

  const handleItemsPerPageChange = (count: number) => {
    setItemsPerPage(count);
  };

  const handleCreateAdmin = async (admin: Partial<User>) => {
    try {
      await createAdmin(admin).unwrap();
      showSnackbar(
        `${admin.firstName} ${admin.lastName} created. Invitation email sent if no password was provided.`
      );
      setAddAdminModalVisible(false);
    } catch {
      showSnackbar("Error creating admin");
    }
  };

  const handleUpdateAdmin = async (admin: Partial<User>) => {
    try {
      await updateAdmin(admin).unwrap();
      showSnackbar(`${admin.firstName} ${admin.lastName} updated successfully`);
      setEditModalVisible(false);
    } catch {
      showSnackbar("Error updating admin");
    }
  };

  const handleDeleteAdmin = async (admin: User) => {
    try {
      await deleteAdmin(admin.id).unwrap();
      showSnackbar(`${admin.firstName} ${admin.lastName} deleted successfully`);
      setDeleteModalVisible(false);
    } catch {
      showSnackbar("Error deleting admin");
    }
  };

  const handleResendInvite = async (admin: User) => {
    try {
      await resendInvitation(admin.id).unwrap();
      showSnackbar(`Invitation resent to ${admin.email}`);
    } catch {
      showSnackbar("Error resending invitation");
    }
  };

  const handleEdit = (admin: User) => {
    setCurrentAdmin(admin);
    setEditModalVisible(true);
  };

  const openDeleteModal = (admin: User) => {
    setCurrentAdmin(admin);
    setDeleteModalVisible(true);
  };

  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(deferredSearch.trim()), 450);
    return () => clearTimeout(t);
  }, [deferredSearch]);

  useEffect(() => {
    const q = (initialSearchQuery || "").trim();
    if (q && q !== searchQuery) {
      setSearchQuery(q);
      setPage(0);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [initialSearchQuery]);

  useEffect(() => {
    setPage(0);
  }, [itemsPerPage]);

  return (
    <>
      <View className="flex-1">
        <Text
          className={`text-2xl font-bold ${
            isMobile ? "mb-1" : "mb-4"
          } text-white`}
        >
          Admins manager
        </Text>
        <View
          className={`bg-lightGray rounded-lg ${
            isMobile ? "p-1" : "p-5"
          } flex-1`}
        >
          {isLoading ? (
            <View className="flex-1 justify-center items-center">
              <LoadingSpinner />
              <Text className="mt-2">Loading admins...</Text>
            </View>
          ) : fetchError ? (
            <NoData
              message="Error loading admins"
              onRetry={refetch}
              isRetrying={isFetching}
            />
          ) : (
            <View className="flex-1">
              <AdminAccountsTableControls
                searchQuery={searchQuery}
                menuVisible={menuVisible}
                menuAnchor={menuAnchor}
                onSearch={handleSearch}
                onMenuDismiss={() => setMenuVisible(false)}
                onItemsPerPageChange={handleItemsPerPageChange}
                onAddAdmin={() => setAddAdminModalVisible(true)}
              />

              <AdminModal
                visible={addAdminModalVisible}
                onClose={() => setAddAdminModalVisible(false)}
                onSubmit={handleCreateAdmin}
                isLoading={isCreating}
                mode={OperationMode.ADD}
              />

              <AdminModal
                visible={editModalVisible}
                admin={currentAdmin}
                onClose={() => setEditModalVisible(false)}
                onSubmit={handleUpdateAdmin}
                isLoading={isUpdating}
                mode={OperationMode.EDIT}
              />

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

              <View className="flex-1 overflow-hidden">
                {searchQuery && adminUsers.length === 0 ? (
                  <View
                    className={`flex-1 items-center justify-center ${
                      isMobile ? "p-1" : "p-5"
                    }`}
                  >
                    <Text className="text-lg text-gray-500">
                      No admins match your search for &quot;{searchQuery}&quot;
                    </Text>
                  </View>
                ) : searchQuery.length === 0 && adminUsers.length === 0 ? (
                  <View
                    className={`flex-1 items-center justify-center ${
                      isMobile ? "p-1" : "p-5"
                    }`}
                  >
                    <Text className="text-lg text-gray-500">
                      No admins found
                    </Text>
                  </View>
                ) : isMobile ? (
                  <View className="flex-1">
                    <MobileAdminAccountsTable
                      admins={adminUsers}
                      onEdit={handleEdit}
                      onDelete={openDeleteModal}
                      onResend={handleResendInvite}
                      isResending={isResending}
                    />
                  </View>
                ) : (
                  <ScrollView className="flex-1 h-96">
                    <DesktopAdminAccountsTable
                      admins={adminUsers}
                      sortColumn={sortColumn}
                      sortDirection={sortDirection}
                      onSort={handleSort}
                      onEdit={handleEdit}
                      onDelete={openDeleteModal}
                      onResend={handleResendInvite}
                      isResending={isResending}
                    />
                  </ScrollView>
                )}
              </View>

              <TablePagination
                page={page}
                itemsPerPage={itemsPerPage}
                totalItems={totalItems}
                from={from}
                to={to}
                onPageChange={setPage}
                onItemsPerPageButtonPress={(event: GestureResponderEvent) => {
                  const { pageX, pageY } = event.nativeEvent;
                  setMenuAnchor({ x: pageX, y: pageY });
                  setMenuVisible(true);
                }}
              />
            </View>
          )}
        </View>
      </View>
      <AppSnackbar
        visible={snackbarVisible}
        onDismiss={() => setSnackbarVisible(false)}
        action={{ label: "Close", onPress: () => setSnackbarVisible(false) }}
      >
        {snackbarMessage}
      </AppSnackbar>
    </>
  );
};
