# wid_convert, wid_metadata, wid_tidy

.XR <- c(lcu = "xlcusx999i", usd = "xlcusx999i", eur = "xleusx999i",
         gbp = "xlgbsx999i", ppp = "xlpppx999i", yppp = "xlpppx999i")

#' Convert a wid_df to another currency
#' @param data      A \code{wid_df}.
#' @param target    One of \code{"lcu"}, \code{"usd"}, \code{"eur"}, \code{"gbp"}, \code{"ppp"}, \code{"yppp"}.
#' @param base_year Pin to a specific year's exchange rate; \code{NULL} uses contemporaneous rates.
#' @return The same \code{wid_df} with values converted. Dimensionless series
#'   (shares, ratios) are returned unchanged with a message.
#' @examples
#' \donttest{
#'   if (nzchar(Sys.getenv("WID_API_KEY"))) {
#'     d <- download_wid("aptinc992j", areas = "US", perc = "p99p100",
#'                       years = 2010:2020)
#'     wid_convert(d, target = "ppp")
#'   }
#' }
#' @export
wid_convert <- function(data, target = "usd", base_year = NULL) {
  .check(data)
  target   <- match.arg(target, names(.XR))
  is_ratio <- substr(data$variable, 1L, 1L) %in% c("s","g","b","w","r","p","i","y")
  if (all(is_ratio)) {
    message("All series are dimensionless; no conversion applied.")
    return(data)
  }
  xr <- download_wid(.XR[target], areas = unique(data$country),
                     years = base_year %||% "all", cache = TRUE)
  if (inherits(xr, "wid_data")) xr <- xr$data
  if (is.null(xr) || !nrow(xr))
    stop("No exchange rates retrieved for target=", target, call. = FALSE)
  if (!is.null(base_year)) xr <- xr[as.integer(xr$year) == as.integer(base_year), ]
  for (i in which(!is_ratio)) {
    rate <- xr$value[xr$country == data$country[i] &
                       (if (!is.null(base_year)) TRUE else as.integer(xr$year) == as.integer(data$year[i]))]
    data$value[i] <- if (length(rate) && !is.na(rate[1L])) data$value[i] / rate[1L] else NA_real_
  }
  data
}

#' Fetch metadata for variables in a wid_df
#' @param data A \code{wid_df}.
#' @return A \code{data.frame} with columns \code{variable}, \code{country},
#'   \code{source}, \code{method}, \code{quality}, and \code{imputation}.
#' @examples
#' \donttest{
#'   if (nzchar(Sys.getenv("WID_API_KEY"))) {
#'     d <- download_wid("sptinc992j", areas = "US", metadata = TRUE)
#'     wid_metadata(d)
#'   }
#' }
#' @export
wid_metadata <- function(data) {
  .check(data)
  dec  <- lapply(unique(data$variable), function(v)
    tryCatch(wid_decode(v, strict = FALSE), warning = function(w) NULL, error = function(e) NULL))
  vars <- unique(vapply(dec, function(d) if (!is.null(d)) d$concept else NA_character_, character(1L)))
  vars <- vars[!is.na(vars)]
  out  <- .get_metadata_variables(unique(data$country), vars)
  if (!nrow(out)) { message("No metadata returned."); return(invisible(out)) }
  cols <- intersect(c("variable","country"), names(out))
  out[!duplicated(out[, cols, drop = FALSE]), ]
}

#' Tidy a wid_df: decode variable codes and coerce column types
#' @param data          A \code{wid_df}.
#' @param decode        Logical. Add decoded columns. Default \code{TRUE}.
#' @param country_names Logical. Join country display names. Default \code{TRUE}.
#' @return A plain \code{data.frame} with \code{year} as integer, \code{value}
#'   as double, and optionally \code{indicator}, \code{series_type},
#'   \code{type_label}, and \code{country_name} columns appended.
#' @examples
#' d <- data.frame(
#'   country = "US", variable = "sptinc992j", percentile = "p99p100",
#'   year = "2020", value = "0.19", age = "992", pop = "j",
#'   stringsAsFactors = FALSE
#' )
#' class(d) <- c("wid_df", "data.frame")
#' wid_tidy(d, country_names = FALSE)
#' @export
wid_tidy <- function(data, decode = TRUE, country_names = TRUE) {
  .check(data)
  out <- as.data.frame(data)
  if (decode) {
    dec             <- lapply(out$variable, function(v)
      tryCatch(wid_decode(v, strict = FALSE), warning = function(w) NULL, error = function(e) NULL))
    out$indicator   <- vapply(dec, function(d)
      if (!is.null(d)) paste0(d$series_type, d$concept) else NA_character_, character(1L))
    out$series_type <- vapply(dec, function(d)
      if (!is.null(d)) d$series_type else NA_character_, character(1L))
    out$type_label  <- .recode(out$series_type, .CODE_TYPES)
  }
  if (country_names) {
    lkp        <- wid_countries[, c("code", "description")]
    names(lkp) <- c("country", "country_name")
    out        <- merge(out, lkp, by = "country", all.x = TRUE)
  }
  out$year  <- as.integer(out$year)
  out$value <- as.numeric(out$value)
  out
}