# ============================================================
# KRONX :: report.R
# Plain-text report generation and structured CSV export.
# ============================================================

# Format a numeric vector with a fixed number of decimal places.
fmt_num <- function(x, digits = 6) formatC(x, digits = digits, format = "f")

# Write a labeled matrix block to a text connection (plain text report).
write_matrix_block <- function(con, title, M, digits = 6) {
  writeLines(title, con)
  rn <- rownames(M); cn <- colnames(M)
  if (is.null(rn)) rn <- paste0("State", seq_len(nrow(M)))
  if (is.null(cn)) cn <- paste0("State", seq_len(ncol(M)))
  writeLines(paste(c("", cn), collapse = "\t"), con)
  for (i in seq_len(nrow(M))) {
    writeLines(paste(c(rn[i], fmt_num(M[i, ], digits)), collapse = "\t"), con)
  }
  writeLines("", con)
}

# Write all analysis outputs to the output_dir.
# Returns (invisibly) a character vector of paths written.
write_kronx_outputs <- function(result, output_dir, input_file) {
  if (!dir.exists(output_dir)) dir.create(output_dir, recursive = TRUE)
  pf <- function(fname) file.path(output_dir, fname)

  # ---- CSV exports ----
  utils::write.csv(result$state_summary,
            pf("kronx_state_summary.csv"),           row.names = FALSE)
  utils::write.csv(result$A_gauss,
            pf("gaussian_transition_matrix.csv"),    row.names = FALSE)
  utils::write.csv(result$A_t,
            pf("student_t_transition_matrix.csv"),   row.names = FALSE)
  utils::write.csv(result$Q,
            pf("kronx_Q_operator.csv"),              row.names = FALSE)
  utils::write.csv(result$K_mat,
            pf("kronx_K_generator.csv"),             row.names = FALSE)
  utils::write.csv(result$N_mat,
            pf("kronx_N_fundamental_matrix.csv"),    row.names = FALSE)
  utils::write.csv(
    data.frame(
      return                = result$ret,
      decoded_state_student = result$vpath_t
    ),
    pf("student_t_decoded_states.csv"),
    row.names = FALSE
  )

  # ---- Plain-text report ----
  rpt <- pf("kronx_analysis_report.txt")
  con <- file(rpt, open = "wt")
  on.exit(close(con), add = TRUE)

  writeLines("============================================================", con)
  writeLines("CLOCK OF REGIMES (KRONX) ANALYSIS REPORT", con)
  writeLines("============================================================\n", con)
  writeLines(sprintf("Input file                : %s", input_file), con)
  writeLines(sprintf("Close observations        : %d", length(result$close_px)), con)
  writeLines(sprintf("Return observations       : %d", length(result$ret)), con)
  writeLines(sprintf("Number of states          : %d", result$K), con)
  writeLines(sprintf("Tail probability alpha    : %.4f", result$tail_alpha), con)
  writeLines(sprintf("Ruin horizon T            : %d\n", result$ruin_horizon), con)

  writeLines("Gaussian HMM log-likelihood", con)
  writeLines(sprintf("%.10f\n", result$gauss_fit$logLik), con)
  writeLines("Student-t HMM log-likelihood", con)
  writeLines(sprintf("%.10f\n", result$t_fit$logLik), con)

  write_matrix_block(con, "Gaussian transition matrix A:", result$A_gauss)
  write_matrix_block(con, "Student-t transition matrix A:", result$A_t)
  write_matrix_block(con, "Hazard-adjusted operator Q:", result$Q)
  write_matrix_block(con, "KRONX generator K = Q - I:", result$K_mat)
  write_matrix_block(con, "Fundamental matrix N = -K^{-1}:", result$N_mat)

  writeLines("State summary", con)
  utils::capture.output(print(result$state_summary, row.names = FALSE), file = con)
  writeLines("", con)

  writeLines(sprintf(
    "Empirical left-tail threshold (alpha = %.4f): %.8f",
    result$tail_alpha, result$loss_threshold), con)
  writeLines(sprintf(
    "Residence-weighted tail probability qbar    : %.8f", result$bar_q), con)
  writeLines(sprintf(
    "Residence-weighted hazard lambdabar         : %.8f", result$bar_lambda), con)
  writeLines(sprintf(
    "Ruin bound over horizon T                   : %.8f\n", result$ruin_bound), con)

  writeLines(paste(
    "Interpretive note:",
    "Because K = Q - I is an open / leaky operator, a classical stationary",
    "distribution does not strictly exist. The script therefore reports a",
    "quasi-stationary vector from Q and a residence-weight vector implied by N.",
    "The latter is used for the residence-weighted tail and ruin summaries.",
    sep = "\n"), con)

  files_written <- c(
    "kronx_analysis_report.txt",
    "kronx_state_summary.csv",
    "gaussian_transition_matrix.csv",
    "student_t_transition_matrix.csv",
    "kronx_Q_operator.csv",
    "kronx_K_generator.csv",
    "kronx_N_fundamental_matrix.csv",
    "student_t_decoded_states.csv"
  )
  invisible(file.path(output_dir, files_written))
}
