import { ActionPanel, Button, Dialog, useNavigate } from "@tailor-platform/app-shell";
import { Pencil, UserX, UserCheck, ShieldPlus, ArrowLeft } from "lucide-react";
import { useState } from "react";
import { useMutation, useQuery } from "urql";
import { graphql, type FragmentOf, readFragment } from "@/graphql";
import { useToast } from "@/hooks/use-toast";

const DeactivateUserMutation = graphql(`
  mutation DeactivateUser($userId: ID!) {
    deactivateUser(userId: $userId) {
      id
      status
    }
  }
`);

const ReactivateUserMutation = graphql(`
  mutation ReactivateUser($userId: ID!) {
    reactivateUser(userId: $userId) {
      id
      status
    }
  }
`);

const UpdateUserRolesMutation = graphql(`
  mutation UpdateUserRoles($userId: ID!, $roleIds: [ID!]!) {
    updateUserRoles(userId: $userId, roleIds: $roleIds) {
      userId
    }
  }
`);

const RolesForAssignQuery = graphql(`
  query RolesForAssign {
    roles {
      edges {
        node {
          id
          name
        }
      }
    }
  }
`);

const MeForActionsQuery = graphql(`
  query MeForActions {
    me {
      id
    }
  }
`);

export const UserActionsFragment = graphql(`
  fragment UserActions on User {
    id
    status
    userRoles {
      edges {
        node {
          role {
            id
          }
        }
      }
    }
  }
`);

interface UserActionsProps {
  user: FragmentOf<typeof UserActionsFragment>;
}

export const UserActions = ({ user: userFragment }: UserActionsProps) => {
  const user = readFragment(UserActionsFragment, userFragment);
  const navigate = useNavigate();
  const toast = useToast();
  const [{ fetching: deactivating }, deactivateUser] = useMutation(DeactivateUserMutation);
  const [{ fetching: reactivating }, reactivateUser] = useMutation(ReactivateUserMutation);
  const [{ fetching: updating }, updateUserRoles] = useMutation(UpdateUserRolesMutation);
  const [{ data: rolesData }] = useQuery({ query: RolesForAssignQuery });
  const [{ data: meData }] = useQuery({ query: MeForActionsQuery });
  const [dialogOpen, setDialogOpen] = useState(false);

  const currentRoleIds = new Set(
    user.userRoles.edges.filter((e) => e.node.role != null).map((e) => e.node.role!.id),
  );
  const [selectedRoleIds, setSelectedRoleIds] = useState<Set<string>>(
    () => new Set(currentRoleIds),
  );

  const roles = rolesData?.roles.edges.map((edge) => edge.node) ?? [];
  const isSelf = meData?.me?.id === user.id;

  const toggleRole = (id: string) => {
    setSelectedRoleIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const handleSaveRoles = () => {
    void updateUserRoles(
      { userId: user.id, roleIds: [...selectedRoleIds] },
      { additionalTypenames: ["User", "UserRole"] },
    ).then((result) => {
      if (result.error) {
        toast.error(result.error);
        return;
      }
      toast.success("Roles updated successfully");
      setDialogOpen(false);
    });
  };

  return (
    <>
      <ActionPanel
        title="Actions"
        actions={[
          {
            key: "edit",
            label: "Edit User",
            icon: <Pencil />,
            onClick: () => navigate("edit"),
          },
          ...(user.status === "ACTIVE" && !isSelf
            ? [
                {
                  key: "deactivate",
                  label: "Deactivate User",
                  icon: <UserX />,
                  variant: "destructive" as const,
                  loading: deactivating,
                  onClick: () =>
                    deactivateUser({ userId: user.id }, { additionalTypenames: ["User"] }).then(
                      (result) => {
                        if (result.error) {
                          toast.error(result.error);
                          return;
                        }
                        toast.success("User deactivated successfully");
                      },
                    ),
                },
              ]
            : []),
          ...(user.status === "INACTIVE"
            ? [
                {
                  key: "reactivate",
                  label: "Reactivate User",
                  icon: <UserCheck />,
                  loading: reactivating,
                  onClick: () =>
                    reactivateUser({ userId: user.id }, { additionalTypenames: ["User"] }).then(
                      (result) => {
                        if (result.error) {
                          toast.error(result.error);
                          return;
                        }
                        toast.success("User reactivated successfully");
                      },
                    ),
                },
              ]
            : []),
          ...(user.status === "ACTIVE"
            ? [
                {
                  key: "manage-roles",
                  label: "Manage Roles",
                  icon: <ShieldPlus />,
                  onClick: () => {
                    setSelectedRoleIds(new Set(currentRoleIds));
                    setDialogOpen(true);
                  },
                },
              ]
            : []),
          {
            key: "back",
            label: "Back to User List",
            icon: <ArrowLeft />,
            onClick: () => navigate("/user-management/user"),
          },
        ]}
      />
      <Dialog.Root open={dialogOpen} onOpenChange={setDialogOpen}>
        <Dialog.Content>
          <Dialog.Header>
            <Dialog.Title>Manage Roles</Dialog.Title>
            <Dialog.Description>Select the roles for this user.</Dialog.Description>
          </Dialog.Header>
          <div className="max-h-60 space-y-1 overflow-y-auto py-4">
            {roles.map((role) => (
              <label
                key={role.id}
                className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-accent"
              >
                <input
                  type="checkbox"
                  checked={selectedRoleIds.has(role.id)}
                  onChange={() => toggleRole(role.id)}
                  className="h-4 w-4 rounded border-gray-300"
                />
                <span className="text-sm">{role.name}</span>
              </label>
            ))}
            {roles.length === 0 && (
              <p className="text-muted-foreground text-sm">No roles available</p>
            )}
          </div>
          <Dialog.Footer>
            <Button variant="outline" onClick={() => setDialogOpen(false)}>
              Cancel
            </Button>
            <Button onClick={handleSaveRoles} disabled={updating}>
              {updating ? "Saving..." : "Save"}
            </Button>
          </Dialog.Footer>
        </Dialog.Content>
      </Dialog.Root>
    </>
  );
};
