#' Compute Dynamic Multipliers for kardl Models
#'
#'
#' Computes cumulative dynamic multipliers based on a model estimated using the
#' \code{kardl} framework. The function supports different configurations of
#' linearity and asymmetry in both short-run and long-run dynamics.
#'
#' The asymmetry structure is determined internally:
#' \itemize{
#'   \item Variables in \code{extractedInfo$ASvars} are treated as asymmetric in the short run.
#'   \item Variables in \code{extractedInfo$ALvars} are treated as asymmetric in the long run.
#' }
#'
#' This allows four possible configurations:
#' \itemize{
#'   \item \strong{LL}: Linear in both short-run and long-run
#'   \item \strong{NN}: Asymmetric in both short-run and long-run
#'   \item \strong{SA}: Short-run linear, long-run asymmetric
#'   \item \strong{AS}: Short-run asymmetric, long-run linear
#' }
#'
#' When a component is linear, the same coefficient path is used for both positive
#' and negative changes. When asymmetric, separate positive and negative effects
#' are computed.
#'
#' @param kmodel An object of class \code{kardl_lm} produced by the \code{kardl} function.
#' @param horizon Integer. Number of periods ahead for which dynamic multipliers are computed.
#' @param minProb Numeric. Minimum p-value threshold for including coefficients in the calculation. Coefficients with p-values above this threshold will be set to zero. Default is \code{0} (no threshold).
#' This parameter allows users to control the inclusion of coefficients in the calculation based on their statistical significance. Setting a threshold can help focus the analysis on more relevant variables, but it may also exclude potentially important effects if set too stringently.
#'
#' @return A list of class \code{kardl_mplier} containing:
#' \itemize{
#'   \item \strong{mpsi}: Matrix of cumulative dynamic multipliers.
#'   \item \strong{omega}: Vector of omega coefficients (persistence structure).
#'   \item \strong{lambda}: Matrix of short-run dynamic coefficients.
#'   \item \strong{horizon}: Forecast horizon used.
#'   \item \strong{vars}: Extracted model variable structure.
#' }
#'
#' @details
#'
#' The \code{mplier} function computes dynamic multipliers based on the coefficients and lag structure of a model estimated using the \code{kardl} package. The function extracts necessary
#' information from the model, such as coefficients, lag structure, and variable names, to compute the dynamic multipliers. It calculates the short-run coefficients, Lambda values, and omega values based on the model's parameters and lag structure. The output includes a matrix of dynamic multipliers (mpsi), which can be used for further analysis or visualization.
#' The dynamic multipliers provide insight into how changes in the independent variables affect the dependent variable over time, allowing for a deeper understanding of the relationships captured by the model. The function also allows users to set a minimum p-value threshold for including coefficients in the calculation, providing flexibility in focusing on statistically significant effects.
#'
#' The function constructs dynamic multipliers based on the recursive relationship:
#'
#' \deqn{
#' \psi_{h}^{+} = \sum_{i=0}^{h} \frac{\partial y_{t+i}}{\partial x_{t}^{+}}, \quad
#' \psi_{h}^{-} = \sum_{i=0}^{h} \frac{\partial y_{t+i}}{\partial x_{t}^{-}}
#' }
#'
#' where \eqn{\psi_h^{+}} and \eqn{\psi_h^{-}} represent cumulative responses to
#' positive and negative shocks.
#'
#' The recursion is defined as:
#'
#' \deqn{
#' \psi_h = \lambda_h + \sum_{j=1}^{p} \omega_j \psi_{h-j}
#' }
#'
#' where \eqn{\lambda_h} captures short-run effects and \eqn{\omega_j} reflects
#' persistence through lagged dependent variables.
#'
#' When asymmetry is present, positive and negative shocks are propagated separately.
#' Otherwise, the same dynamic path is used.
#'
#' @seealso \code{\link{bootstrap}}
#'
#' @import stats msm
#'
#'
#' @srrstats {G1.3}  Statistical terms such as "dynamic multipliers" are clearly defined and used consistently throughout the documentation and examples.
#' @srrstats {G2.0} The function validates that `kmodel` is of class `kardl_lm` before extracting lag and coefficient information.
#' @srrstats {G3.1} Long-run multiplier inference uses the variance-covariance matrix of the fitted model object.
#' @srrstats {G3.1a} Documentation describes the recursive formula used to compute cumulative multipliers and the role of the `omega` persistence structure.
#' @srrstats {TS4.2} The return value documents the `mpsi`, `omega`, `lambda`, `horizon`, and `vars` components with their meanings.
#' @srrstats {TS4.3} Dynamic multiplier outputs include the horizon index so that multiplier paths can be interpreted over modelled time steps.
#' @srrstats {TS5.0} A `plot` method is implemented for `kardl_mplier` objects.
#' @srrstats {TS5.7} The plot method displays the computed response path from the fitted model over the selected horizon.
#' @srrstats {TS5.8} Plot methods distinguish multiplier components by variable and shock direction where asymmetric effects are present.
#'
#'
#'
#'
#' @export
#'
#' @examples
#'
#' # This example demonstrates how to use the mplier function to calculate dynamic multipliers
#' # from a model estimated using the kardl package. The example includes fitting a model with
#' # the kardl function, calculating the multipliers, and visualizing the results using both
#' # base R plotting and ggplot2.
#'
#'  # Calculating dynamic multipliers for a linear model in short and long run (NN)
#'
#'  kardl_model<-kardl(imf_example_data, CPI~ER )
#'  m<-mplier(kardl_model,40)
#'  head(m$mpsi)
#'  plot(m)
#'
#'  # Calculating dynamic multipliers for a model with
#'  # Short-run linear, long-run asymmetric (SA)
#'  kardl_model<-kardl(imf_example_data, CPI~lasym(ER) )
#'  m<-mplier(kardl_model,40)
#'  head(m$mpsi)
#'  plot(m)
#'
#'  # Calculating dynamic multipliers for a model with
#'  # Short-run asymmetric, long-run linear (AS)
#'  kardl_model<-kardl(imf_example_data, CPI~sasym(ER) )
#'  m<-mplier(kardl_model,40)
#'  head(m$mpsi)
#'  plot(m)
#'
#'  # Calculating dynamic multipliers for a model with
#'  # asymmetric effects in both short and long run (NN)
#'  kardl_model<-kardl(imf_example_data, CPI~asym(ER) )
#'  m<-mplier(kardl_model,40)
#'  head(m$mpsi)
#'  plot(m)
#'
#'  # The mpsi matrix contains the cumulative dynamic multipliers for each variable and time horizon.
#'  # The omega vector contains the persistence structure of the model,
#'  # while the lambda matrix contains the short-run dynamic coefficients.
#'  # You can inspect these components to understand the dynamics captured by the model.
#'  kardl_model<-kardl(imf_example_data, CPI~PPI+asym(ER) )
#'  m<-mplier(kardl_model,40)
#'  head(m$mpsi)
#'  head(m$omega)
#'  head(m$lambda)
#'
#'  # For plotting specific variables, you can specify them in the plot function. For example,
#'  # to plot the multipliers for the variable "PPI":
#'
#'  plot(m, variable = "PPI")
#'
#'
mplier<-function(kmodel,horizon=80,minProb=0){

  if(! inherits(kmodel, "kardl_lm")){

    stop("Input object must be of class 'kardl_lm'.",call. = FALSE)
  }
  var_names <- names(coefficients(kmodel))
  properLag <- kmodel$lagInfo$OptLag
  h <- horizon + 1
  vars <- kmodel$extractedInfo

  depvar <- replace_lag_var(.kardl_Settings_env$LongCoef, vars$dependentVar, 1)
  a_index <- which(var_names == depvar)

  gamma__lags <- properLag[[vars$dependentVar]]
  gamma__index <- which(var_names %in% unlist(lapply(1:gamma__lags, function(i) {
    replace_lag_var(.kardl_Settings_env$ShortCoef, vars$dependentVar, i)
  })))

  model_params <- kmodel$coefficients

  if (minProb > 0) {
    tempModel <- summary(kmodel)$coefficients
    for (v in seq_len(nrow(tempModel))) {
      if (tempModel[v, 4] > minProb) {
        model_params[v] <- 0
      }
    }
  }

  my_theta <- model_params[a_index]
  gamma_ <- model_params[gamma__index]
  p <- length(gamma__index)

  omega_ <- numeric(p + 1)
  omega_[1] <- 1 + model_params[a_index] + gamma_[1]
  if (p >= 2) {
    for (i in 2:p) {
      omega_[i] <- gamma_[i] - gamma_[i - 1]
    }
  }
  omega_[p + 1] <- -gamma_[p]

  ColNum <- length(vars$independentVars)

  ColName <- ColName_F <- c()
  for (x in vars$independentVars) {
    posName <- paste0(.kardl_Settings_env$AsymPrefix[1], x, .kardl_Settings_env$AsymSuffix[1])
    negName <- paste0(.kardl_Settings_env$AsymPrefix[2], x, .kardl_Settings_env$AsymSuffix[2])
    diff_name <- paste0(x, "_dif")
    ColName_F <- c(ColName_F, posName, negName, diff_name)
    ColName <- c(ColName, posName, negName)
  }

  shortRun_coefs <- matrix(0, nrow = h, ncol = ColNum * 2)
  lambda_mtx <- matrix(0, nrow = h, ncol = ColNum * 2)
  mpsi_mtx <- matrix(0, nrow = h, ncol = ColNum * 2)
  colnames(shortRun_coefs) <- colnames(lambda_mtx) <- colnames(mpsi_mtx) <- ColName

  for (v in seq_len(ColNum)) {

    x <- vars$independentVars[v]

    posName <- paste0(.kardl_Settings_env$AsymPrefix[1], x, .kardl_Settings_env$AsymSuffix[1])
    negName <- paste0(.kardl_Settings_env$AsymPrefix[2], x, .kardl_Settings_env$AsymSuffix[2])

    # decide short-run / long-run asymmetry
    sr_asym <- x %in% vars$ASvars
    lr_asym <- x %in% vars$ALvars

    ## names used in long-run part
    lr_pos <- if (lr_asym) posName else x
    lr_neg <- if (lr_asym) negName else x

    ## names used in short-run part
    sr_pos <- if (sr_asym) posName else x
    sr_neg <- if (sr_asym) negName else x

    ## long-run coefficient indices
    mtx_index_POS <- which(var_names == replace_lag_var(.kardl_Settings_env$LongCoef, lr_pos, 1))
    mtx_index_NEG <- which(var_names == replace_lag_var(.kardl_Settings_env$LongCoef, lr_neg, 1))

    ## short-run lag indices
    mtx_beta_index_p <- which(var_names %in% unlist(lapply(0:properLag[[sr_pos]], function(i) {
      replace_lag_var(.kardl_Settings_env$ShortCoef, sr_pos, i)
    })))

    mtx_beta_index_n <- which(var_names %in% unlist(lapply(0:properLag[[sr_neg]], function(i) {
      replace_lag_var(.kardl_Settings_env$ShortCoef, sr_neg, i)
    })))

    mtx_beta_POS <- model_params[mtx_beta_index_p]
    mtx_beta_NEG <- model_params[mtx_beta_index_n]

    tempColNo <- (v - 1) * 2 + 1

    shortRun_coefs[seq_along(mtx_beta_POS), tempColNo] <- mtx_beta_POS
    shortRun_coefs[seq_along(mtx_beta_NEG), tempColNo + 1] <- mtx_beta_NEG

    lambda_mtx[1, tempColNo] <- shortRun_coefs[1, tempColNo]
    lambda_mtx[1, tempColNo + 1] <- shortRun_coefs[1, tempColNo + 1]

    lambda_mtx[2, tempColNo] <-
      model_params[mtx_index_POS] - shortRun_coefs[1, tempColNo] + shortRun_coefs[2, tempColNo]

    lambda_mtx[2, tempColNo + 1] <-
      model_params[mtx_index_NEG] - shortRun_coefs[1, tempColNo + 1] + shortRun_coefs[2, tempColNo + 1]

    my_beta_lags_p <- properLag[[sr_pos]]
    if (my_beta_lags_p > 1) {
      for (i in 2:length(mtx_beta_POS)) {
        lambda_mtx[i + 1, tempColNo] <- shortRun_coefs[i + 1, tempColNo] - shortRun_coefs[i, tempColNo]
      }
    }
    if (my_beta_lags_p > 0) {
      lambda_mtx[my_beta_lags_p + 2, tempColNo] <- -shortRun_coefs[my_beta_lags_p + 1, tempColNo]
    }

    ## if short-run is linear, copy lambda from POS to NEG
    if (!sr_asym) {
      lambda_mtx[, tempColNo + 1] <- lambda_mtx[, tempColNo]
    } else {
      my_beta_lags_n <- properLag[[sr_neg]]
      if (my_beta_lags_n > 1) {
        for (i in 2:length(mtx_beta_NEG)) {
          lambda_mtx[i + 1, tempColNo + 1] <- shortRun_coefs[i + 1, tempColNo + 1] - shortRun_coefs[i, tempColNo + 1]
        }
      }
      if (my_beta_lags_n > 0) {
        lambda_mtx[my_beta_lags_n + 2, tempColNo + 1] <- -shortRun_coefs[my_beta_lags_n + 1, tempColNo + 1]
      }
    }

    ## if long-run is linear, force same long-run effect in lambda[2]
    if (!lr_asym) {
      lambda_mtx[2, tempColNo + 1] <- lambda_mtx[2, tempColNo]
    }
  }

  mpsi_mtx[1, ] <- lambda_mtx[1, ]
  p2 <- p + 1

  for (v in 2:h) {
    n_say <- ifelse(v > p2, p2, v - 1)
    g_say <- ifelse(v - p2 <= 0, 1, v - p2)
    n_omega <- omega_[1:n_say]
    mpsi_mtx[v, ] <- lambda_mtx[v, ] + n_omega %*% mpsi_mtx[(v - 1):g_say, ]
  }

  mpsi_mtx2 <- apply(mpsi_mtx, 2, cumsum)

  mpsi <- matrix(0, nrow = h, ncol = ColNum * 3)
  for (v in seq_len(ColNum)) {
    colNo2 <- v * 2 - 1
    colNo3 <- v * 3 - 2
    mpsi[, colNo3] <- mpsi_mtx2[, colNo2]
    mpsi[, colNo3 + 1] <- -mpsi_mtx2[, colNo2 + 1]
    mpsi[, colNo3 + 2] <- mpsi_mtx2[, colNo2] - mpsi_mtx2[, colNo2 + 1]
  }

  mpsi <- cbind(0:horizon, mpsi)
  colnames(mpsi) <- c("h", ColName_F)

  structure(
    list(
      call = match.call(),
      mpsi = mpsi,
      omega = omega_,
      lambda = lambda_mtx,
      horizon = horizon,
      vars = vars
    ),
    class = "kardl_mplier"
  )
}

#' Bootstrap Confidence Intervals for Dynamic Multipliers
#'
#' This function computes bootstrap confidence intervals (CI) for dynamic multipliers
#' of a specified variable in a model estimated using the \code{kardl} package. The bootstrap method
#' generates resampled datasets to estimate the variability of the dynamic multipliers,
#' providing upper and lower bounds for the confidence interval.
#'
#' @param kmodel The model produced by the \code{\link{kardl}} function. This is the model object
#'        from which the dynamic multipliers are calculated.
#' @param horizon An integer specifying the horizon over which dynamic multipliers will be computed.
#'        The horizon defines the time frame for the analysis (e.g., 40 periods).
#' @param replications An integer indicating the number of bootstrap replications to perform.
#'        Higher values increase accuracy but also computational time. Default is \code{100}.
#' @param level A numeric value specifying the confidence level for the intervals (e.g., 95 for 95% confidence).
#'        Default is \code{90}.
#' @param minProb A numeric value specifying the minimum p-value threshold for including coefficients in the bootstrap.
#'       Coefficients with p-values above this threshold will be set to zero in the bootstrap samples. Default is \code{0} (no threshold).
#'       This parameter allows users to control the inclusion of coefficients in the bootstrap process based on their statistical significance. Setting a threshold can help focus the analysis on more relevant variables, but it may also exclude potentially important effects if set too stringently.
#'@param seed An optional integer to set the random seed for reproducibility of the bootstrap results. If not provided, the bootstrap will use the current random state.
#'
#' @seealso
#' \code{\link{mplier}} for calculating dynamic multipliers
#'
#' @return A list containing the following elements:
#' \itemize{
#' \item \strong{mpsi}: A data frame containing the dynamic multiplier estimates along with their upper and lower confidence intervals for each variable and time horizon.
#' \item \strong{level}: The confidence level used for the intervals (e.g 95).
#' \item \strong{horizon}: The horizon over which the multipliers were computed (e.g., 40).
#' \item \strong{vars}: A list of variable information extracted from the model, including dependent variable, independent variables, asymmetric variables, and deterministic terms.
#' \item \strong{replications}: The number of bootstrap replications performed.
#' \item \strong{type}: A character string indicating the type of analysis, in this case "bootstrap".
#' }
#'
#'
#' @details
#'
#' The \code{mpsi} component of the output contains the dynamic multiplier estimates along with their upper
#' and lower confidence intervals. These values are provided for each variable and at each time horizon.
#'
#' @srrstats {G5.5} Tests involving random resampling in the bootstrap set a random seed before the replication loop.
#' @srrstats {G5.6} Parameter-recovery properties of the bootstrap are assessed through deterministic examples in the test suite.
#' @srrstats {G3.1} Bootstrap standard errors for dynamic multipliers are derived from the covariance structure of the fitted model's residuals.
#' @srrstats {TS4.2} The bootstrap return value documents the `mpsi`, `level`, `horizon`, `vars`, and `replications` components.
#' @srrstats {G5.9} The documentation includes examples demonstrating the use of the bootstrap function, including how to specify the number of replications and how to interpret the output.
#'
#'
#' @import ggplot2
#' @export
#'
#' @examples
#'
#'   # Example usage of the bootstrap function
#'
#'
#'  # Fit a model using kardl
#'  kardl_model <- kardl(imf_example_data,
#'                       CPI ~ ER + PPI + asy(ER) +
#'                        det(covid) + trend,
#'                       mode = c(1, 2, 3, 0))
#'
#'  # Perform bootstrap with specific variables for plotting
#'  boot <-
#'    bootstrap(kardl_model,   replications=5, seed = 123L)
#'  # The boot object will include all plots for the specified variables
#'  # Displaying the boot object provides an overview of its components
#'  names(boot)
#'
#'
#'  # Inspect the first few rows of the dynamic multiplier estimates
#'   head(boot$mpsi)
#'
#'
#'   summary(boot)
#'
#'  # Retrieve plots generated during the bootstrap process
#'  # Accessing all plots
#'   plot(boot)
#'
#'  # Accessing the plot for a specific variable by its name
#'   plot(boot, variable = "PPI")
#'  plot(boot, variable = "ER")
#'
#'
#'
#' @examplesIf requireNamespace("magrittr", quietly = TRUE)
#' library(magrittr)
#'
#'    imf_example_data %>% kardl( CPI ~ PPI + asym(ER) +trend, maxlag=2) %>%
#'    bootstrap(replications=5) %>% plot(variable = "ER")
#'
#'
bootstrap<-function(kmodel,
                    horizon=80,
                    replications=100,
                    level=95,
                    minProb=0,
                    seed = NULL){

  if(! inherits(kmodel, "kardl_lm")){

    stop("Input object must be of class 'kardl_lm'.",call. = FALSE)
  }
  if (!is.null(seed)) {
    set.seed(seed)
  }

  My_mp<-mplier(kmodel,horizon, minProb)
  mpsi<-as.data.frame(My_mp[["mpsi"]])
  vars<-kmodel$extractedInfo

  if(length( vars$ASvars)>0){
    b0 <- coef(kmodel )
    tmin <- kmodel$estInfo$start
    tmax <-OBS <- kmodel$estInfo$end
    OptLag<-kmodel$lagInfo$OptLag
    nardlres<-residuals(kmodel)
    NewDiff<-matrix(NA,nrow = 1,ncol = length(vars$ASvars)+1)
    colnames(NewDiff)<-c("h",  vars$ASvars )
    phi <-  My_mp$omega
    phi.length<-length(phi)

    p<-OptLag[[vars$dependentVar]]+1

    q<-max(OptLag[names(OptLag)!= vars$dependentVar])+2
    # q<-max(OptLag[-1])+2
    theta<-My_mp$lambda[1:q,]


    # excluding symmetric independent vars
    symPosNames<- unlist(lapply(vars$indepASexcluded ,function(x){paste0(.kardl_Settings_env$AsymPrefix[1],x,.kardl_Settings_env$AsymSuffix[1])}) )
    symNegNames<- unlist(lapply(vars$indepASexcluded ,function(x){paste0(.kardl_Settings_env$AsymPrefix[2],x,.kardl_Settings_env$AsymSuffix[2])}) )

     if(!is.null(symPosNames)){
      theta<-theta[, colnames(theta) != symPosNames]
      colnames(theta)[colnames(theta) %in% symNegNames]<-vars$indepASexcluded
    }

    ## names of the indep. variables that matter for multipliers
    inddColnames <- colnames(theta)

    ## build the column list; add deterministic terms only if they exist
    reqCols <- c(vars$dependentVar,
                 inddColnames,
                 if (!is.null(vars$deterministic)) vars$deterministic)

    vars$data <- as.data.frame(vars$data)

    ## --- NEW: make sure every requested column exists --------------------
    missingCols <- setdiff(reqCols, colnames(vars$data))
    if (length(missingCols)) {
      vars$data[ , missingCols] <- 0          # fill with zeros
    }
    ## --------------------------------------------------------------------

    ## subset the data safely
    my_newData <- as.data.frame(vars$data)[ , reqCols, drop = FALSE]


    # Addin dif suffix to asymmetric short-run var names


    # Replace leading NA values with 0 for each column
    for(col in colnames(my_newData)) {
      first_non_na_index <- which(!is.na(my_newData[,col]))[1] # Find the index of first non-NA value
      if (!is.na(first_non_na_index) && first_non_na_index>1) { # Check if non-NA value exists
        my_newData[1:(first_non_na_index - 1), col] <- 0 # Replace leading NA values with 0
      }
    }



    newFormula <- kmodel$argsInfo$formula
    newDepData<- my_newData[,vars$dependentVar] #my_newData[,1]

    for (r in 1:replications) {
        for (t in tmin:tmax) {
          newy1<-sum(phi*newDepData[(t-1):(t-phi.length)]) # calculating dependent
          newy2<- sum(theta*my_newData[(t-0):(t-q+1),inddColnames]) #calculating independent vars
          newy3<-sum(my_newData[t,vars$deterministic]*b0[vars$deterministic]) #calculating deterministic vars
          newy <- newy1+ newy2+newy3+ b0[[1]] # adding constant
          newDepData[t]  <-   newy  +   nardlres[sample(seq_len(NROW(nardlres)), 1)] #adding random residual
        }
        if(r==1){
          BSnewdata<-cbind(newDepData,vars$data) # adding to original data
          colnames(BSnewdata)<-c("BStmp",colnames(vars$data))
          tempFormula<-BStmp~x+ff
          newFormula[[2]]<-tempFormula[[2]]
          names(OptLag)[1]<-"BStmp"
          OptLag<-as.double(OptLag)
        }else{
          BSnewdata[,"BStmp"]<-newDepData
        }

        My_model<-kardl(BSnewdata,newFormula,mode=OptLag)
        My_mpNew<- mplier(My_model,horizon ,minProb)
        NewDiff<-rbind(NewDiff, cbind(horizon=0:horizon, val=My_mpNew$mpsi[,paste0( vars$ASvars,"_dif")]))
    }

    NewDiff<-as.data.frame( NewDiff[-1,])
    rownames(NewDiff)<-seq_len(nrow(NewDiff))

    lowerZ <- 0.5 * (1 - level / 100)
    rZ<-replications * lowerZ
    lowerIndex1 <- ceiling(rZ)
    lowerIndex2 <- ifelse(lowerIndex1 - rZ != 0,lowerIndex1,rZ + 1)

    medianZ<-0.5
    rZ<-replications * medianZ
    medianIndex1 <- ceiling(rZ)
    medianIndex2 <- ifelse(medianIndex1 - rZ != 0,medianIndex1,rZ + 1)

    upperZ<-1-lowerZ
    rZ<-replications * upperZ
    upperIndex1 <- ceiling(rZ)
    upperIndex2 <- ifelse(upperIndex1 - rZ != 0,upperIndex1,rZ + 1)

    for (variable in vars$ASvars) {
      lowerCI<-medianCI<-upperCI<-c()
      for (jh in 0:horizon) {
        nardlbs_sub <- NewDiff[NewDiff$h==jh,]
        nardlbs_sub <- nardlbs_sub[order(nardlbs_sub[,variable]), variable]
        # nardlbs_sub <- unlist( nardlbs_sub[2])
        lowerCI[jh+1]<-(nardlbs_sub[lowerIndex1]+nardlbs_sub[lowerIndex2])/2
        medianCI[jh+1]<-(nardlbs_sub[medianIndex1]+nardlbs_sub[medianIndex2])/2
        upperCI[jh+1]<-(nardlbs_sub[upperIndex1]+nardlbs_sub[upperIndex2])/2
      }
      dynNames<-colnames(mpsi)
      mpsi<-cbind(mpsi,upperCI,lowerCI)
      colnames(mpsi)<-c(dynNames,paste0(variable,c("_CI_upper","_CI_lower")))

    }
  }


  my_output<-  list(
    mpsi=mpsi,
    level=level,
    horizon=horizon,
    vars=vars,
    replications=replications,
    type="bootstrap"
  )
  class(my_output)<-c("kardl_boot","kardl_mplier")
  my_output

}

#' Plot Dynamic Multipliers with ggplot2
#'
#' This function creates a ggplot visualization of the dynamic multipliers for a specified variable from a model estimated using the \code{kardl} package. The plot includes lines for positive and negative changes, as well as confidence intervals if available. The function allows for customization of colors, line types, and legend formatting to enhance the interpretability of the results.
#' @param mpsi A data frame containing the dynamic multipliers and confidence intervals for the specified variable. This data frame is typically generated by the \code{bootstrap} function.
#' @param vars A list of variable information extracted from the model, including dependent variable,
#' independent variables, asymmetric variables, and deterministic terms. This information is used to label the plot appropriately.
#' @param varName A character string specifying the name of the variable for which the dynamic
#' multipliers are being plotted. This variable should be one of the independent variables in the model, and it is used to construct the plot labels and legend.
#' @return A ggplot object visualizing the dynamic multipliers for the specified variable,
#' including lines for positive and negative changes, as well as confidence intervals if available. The plot is formatted with appropriate labels, colors, and legend to enhance interpretability.
#' @import ggplot2
#' @noRd

mplierggplot<-function(mpsi,vars, varName  ){
  x_p <- paste0(.kardl_Settings_env$AsymPrefix[1], varName, .kardl_Settings_env$AsymSuffix[1]) # paste0(varName,".POS")
  x_n <- paste0(.kardl_Settings_env$AsymPrefix[2], varName, .kardl_Settings_env$AsymSuffix[2]) # paste0(varName,".NEG")

  x_diff<-paste0(varName,"_dif")
  upperCI<-paste0(varName,"_CI_upper")
  lowerCI<-paste0(varName,"_CI_lower")

  p<- ggplot(mpsi, aes(x=.data$h)) +
    geom_line(aes(y = .data[[x_p]], color = "Positive")) +
    geom_line(aes(y = .data[[x_n]], color = "Negative"))
    # geom_line(aes(y=!!rlang::sym(x_p),color="Positive")) +
    # geom_line(aes(y=!!rlang::sym(x_n),color="Negative"))


  myBreaks<- c("Difference", "Positive", "Negative")
  labels <- c("Difference" = "Difference",
    "Positive" = "Positive Change",
    "Negative" = "Negative Change")
  values <- c( # Specify colors for each legend item
    "Difference" = alpha("black",1),
    "Positive" =  alpha("blue",1),
    "Negative" =  alpha("red",1) )
  color<-c("black","blue", "red")
  fill<-c("transparent", "transparent","transparent")
  linetype <-c(2,1,1) # c("dashed", "solid","solid","solid") ,
  size<-c(8,8,8)  # Increases the width of the legend key

  if(upperCI  %in% colnames(mpsi) ){ # !is.null(mpsi[[upperCI]])){

    # p <- p+    geom_line(aes(y=!!rlang::sym(x_diff),color="Difference"),linetype = "dashed") +
    #   geom_ribbon(aes(ymin = !!rlang::sym(lowerCI), ymax = !!rlang::sym(upperCI),color="CI") ,fill=  "blue"  ,   alpha = 0.2 )
     p <- p+
       # geom_line(aes(y = .data[[x_diff]], color = "Difference"), linetype = "dashed") +
      geom_ribbon(aes(ymin = .data[[lowerCI]], ymax = .data[[upperCI]], color = "CI"), fill = "blue", alpha = 0.2)

    myBreaks<- c(myBreaks, "CI")
    labels["Difference"]<- "Asymmetry"
    labels <- c( labels  , "CI" = "Confidence Interval")
    values <- c(  values  ,       "CI" =  alpha("blue",0.2) )
    color<-c(color,"transparent")
    fill<-c(fill,"blue")
    linetype <-c(linetype,0)
    size<-c( size,8)
  }

  p <- p+    geom_line(aes(y = .data[[x_diff]], color = "Difference"), linetype = "dashed") +
    scale_colour_manual(name="",
                                  breaks =myBreaks,  # Include "Confidence Interval" in breaks
                                  labels = labels,  # Include label for "Confidence Interval"
                                  values = values


  ) +  # Use the same color for "Confidence Interval" as the fill color
    #scale_fill_manual(name="",values=  "#84CA72"                   ,labels="CI")+
    scale_x_continuous(limits = c(0,nrow(mpsi)-1),  expand = c(0, 0))+
    labs(x = "time",y="") + ggtitle(paste0("Cumulative effect of ",varName," on ",vars$dependentVar))+
    guides( color = guide_legend(
      override.aes = list(
        color = color,
        fill  = fill,
        linetype =linetype, # c("dashed", "solid","solid","solid") ,

        size=size  # Increases the width of the legend key
      ) )
    )+  theme_bw()  +
    theme( legend.key.width = unit(0, "cm") ,
           legend.position = "bottom"  ,
           legend.margin = margin(t = 0, unit='cm')

    )

  p
}


