#' @title Daily statistics of dendrometer data
#'
#' @description
#' Computes daily statistics from high-frequency dendrometer time series.
#' For each day, it extracts the minimum and maximum values, their times
#' of occurrence, daily mean and median, daily amplitude, the signed lag
#' between the time of maximum and minimum, the day-to-day change in the
#' daily maximum, and a daily status indicating whether the day is growing,
#' shrinking, or stable relative to the previous day.
#'
#' @details
#' The function requires a data frame with a time column in the first column
#' and one or more dendrometer series in the following columns. The user
#' selects the series using \code{TreeNum}.
#'
#' The returned object has class \code{"daily_output"}, so it can be plotted
#' directly with \code{plot()}.
#'
#' The column \code{Max_diff} is computed as:
#' \deqn{Max\_diff_t = Max_t - Max_{t-1}}
#'
#' The column \code{Day_status} is derived from \code{Max_diff}:
#' \itemize{
#'   \item \code{"growing"} if \code{Max_diff > 0}
#'   \item \code{"shrinking"} if \code{Max_diff < 0}
#'   \item \code{"stable"} if \code{Max_diff = 0}
#' }
#'
#' The first day has \code{NA} for \code{Max_diff} and \code{Day_status}.
#'
#' @references
#' King G, Fonti P, Nievergelt D, Büntgen U, Frank D (2013)
#' Climatic drivers of hourly to yearly tree radius variations along a 6°C natural warming gradient.
#' \emph{Agricultural and Forest Meteorology} 168:36–46.
#' \doi{10.1016/j.agrformet.2012.08.002}
#'
#' @param df A data frame with the first column containing date-time stamps
#'   convertible to \code{POSIXct} and subsequent columns containing
#'   dendrometer measurements.
#' @param TreeNum Integer. The index of the tree (column) to analyze.
#'   \code{TreeNum = 1} refers to the first dendrometer column after the
#'   time column.
#'
#' @return A tibble of class \code{"daily_output"} containing:
#' \describe{
#'   \item{DATE}{Calendar date.}
#'   \item{Min}{Daily minimum value.}
#'   \item{Time_min}{Time of day of minimum value.}
#'   \item{Max}{Daily maximum value.}
#'   \item{Time_max}{Time of day of maximum value.}
#'   \item{mean}{Daily mean value.}
#'   \item{median}{Daily median value.}
#'   \item{amplitude}{Daily amplitude = Max - Min.}
#'   \item{Time_min_h}{Time of minimum expressed in decimal hours.}
#'   \item{Time_max_h}{Time of maximum expressed in decimal hours.}
#'   \item{lag_h}{Signed difference in hours: Time_max_h - Time_min_h.}
#'   \item{Remarks}{\code{"*"} if \code{Time_max > Time_min}, otherwise \code{""}.}
#'   \item{Max_diff}{Difference between today's maximum and the previous day's maximum.}
#'   \item{Day_status}{\code{"growing"}, \code{"shrinking"}, \code{"stable"}, or \code{NA}.}
#' }
#'
#' @note
#' The object returned by \code{daily.data()} can be plotted using
#' \code{plot()} because it is assigned class \code{"daily_output"}.
#'
#' @importFrom lubridate ymd_hms
#' @importFrom dplyr mutate group_by summarise rename lag case_when if_else %>%
#' @importFrom tibble tibble
#' @importFrom stats median
#'
#' @examples
#' \donttest{
#' data(nepa17)
#' daily_stats <- daily.data(df = nepa17[1:1000, ], TreeNum = 1)
#' head(daily_stats, 10)
#' }
#'
#' @export
daily.data <- function(df, TreeNum) {
  if (TreeNum > ncol(df) - 1) {
    stop("The tree number is not valid for provided dataset.")
  }
  TIME <- DATE <- dm <- time <- Time_min <- Time_max <- Time_max_h <- Time_min_h <- Max <- NULL


  tn <- TreeNum + 1

  if (!inherits(df[[1]], "Date") && !inherits(df[[1]], "POSIXct")) {
    df[[1]] <- lubridate::ymd_hms(df[[1]])
  }

  time_to_hours <- function(x) {
    x <- as.character(x)
    bad <- is.na(x) | x == ""
    hh <- suppressWarnings(as.numeric(substr(x, 1, 2)))
    mm <- suppressWarnings(as.numeric(substr(x, 4, 5)))
    ss <- suppressWarnings(as.numeric(substr(x, 7, 8)))
    out <- hh + mm / 60 + ss / 3600
    out[bad] <- NA_real_
    out
  }

  dat <- tibble::tibble(
    TIME = as.POSIXct(df[[1]]),
    dm = df[[tn]]
  ) %>%
    dplyr::mutate(
      DATE = as.Date(TIME),
      time = format(TIME, "%H:%M:%S")
    )

  result <- dat %>%
    dplyr::group_by(DATE) %>%
    dplyr::summarise(
      Min = if (all(is.na(dm))) NA_real_ else min(dm, na.rm = TRUE),
      Time_min = if (all(is.na(dm))) {
        NA_character_
      } else {
        time[which.min(replace(dm, is.na(dm), Inf))][1]
      },
      Max = if (all(is.na(dm))) NA_real_ else max(dm, na.rm = TRUE),
      Time_max = if (all(is.na(dm))) {
        NA_character_
      } else {
        time[which.max(replace(dm, is.na(dm), -Inf))][1]
      },
      mean = if (all(is.na(dm))) NA_real_ else mean(dm, na.rm = TRUE),
      median = if (all(is.na(dm))) NA_real_ else stats::median(dm, na.rm = TRUE),
      amplitude = if (all(is.na(dm))) NA_real_ else max(dm, na.rm = TRUE) - min(dm, na.rm = TRUE),
      .groups = "drop"
    ) %>%
    dplyr::mutate(
      Time_min_h = time_to_hours(Time_min),
      Time_max_h = time_to_hours(Time_max),
      lag_h = Time_max_h - Time_min_h,
      Remarks = dplyr::if_else(
        !is.na(Time_max_h) & !is.na(Time_min_h) & Time_max_h > Time_min_h,
        "*", ""
      ),
      Max_diff = Max - dplyr::lag(Max),
      Day_status = dplyr::case_when(
        is.na(Max_diff) ~ NA_character_,
        Max_diff > 0 ~ "growing",
        Max_diff < 0 ~ "shrinking",
        TRUE ~ "stable"
      )
    )

  attr(result, "tree_num") <- TreeNum
  attr(result, "tree_col") <- names(df)[tn]

  class(result) <- c("daily_output", class(result))
  result
}
