#' Series 1 PRBMS Design
#'
#' @description
#' This function generates a new series of PRBMS designs using initial sequence q1: [1, v, 2, v-1, ..., v/2, v/2+1]
#' with parameters (v, s = v/2, m = 2, p = v), and calculates the canonical efficiency factors.
#'
#' @param v Total number of products
#' @param verbose Logical; if TRUE, prints design layout and efficiency factors
#'
#' @return A list containing design and efficiency measures
#'
#' @examples
#' SERIES1(8, verbose = FALSE)
#'
#' @export
SERIES1 <- function(v, verbose = TRUE) {

  if (v %% 2 != 0) stop("v must be even")

  # ---------- William square ----------
  construct_william_square <- function(n) {
    square <- matrix(0, n, n)

    for (i in 1:n) {

      if (i %% 2 == 1) {
        start <- ((i - 1) / 2 + 1) %% n
      } else {
        start <- (n - i / 2 + 1) %% n
      }

      if (start == 0) start <- n

      row_vals <- (start:(start + n - 1)) %% n
      row_vals[row_vals == 0] <- n

      square[i, ] <- row_vals
    }

    square
  }

  design <- construct_william_square(v)

  n_panel   <- v
  n_session <- v / 2
  n_obs     <- v * v

  # ============================================================
  # DIRECT MATRIX
  # ============================================================

  direct <- matrix(0, n_obs, v)

  k <- 1
  for (i in 1:v) {
    for (j in 1:v) {
      direct[k, design[i, j]] <- 1
      k <- k + 1
    }
  }

  # ============================================================
  # CARRYOVER MATRIX
  # ============================================================

  carry <- matrix(0, n_obs, v)

  session_starts <- seq(1, v, by = 2)

  k <- 1
  for (i in 1:v) {
    for (j in 1:v) {

      if (!(i %in% session_starts)) {
        prev <- design[i - 1, j]
        carry[k, prev] <- 1
      }

      k <- k + 1
    }
  }

  carry <- carry[, colSums(carry) > 0]

  # ============================================================
  # PERIOD (NESTED)
  # ============================================================

  period_mat <- matrix(0, n_obs, v)

  r <- 1
  c <- 1

  for (s in 1:n_session) {
    for (p in 1:2) {
      for (j in 1:n_panel) {

        period_mat[r, c] <- 1
        r <- r + 1
      }

      c <- c + 1
    }
  }

  # ============================================================
  # PANELIST MATRIX
  # ============================================================

  panel <- matrix(0, n_obs, n_panel)

  k <- 1
  for (i in 1:v) {
    for (j in 1:v) {

      panel[k, j] <- 1
      k <- k + 1
    }
  }

  # ============================================================
  # SESSION MATRIX
  # ============================================================

  session_mat <- matrix(0, n_obs, n_session)

  k <- 1
  for (s in 1:n_session) {
    for (p in 1:2) {
      for (j in 1:n_panel) {

        session_mat[k, s] <- 1
        k <- k + 1
      }
    }
  }

  intercept <- matrix(1, n_obs, 1)

  # ============================================================
  # C-MATRIX
  # ============================================================

  X1 <- cbind(direct, carry)
  X2 <- cbind(intercept, period_mat, panel, session_mat)

  Cjoint <- t(X1) %*% X1 -
    t(X1) %*% X2 %*%
    MASS::ginv(t(X2) %*% X2) %*%
    t(X2) %*% X1

  t_cols <- ncol(direct)
  r_cols <- ncol(carry)

  C11 <- Cjoint[1:t_cols, 1:t_cols]

  C22 <- Cjoint[
    (t_cols + 1):(t_cols + r_cols),
    (t_cols + 1):(t_cols + r_cols)
  ]

  C12 <- Cjoint[
    1:t_cols,
    (t_cols + 1):(t_cols + r_cols)
  ]

  C_direct <- C11 -
    C12 %*% MASS::ginv(C22) %*% t(C12)

  C_carry <- C22 -
    t(C12) %*% MASS::ginv(C11) %*% C12

  # ============================================================
  # PRINT DESIGN
  # ============================================================

  # Roman numerals
  to_roman <- function(num) {

    roman_map <- c(
      M = 1000, CM = 900, D = 500, CD = 400,
      C = 100, XC = 90, L = 50, XL = 40,
      X = 10, IX = 9, V = 5, IV = 4, I = 1
    )

    result <- ""

    for (sym in names(roman_map)) {
      while (num >= roman_map[sym]) {
        result <- paste0(result, sym)
        num <- num - roman_map[sym]
      }
    }

    result
  }

  roman_periods <- sapply(1:100, to_roman)

  # Widths
  w_session <- 8
  w_period  <- 8
  w_panel   <- 4

  panel_width_total <- n_panel * w_panel
  total_left_width  <- w_session + w_period

  left_padding <- total_left_width +
    floor((panel_width_total - nchar("Panelist")) / 2)

  if (verbose) {

    cat("\nPRBMS Design:\n\n")

    # Header
    cat(sprintf("%*s%s\n", left_padding, "", "Panelist"))

    cat(sprintf("%-*s%-*s", w_session, "Session", w_period, "Period"))

    for (j in 1:n_panel) {
      cat(sprintf("%*s", w_panel, paste0("P", j)))
    }

    cat("\n\n")

    # Body
    row_counter <- 1

    for (s in 1:n_session) {

      cat(sprintf("%-*s", w_session, paste0("S", s)))

      for (p in 1:2) {

        cat(sprintf("%-*s", w_period, roman_periods[row_counter]))

        for (j in 1:n_panel) {
          cat(sprintf("%*d", w_panel, design[row_counter, j]))
        }

        cat("\n")

        row_counter <- row_counter + 1

        if (p == 1) {
          cat(sprintf("%-*s", w_session, ""))
        }
      }

      cat("\n")
    }
  }

  # ============================================================
  # EFFICIENCY FACTORS
  # ============================================================

  eig_d <- eigen(C_direct)$values
  eig_d <- eig_d[eig_d > 1e-7]

  rep_d <- t(direct) %*% direct
  eff_d <- length(eig_d) / sum(1 / (eig_d / rep_d[1, 1]))

  eig_r <- eigen(C_carry)$values
  eig_r <- eig_r[eig_r > 1e-7]

  rep_r <- t(carry) %*% carry
  eff_r <- length(eig_r) / sum(1 / (eig_r / rep_r[1, 1]))

  if (verbose) {
    cat("\nEfficiency Factors:\n\n")
    cat(sprintf("Direct effect: %.3f\n", eff_d))
    cat(sprintf("Carryover effect: %.3f\n", eff_r))
  }

  invisible(list(
    design = design,
    C_direct = C_direct,
    C_carry = C_carry,
    efficiency = c(
      Direct = eff_d,
      Carryover = eff_r
    )
  ))
}

