import { useEffect, useState } from 'react';
import { useBanUserMutation, useCreateUserMutation, useDeleteUserMutation, useInviteUserMutation, useUnbanUserMutation, useUpdateUserMutation } from './queries';
import { IUserSchema, IUserFilterOptionsSchema } from '@/src/entities/models/users/users.model';
import { toast } from 'sonner';
import { set } from 'date-fns';
import { CreateUserSchema, defaulICreateUserSchemaValues, ICreateUserSchema } from '@/src/entities/models/users/create-user.model';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { defaulIInviteUserSchemaValues, IInviteUserSchema, InviteUserSchema } from '@/src/entities/models/users/invite-user.model';
import { useQueryClient } from '@tanstack/react-query';
import { useSendMagicLinkMutation, useSendPasswordRecoveryMutation } from '@/app/(pages)/(auth)/queries';
import { ValidBanDuration } from '@/app/_lib/types/ban-duration';
import { IUpdateUserSchema, UpdateUserSchema } from '@/src/entities/models/users/update-user.model';

export const useUsersHandlers = () => {
  const queryClient = useQueryClient();

  // Core mutations
  const { updateUser, isPending: isUpdatePending, errors: isUpdateError } = useUpdateUserMutation();
  const { deleteUser, isPending: isDeletePending } = useDeleteUserMutation();
  const { sendPasswordRecovery, isPending: isSendPasswordRecoveryPending } = useSendPasswordRecoveryMutation();
  const { sendMagicLink, isPending: isSendMagicLinkPending } = useSendMagicLinkMutation();
  const { banUser, isPending: isBanPending } = useBanUserMutation();
  const { unbanUser, isPending: isUnbanPending } = useUnbanUserMutation();


  /**
   * update a user by ID
   */

  const handleUpdateUser = async (userId: string, data: IUpdateUserSchema, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    await updateUser({ id: userId, data }, {
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: ["users"] });

        toast.success("User updated successfully");
        options?.onSuccess?.();
      },
      onError: (error) => {
        toast.error("Failed to update user");
        options?.onError?.(error);
      },
    });
  }

  /**
   * Deletes a user by ID
   */
  const handleDeleteUser = async (userId: string, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    await deleteUser(userId, {
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: ["users"] });
        toast.success("User deleted successfully");
        options?.onSuccess?.();
      },
      onError: (error) => {
        toast.error("Failed to delete user");
        options?.onError?.(error);
      },
    });
  };

  /**
   * Sends a password recovery email to the user
   */
  const handleSendPasswordRecovery = async (email: string, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    if (!email) {
      toast.error("No email address provided");
      options?.onError?.(new Error("No email address provided"));
      return;
    }

    await sendPasswordRecovery(email, {
      onSuccess: () => {
        toast.success("Recovery email sent");
        options?.onSuccess?.();
      },
      onError: (error) => {
        toast.error("Failed to send recovery email");
        options?.onError?.(error);
      },
    });
  };

  /**
   * Sends a magic link to the user's email
   */
  const handleSendMagicLink = async (email: string, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    if (!email) {
      toast.error("No email address provided");
      options?.onError?.(new Error("No email address provided"));
      return;
    }

    await sendMagicLink(email, {
      onSuccess: () => {
        toast.success("Magic link sent");
        options?.onSuccess?.();
      },
      onError: (error) => {
        toast.error("Failed to send magic link");
        options?.onError?.(error);
      },
    });
  };

  /**
   * Bans a user for the specified duration
   */
  const handleBanUser = async (userId: string, banDuration: ValidBanDuration = "24h", options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    await banUser({ credential: { id: userId }, data: { ban_duration: banDuration } }, {
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: ["users"] });
        toast.success("User banned successfully");
        options?.onSuccess?.();
      },
      onError: (error) => {
        toast.error("Failed to ban user");
        options?.onError?.(error);
      },
    });
  };

  /**
   * Unbans a user
   */
  const handleUnbanUser = async (userId: string, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    await unbanUser({ id: userId }, {
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: ["users"] });
        toast.success("User unbanned successfully");
        options?.onSuccess?.();
      },
      onError: (error) => {
        toast.error("Failed to unban user");
        options?.onError?.(error);
      },
    });
  };

  /**
   * Toggles a user's ban status
   */
  const handleToggleBan = async (user: { id: string, banned_until?: ValidBanDuration }, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void,
    banDuration?: ValidBanDuration
  }) => {
    if (user.banned_until) {
      await handleUnbanUser(user.id, options);
    } else {
      await handleBanUser(user.id, options?.banDuration, options);
    }
  };

  /**
   * Copies text to clipboard
   */
  const handleCopyItem = (item: string, options?: {
    onSuccess?: () => void,
    onError?: (error: unknown) => void
  }) => {
    if (!navigator.clipboard) {
      const error = new Error("Clipboard not supported");
      toast.error("Clipboard not supported");
      options?.onError?.(error);
      return;
    }

    if (!item) {
      const error = new Error("Nothing to copy");
      toast.error("Nothing to copy");
      options?.onError?.(error);
      return;
    }

    navigator.clipboard.writeText(item)
      .then(() => {
        toast.success("Copied to clipboard");
        options?.onSuccess?.();
      })
      .catch((error) => {
        toast.error("Failed to copy to clipboard");
        options?.onError?.(error);
      });
  };

  return {
    // Action handlers
    updateUser: handleUpdateUser,
    deleteUser: handleDeleteUser,
    sendPasswordRecovery: handleSendPasswordRecovery,
    sendMagicLink: handleSendMagicLink,
    banUser: handleBanUser,
    unbanUser: handleUnbanUser,
    toggleBan: handleToggleBan,
    copyToClipboard: handleCopyItem,

    // Loading states
    isUpdatePending,
    isDeletePending,
    isSendPasswordRecoveryPending,
    isSendMagicLinkPending,
    isBanPending,
    isUnbanPending,

    // Errors
    isUpdateError,
  };
};

// Specific handler for the component

export const useAddUserDialogHandler = ({ onUserAdded, onOpenChange }: {
  onUserAdded: () => void;
  onOpenChange: (open: boolean) => void;
}) => {

  const queryClient = useQueryClient();
  const { createUser, isPending } = useCreateUserMutation();

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors: errors },
    setError,
    getValues,
    clearErrors,
    watch,
  } = useForm<ICreateUserSchema>({
    resolver: zodResolver(CreateUserSchema),
    defaultValues: {
      email: "",
      password: "",
      email_confirm: true,
    }
  });

  const emailConfirm = watch("email_confirm");

  const onSubmit = handleSubmit(async (data) => {

    await createUser(data, {
      onSuccess: () => {

        queryClient.invalidateQueries({ queryKey: ["users"] });

        toast.success("User created successfully.");

        onUserAdded();
        onOpenChange(false);
        reset();
      },
      onError: (error) => {
        reset();
        toast.error(error.message);
      },
    });

  });

  const handleOpenChange = (open: boolean) => {
    if (!open) {
      reset();
    }
    onOpenChange(open);
  };

  return {
    register,
    handleSubmit: onSubmit,
    reset,
    errors,
    isPending,
    getValues,
    clearErrors,
    emailConfirm,
    handleOpenChange,
  };
}

export const useInviteUserHandler = ({ onUserInvited, onOpenChange }: {
  onUserInvited: () => void;
  onOpenChange: (open: boolean) => void;
}) => {

  const queryClient = useQueryClient();
  const { inviteUser, isPending } = useInviteUserMutation();

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors: errors },
    setError,
    getValues,
    clearErrors,
    watch,
  } = useForm<IInviteUserSchema>({
    resolver: zodResolver(InviteUserSchema),
    defaultValues: defaulIInviteUserSchemaValues
  })

  const onSubmit = handleSubmit(async (data) => {
    await inviteUser(data, {
      onSuccess: () => {

        queryClient.invalidateQueries({ queryKey: ["users"] });

        toast.success("Invitation sent");

        onUserInvited();
        onOpenChange(false);
        reset();
      },
      onError: () => {
        reset();
        toast.error("Failed to send invitation");
      },
    });
  });

  const handleOpenChange = (open: boolean) => {
    if (!open) {
      reset();
    }
    onOpenChange(open);
  };

  return {
    register,
    handleSubmit: onSubmit,
    handleOpenChange,
    reset,
    getValues,
    clearErrors,
    watch,
    errors,
    isPending,
  };
}


export const useUserDetailSheetHandlers = ({ open, user, onUserUpdated, onOpenChange }: {
  open: boolean;
  user: IUserSchema;
  onUserUpdated: () => void;
  onOpenChange: (open: boolean) => void;
}) => {
  const {
    deleteUser,
    sendPasswordRecovery,
    sendMagicLink,
    banUser,
    unbanUser,
    toggleBan,
    copyToClipboard,
    isDeletePending,
    isSendPasswordRecoveryPending,
    isSendMagicLinkPending,
    isBanPending,
    isUnbanPending,
  } = useUsersHandlers();

  const handleDeleteUser = async () => {
    await deleteUser(user.id, {
      onSuccess: () => {
        onOpenChange(false);
      }
    });
  };

  const handleSendPasswordRecovery = async () => {
    if (!user.email) {
      toast.error("User has no email address");
      return;
    }
    await sendPasswordRecovery(user.email);
  };

  const handleSendMagicLink = async () => {
    if (!user.email) {
      toast.error("User has no email address");
      return;
    }
    await sendMagicLink(user.email);
  };

  const handleBanUser = async () => {
    await banUser(user.id, "24h", {
      onSuccess: onUserUpdated
    });
  };

  const handleUnbanUser = async () => {
    await unbanUser(user.id, {
      onSuccess: onUserUpdated
    });
  };

  const handleToggleBan = async () => {
    await toggleBan({ id: user.id }, {
      onSuccess: onUserUpdated
    });
  };

  return {
    handleDeleteUser,
    handleSendPasswordRecovery,
    handleSendMagicLink,
    handleBanUser,
    handleUnbanUser,
    handleToggleBan,
    handleCopyItem: copyToClipboard,
    isDeletePending,
    isSendPasswordRecoveryPending,
    isSendMagicLinkPending,
    isBanPending,
    isUnbanPending,
  };
};

export const useUserProfileSheetHandlers = ({ open, onOpenChange, userData, onUserUpdated }: {
  open: boolean;
  userData: IUserSchema;
  onOpenChange: (open: boolean) => void;
  onUserUpdated: () => void;
}) => {

  const { updateUser, isUpdatePending, isUpdateError } = useUsersHandlers();

  // Initialize form with user data
  const form = useForm<IUpdateUserSchema>({
    resolver: zodResolver(UpdateUserSchema),
    defaultValues: {
      email: userData?.email || undefined,
      encrypted_password: userData?.encrypted_password || undefined,
      role: (userData?.role as "user" | "staff" | "admin") || "user",
      phone: userData?.phone || undefined,
      invited_at: userData?.invited_at || undefined,
      confirmed_at: userData?.confirmed_at || undefined,
      // recovery_sent_at: userData?.recovery_sent_at || undefined,
      last_sign_in_at: userData?.last_sign_in_at || undefined,
      created_at: userData?.created_at || undefined,
      updated_at: userData?.updated_at || undefined,
      is_anonymous: userData?.is_anonymous || false,
      profile: {
        // id: userData?.profile?.id || undefined,
        // user_id: userData?.profile?.user_id || undefined,
        avatar: userData?.profile?.avatar || undefined,
        username: userData?.profile?.username || undefined,
        first_name: userData?.profile?.first_name || undefined,
        last_name: userData?.profile?.last_name || undefined,
        bio: userData?.profile?.bio || undefined,
        address: userData?.profile?.address || {
          street: "",
          city: "",
          state: "",
          country: "",
          postal_code: "",
        },
        birth_date: userData?.profile?.birth_date ? new Date(userData.profile.birth_date) : undefined,
      },
    },
  })

  const handleUpdateUser = async () => {
    await updateUser(userData.id, form.getValues(), {
      onSuccess: () => {
        onUserUpdated();
        onOpenChange(false);
      },
      onError: () => {
        onOpenChange(false);
      },
    });

  }

  return {
    handleUpdateUser,
    form,
    isUpdatePending,
  };
}

export const useUserManagementHandlers = (refetch: () => void) => {
  const [searchQuery, setSearchQuery] = useState("")
  const [detailUser, setDetailUser] = useState<IUserSchema | null>(null)
  const [updateUser, setUpdateUser] = useState<IUserSchema | null>(null)
  const [isSheetOpen, setIsSheetOpen] = useState(false)
  const [isUpdateOpen, setIsUpdateOpen] = useState(false)
  const [isAddUserOpen, setIsAddUserOpen] = useState(false)
  const [isInviteUserOpen, setIsInviteUserOpen] = useState(false)

  // Filter states
  const [filters, setFilters] = useState<IUserFilterOptionsSchema>({
    email: "",
    phone: "",
    lastSignIn: "",
    createdAt: "",
    status: [],
  })

  // Handle opening the detail sheet
  const handleUserClick = (user: IUserSchema) => {
    setDetailUser(user)
    setIsSheetOpen(true)
  }

  // Handle opening the update sheet
  const handleUserUpdate = (user: IUserSchema) => {
    setUpdateUser(user)
    setIsUpdateOpen(true)
  }

  // Close detail sheet when update sheet opens
  useEffect(() => {
    if (isUpdateOpen) {
      setIsSheetOpen(false)
    }
  }, [isUpdateOpen])

  // Reset detail user when sheet closes
  useEffect(() => {
    if (!isSheetOpen) {
      // Use a small delay to prevent flickering if another sheet is opening
      const timer = setTimeout(() => {
        if (!isSheetOpen && !isUpdateOpen) {
          setDetailUser(null)
        }
      }, 300)
      return () => clearTimeout(timer)
    }
  }, [isSheetOpen, isUpdateOpen])

  // Reset update user when update sheet closes
  useEffect(() => {
    if (!isUpdateOpen) {
      // Use a small delay to prevent flickering if another sheet is opening
      const timer = setTimeout(() => {
        if (!isUpdateOpen) {
          setUpdateUser(null)
        }
      }, 300)
      return () => clearTimeout(timer)
    }
  }, [isUpdateOpen])

  const clearFilters = () => {
    setFilters({
      email: "",
      phone: "",
      lastSignIn: "",
      createdAt: "",
      status: [],
    })
  }

  const getActiveFilterCount = () => {
    return Object.values(filters).filter(
      (value) => (typeof value === "string" && value !== "") || (Array.isArray(value) && value.length > 0),
    ).length
  }

  return {
    searchQuery,
    setSearchQuery,
    detailUser,
    updateUser,
    isSheetOpen,
    setIsSheetOpen,
    isUpdateOpen,
    setIsUpdateOpen,
    isAddUserOpen,
    setIsAddUserOpen,
    isInviteUserOpen,
    setIsInviteUserOpen,
    filters,
    setFilters,
    handleUserClick,
    handleUserUpdate,
    clearFilters,
    getActiveFilterCount,
  }
}

export const filterUsers = (users: IUserSchema[], searchQuery: string, filters: IUserFilterOptionsSchema): IUserSchema[] => {
  return users.filter((user) => {

    // Global search
    if (searchQuery) {
      const query = searchQuery.toLowerCase()
      const matchesSearch =
        user.email?.toLowerCase().includes(query) ||
        user.phone?.toLowerCase().includes(query) ||
        user.id.toLowerCase().includes(query)

      if (!matchesSearch) return false
    }

    // Email filter
    if (filters.email && !user.email?.toLowerCase().includes(filters.email.toLowerCase())) {
      return false
    }

    // Phone filter
    if (filters.phone && !user.phone?.toLowerCase().includes(filters.phone.toLowerCase())) {
      return false
    }

    // Last sign in filter
    if (filters.lastSignIn) {
      if (filters.lastSignIn === "never" && user.last_sign_in_at) {
        return false
      } else if (filters.lastSignIn === "today") {
        const today = new Date()
        today.setHours(0, 0, 0, 0)
        const signInDate = user.last_sign_in_at ? new Date(user.last_sign_in_at) : null
        if (!signInDate || signInDate < today) return false
      } else if (filters.lastSignIn === "week") {
        const weekAgo = new Date()
        weekAgo.setDate(weekAgo.getDate() - 7)
        const signInDate = user.last_sign_in_at ? new Date(user.last_sign_in_at) : null
        if (!signInDate || signInDate < weekAgo) return false
      } else if (filters.lastSignIn === "month") {
        const monthAgo = new Date()
        monthAgo.setMonth(monthAgo.getMonth() - 1)
        const signInDate = user.last_sign_in_at ? new Date(user.last_sign_in_at) : null
        if (!signInDate || signInDate < monthAgo) return false
      }
    }

    // Created at filter
    if (filters.createdAt) {
      if (filters.createdAt === "today") {
        const today = new Date()
        today.setHours(0, 0, 0, 0)
        const createdAt = user.created_at ? (user.created_at ? new Date(user.created_at) : new Date()) : new Date()
        if (createdAt < today) return false
      } else if (filters.createdAt === "week") {
        const weekAgo = new Date()
        weekAgo.setDate(weekAgo.getDate() - 7)
        const createdAt = user.created_at ? new Date(user.created_at) : new Date()
        if (createdAt < weekAgo) return false
      } else if (filters.createdAt === "month") {
        const monthAgo = new Date()
        monthAgo.setMonth(monthAgo.getMonth() - 1)
        const createdAt = user.created_at ? new Date(user.created_at) : new Date()
        if (createdAt < monthAgo) return false
      }
    }

    // Status filter
    if (filters.status.length > 0) {
      const userStatus = user.banned_until ? "banned" : !user.email_confirmed_at ? "unconfirmed" : "active"

      if (!filters.status.includes(userStatus)) {
        return false
      }
    }

    return true
  })
}