#' Generate a scorecard of curricular complexity metrics
#'
#' This function calculates course-level and curriculum-level curricular
#' complexity metrics for a plan of study. Course-level metrics include
#' blocking, reachability, delay, cruciality, deferment, and bottleneck
#' status. Curriculum-level metrics include structural complexity,
#' curricular rigidity, and the total number of bottleneck courses.
#'
#' @param plan_of_study An igraph object representing a plan of study,
#'   created using the \code{\link{create_plan_of_study}} function.
#' @param include_coreqs A logical value indicating whether corequisite
#'   courses should be included when calculating course-level metrics and
#'   structural complexity.
#'
#' @return A list containing two elements:
#'   \describe{
#'     \item{CourseLevel}{A data frame containing the course-level metrics
#'       \code{Course}, \code{Blocking}, \code{Reachability}, \code{Delay},
#'       \code{Cruciality}, \code{Deferment}, and \code{Bottleneck}. An
#'       asterisk in the \code{Bottleneck} column indicates that the course
#'       was identified as a bottleneck.}
#'     \item{CurriculumLevel}{A named vector containing the curriculum-level
#'       metrics \code{StructuralComplexity}, \code{CurricularRigidity}, and
#'       \code{TotalBottlenecks}.}
#'   }
#'
#' @export

generate_curricular_complexity_scorecard <- function(plan_of_study, include_coreqs = TRUE)
{
  complexity_score_card <- NULL
  curriculum_level_metrics <- NULL

  # Calculate bottlenecks once
  bottlenecks <- names(find_bottlenecks(plan_of_study))

  # Course-level metrics
  complexity_score_card <- data.frame(
    Course = names(V(plan_of_study)),
    Blocking = NA,
    Reachability = NA,
    Delay = NA,
    Cruciality = NA,
    Deferment = NA,
    Bottleneck = "",
    stringsAsFactors = FALSE
  )

  final_term <- max(V(plan_of_study)$term)

  for (course in names(V(plan_of_study)))
  {
    # Find the row corresponding to the current course
    course_index <- which(complexity_score_card$Course == course)

    complexity_score_card$Blocking[course_index] <-
      blocking_factor(plan_of_study, course, include_coreqs)

    complexity_score_card$Reachability[course_index] <-
      reachability_factor(plan_of_study, course, include_coreqs)

    complexity_score_card$Delay[course_index] <-
      delay_factor(plan_of_study, course, include_coreqs)

    complexity_score_card$Cruciality[course_index] <-
      cruciality(plan_of_study, course, include_coreqs)

    complexity_score_card$Deferment[course_index] <-
      round(
        deferment_factor(plan_of_study, course, final_term),
        2
      )

    complexity_score_card$Bottleneck[course_index] <-
      ifelse(course %in% bottlenecks, "*", "")
  }

  # Curriculum-level metrics
  structural_complexity_score <-
    structural_complexity(plan_of_study, include_coreqs)[[2]]

  curricular_rigidity_score <-
    round(curriculum_rigidity(plan_of_study), 2)

  bottlenecks_score <-
    length(bottlenecks)

  curriculum_level_metrics <- c(
    StructuralComplexity = structural_complexity_score,
    CurricularRigidity = curricular_rigidity_score,
    TotalBottlenecks = bottlenecks_score
  )

  # Return results
  results <- list(
    CourseLevel = complexity_score_card,
    CurriculumLevel = curriculum_level_metrics
  )

  return(results)
}

