#' Metadata about a remote table
#'
#' `remote_name()` gives the unescaped name of the remote table, or `NULL` if it
#' is a query (created by `sql()`) or already escape (created by `ident_q()`).
#' `remote_table()` gives the remote table or the query.
#' `remote_query()` gives the text of the query, and `remote_query_plan()`
#' the query plan (as computed by the remote database). `remote_src()` and
#' `remote_con()` give the dplyr source and DBI connection respectively.
#'
#' @param x Remote table, currently must be a [`tbl_sql`].
#' @param null_if_local Return `NULL` if the remote table is created via
#'   [tbl_lazy()] or [lazy_frame()]?
#' @param cte `r lifecycle::badge("deprecated")`
#'   Use the `sql_options` argument instead.
#' @param sql_options SQL rendering options generated by [sql_options()].
#' @param ... Additional arguments passed on to methods.
#' @return
#'   * `remote_name()` returns a string, or `NULL` if not a remote table, or not
#'     applicable. For example, computed queries do not have a "name".
#'   * `remote_table()` returns a [sql()] object containing the (correctly
#'     quoted) table identifier, or the custom query if the table was created
#'     from `sql()`. Returns `NULL` if applied to a lazy query that no longer
#'     corresponds to a single table (e.g. after a `filter()` or a join), or if
#'     applied to a local lazy table.
#' @export
#' @examples
#' mf <- memdb_frame(x = 1:5, y = 5:1, .name = "blorp")
#' remote_name(mf)
#' remote_src(mf)
#' remote_con(mf)
#' remote_query(mf)
#'
#' mf2 <- dplyr::filter(mf, x > 3)
#' remote_name(mf2)
#' remote_src(mf2)
#' remote_con(mf2)
#' remote_query(mf2)
remote_name <- function(x, null_if_local = TRUE) {
  table <- remote_table_path(x, null_if_local = null_if_local)

  if (is.sql(table) || is.null(table)) {
    NULL
  } else if (inherits(x, "tbl_lazy")) {
    table_path_name(table, x$con)
  } else {
    table
  }
}

#' @export
#' @rdname remote_name
remote_table <- function(x, null_if_local = TRUE) {
  check_bool(null_if_local)
  table <- remote_table_path(x, null_if_local = null_if_local)
  if (is.null(table) || is.sql(table)) {
    table
  } else {
    sql(unclass(table))
  }
}

# Internal generic that returns the raw table path (or sql for custom queries,
# or NULL when the lazy query no longer corresponds to a single table).
# Use this instead of `remote_table()` when internal code needs a value that can
# be passed to `as_table_path()` / `sql_escape_table_source()`.
remote_table_path <- function(x, null_if_local = TRUE) {
  UseMethod("remote_table_path")
}

#' @export
remote_table_path.tbl_lazy <- function(x, null_if_local = TRUE) {
  remote_table_path(x$lazy_query, null_if_local = null_if_local)
}

#' @export
remote_table_path.lazy_base_remote_query <- function(x, null_if_local = TRUE) {
  x$x
}

#' @export
remote_table_path.lazy_base_local_query <- function(x, null_if_local = TRUE) {
  if (null_if_local) {
    return()
  }

  x$name
}

#' @export
remote_table_path.lazy_query <- function(x, null_if_local = TRUE) {
  NULL
}

#' @export
#' @rdname remote_name
remote_src <- function(x) {
  x$src
}

#' @export
#' @rdname remote_name
remote_con <- function(x) {
  x$con
}

#' @export
#' @rdname remote_name
remote_query <- function(x, sql_options = NULL, cte = deprecated()) {
  rlang::check_exclusive(sql_options, cte, .require = FALSE)
  if (lifecycle::is_present(cte)) {
    lifecycle::deprecate_warn(
      when = "2.4.0",
      what = "remote_query(cte)",
      with = I("remote_query(sql_options = sql_options(cte = TRUE))")
    )
    sql_options <- dbplyr::sql_options(cte = cte)
  }
  db_sql_render(remote_con(x), x, sql_options = sql_options)
}

#' @export
#' @rdname remote_name
remote_query_plan <- function(x, ...) {
  dbplyr_explain(remote_con(x), db_sql_render(remote_con(x), x$lazy_query), ...)
}

#' Retrieve the last SQL query generated
#'
#' This is a helper function that retrieves the most recent SQL query generated
#' by dbplyr, which can be useful for debugging.
#'
#' @return A SQL string, or `NULL` if no query has been generated yet.
#' @export
#' @examples
#' library(dplyr, warn.conflicts = FALSE)
#'
#' df <- lazy_frame(x = 1:3)
#' df |> filter(x > 1)
#'
#' last_sql()
last_sql <- function() {
  the$last_sql
}
