#' Moderated Regression Model
#'
#' Fits a moderated regression model with optional extensions.
#'
#' @param data A data frame
#' @param dv Dependent variable
#' @param iv Independent variable
#' @param moderator Moderator variable
#' @param covariates Optional character vector of covariate names.
#'   Defaults to NULL (no covariates).
#' @param center Logical; whether to center variables
#' @param quadratic Logical; include quadratic terms
#' @param robust_se Logical; use HC3 robust standard errors
#'
#' @return A fitted model object
#' @importFrom stats lm coef vcov update
#' @importFrom sandwich vcovHC
#' @importFrom lmtest coeftest
#'
#' @examples
#' set.seed(123)
#'
#' n <- 100
#' x <- rnorm(n)
#' w1 <- rnorm(n)
#' w2 <- rnorm(n)
#' z <- 0.5 * x + sqrt(1 - 0.5^2) * rnorm(n)
#'
#' y <- 0.3 * x + 0.3 * z + 0.8 * x * z + rnorm(n)
#'
#' data <- data.frame(w1, w2, x, z, y)
#'
#'result <- moderated_regression(
#'  data,
#'  iv = "x",
#'  moderator = "z",
#'  dv = "y",
#'  covariates = c("w1", "w2")
#'  )
#'
#'
#' @export
#'
moderated_regression <- function(data, iv, moderator, dv,
                                 covariates = NULL,
                                 center = TRUE,
                                 quadratic = FALSE,
                                 robust_se = FALSE) {

  detect_type <- function(x) {
    if (is.factor(x)) return("binary")
    unique_vals <- unique(na.omit(x))
    if (length(unique_vals) <= 2) return("binary")
    return("continuous")
  }

  # -------------------------------
  # Validate input
  # -------------------------------
  if (!is.data.frame(data)) stop("data must be a data frame")

  if (is.null(covariates)) covariates <- character(0)

  required_vars <- c(iv, moderator, dv, covariates)

  missing_vars <- required_vars[!required_vars %in% names(data)]
  if (length(missing_vars) > 0) {
    stop("Missing variables: ", paste(missing_vars, collapse = ", "))
  }

  data_clean <- data[complete.cases(data[, required_vars, drop = FALSE]), ]
  if (nrow(data_clean) < 10) stop("Insufficient observations")

  type_iv <- detect_type(data_clean[[iv]])
  type_moderator <- detect_type(data_clean[[moderator]])

  df <- data_clean

  # -------------------------------
  # Centering (UPDATED NAMING)
  # -------------------------------
  if (center) {
    x_var <- "x_center"
    z_var <- "z_center"

    df[[x_var]] <- scale(df[[iv]], center = TRUE, scale = FALSE)
    df[[z_var]] <- scale(df[[moderator]], center = TRUE, scale = FALSE)
  } else {
    x_var <- iv
    z_var <- moderator

    df[[x_var]] <- df[[iv]]
    df[[z_var]] <- df[[moderator]]
  }

  # -------------------------------
  # Interaction
  # -------------------------------
  df$int_term <- df[[x_var]] * df[[z_var]]

  # -------------------------------
  # Covariates (UPDATED NAMING)
  # -------------------------------
  if (length(covariates) > 0) {

    cov_names <- c()

    for (cov in covariates) {

      if (center && is.numeric(df[[cov]])) {
        new_name <- paste0(cov, "_center")
        df[[new_name]] <- scale(df[[cov]], center = TRUE, scale = FALSE)
      } else {
        new_name <- cov
        df[[new_name]] <- df[[cov]]
      }

      cov_names <- c(cov_names, new_name)
    }

    cov_terms <- paste(cov_names, collapse = " + ")

    formula_base <- as.formula(
      paste(dv, "~", cov_terms, "+", x_var, "+", z_var, "+ int_term")
    )

  } else {

    formula_base <- as.formula(
      paste(dv, "~", x_var, "+", z_var, "+ int_term")
    )
  }

  # -------------------------------
  # Quadratic terms (UPDATED NAMING)
  # -------------------------------
  if (quadratic &&
      type_iv == "continuous" &&
      type_moderator == "continuous") {

    x_sq <- paste0(x_var, "_sq")
    z_sq <- paste0(z_var, "_sq")

    df[[x_sq]] <- df[[x_var]]^2
    df[[z_sq]] <- df[[z_var]]^2

    formula_final <- update(formula_base,
                            as.formula(paste(". ~ . +", x_sq, "+", z_sq)))
  } else {
    formula_final <- formula_base
  }

  # -------------------------------
  # Model estimation
  # -------------------------------
  model <- lm(formula_final, data = df)

  coef_summary <- summary(model)$coefficients

  interaction_p <- if ("int_term" %in% rownames(coef_summary)) {
    coef_summary["int_term", "Pr(>|t|)"]
  } else {
    NA_real_
  }

  # -------------------------------
  # Robust SE
  # -------------------------------
  if (robust_se) {
    vc <- sandwich::vcovHC(model, type = "HC3")
    coef_table <- lmtest::coeftest(model, vc)
  } else {
    vc <- vcov(model)
    coef_table <- coef_summary
  }

  # -------------------------------
  # Output
  # -------------------------------
  result <- list(
    model = model,
    vcov = vc,
    coef_table = coef_table,
    interaction_p = interaction_p,
    type_iv = type_iv,
    type_moderator = type_moderator,
    covariates = covariates,
    center = center,
    quadratic = quadratic,
    robust_se = robust_se,
    iv = iv,
    moderator = moderator,
    dv = dv,
    data = df,
    call = match.call()
  )

  class(result) <- "modlr"
  return(result)
}
