# ============================================================
#  runme.R - finlabR demo + launch both Shiny apps
# ============================================================
#
#  Usage (from project root):
#    source("runme.R")   OR   Rscript runme.R
#
#  App 1 (port 3838): run_quantportr_app() from R/shiny_app.R
#  App 2 (port 3939): inst/shiny/finlabR-dashboard/app.R
# ============================================================

# ---- Resolve project root (works with source() and Rscript) ----
PROJECT_ROOT <- tryCatch(
  normalizePath(dirname(sys.frame(1)$ofile), mustWork = TRUE),
  error = function(e) normalizePath(getwd(), mustWork = TRUE)
)

# ---- Load package for examples ----
loaded_from_source <- FALSE
if (requireNamespace("devtools", quietly = TRUE) && file.exists(file.path(PROJECT_ROOT, "DESCRIPTION"))) {
  devtools::load_all(PROJECT_ROOT, quiet = TRUE)
  loaded_from_source <- TRUE
  message("Loaded finlabR from source via devtools::load_all().")
} else if (requireNamespace("finlabR", quietly = TRUE)) {
  suppressPackageStartupMessages(library(finlabR))
} else {
  stop("Package 'finlabR' is not installed and 'devtools' is missing.")
}

message("\n============================")
message(" finlabR quick examples")
message("============================")

set.seed(1)
rets <- matrix(rnorm(1000), ncol = 5)
colnames(rets) <- paste0("A", 1:5)

# Example 1: Risk parity weights
Sigma <- cov(rets)
rp <- finlabR::risk_parity_weights(Sigma)
print(rp$weights)

# Example 2: VaR / CVaR table
vc <- finlabR::var_cvar(rets, alpha = 0.95)
print(head(vc))

# Example 3: Efficient frontier (lightweight)
ef <- finlabR::mvo_efficient_frontier(rets, n = 20, rf = 0.02)
print(head(ef$frontier))

# Example 4: Max Sharpe portfolio from scan
ms <- finlabR::mvo_max_sharpe(rets, rf = 0.02, n = 20)
print(ms$weights)

message("\nExamples done. Launching Shiny apps...\n")

# ---- Shiny app launch (both apps) ----
if (!requireNamespace("callr", quietly = TRUE)) {
  stop("Package 'callr' is required. Install with: install.packages('callr')")
}
if (!requireNamespace("shiny", quietly = TRUE)) {
  stop("Package 'shiny' is required. Install with: install.packages('shiny')")
}

PORT_APP1 <- 3838
PORT_APP2 <- 3939

SHINY_APP2_DIR  <- file.path(PROJECT_ROOT, "inst", "shiny", "finlabR-dashboard")

# Make project root available to background R sessions
Sys.setenv(FINLABR_PROJECT_ROOT = PROJECT_ROOT)

if (!dir.exists(SHINY_APP2_DIR)) {
  stop("Cannot find App 2 directory at: ", SHINY_APP2_DIR)
}

message("=================================================")
message(" Launching Shiny apps in background processes...")
message("=================================================")
message(" App 1 (QuantPortR dashboard) -> http://127.0.0.1:", PORT_APP1)
message(" App 2 (finlabR-dashboard)    -> http://127.0.0.1:", PORT_APP2)
message("=================================================\n")

# App 1: run_quantportr_app() from the package namespace
bg_app1 <- callr::r_bg(
  func = function(project_root, port) {
    if (requireNamespace("devtools", quietly = TRUE)) {
      devtools::load_all(project_root, quiet = TRUE)
    } else if (!requireNamespace("finlabR", quietly = TRUE)) {
      stop("Package 'finlabR' is not installed and 'devtools' is missing.")
    }
    finlabR::run_quantportr_app(
      host           = "127.0.0.1",
      port           = port,
      launch.browser = FALSE
    )
  },
  args    = list(project_root = PROJECT_ROOT, port = PORT_APP1),
  package = FALSE,
  stdout  = "|",
  stderr  = "|"
)

# App 2: inst/shiny/finlabR-dashboard/app.R
bg_app2 <- callr::r_bg(
  func = function(app_dir, port, project_root) {
    Sys.setenv(FINLABR_PROJECT_ROOT = project_root)
    shiny::runApp(
      appDir         = app_dir,
      host           = "127.0.0.1",
      port           = port,
      launch.browser = FALSE
    )
  },
  args    = list(app_dir = SHINY_APP2_DIR, port = PORT_APP2, project_root = PROJECT_ROOT),
  package = FALSE,
  stdout  = "|",
  stderr  = "|"
)

# Wait briefly for apps to bind to ports
message("Waiting for apps to start ", appendLF = FALSE)
for (i in seq_len(6)) {
  Sys.sleep(0.8)
  message(".", appendLF = FALSE)
}
message(" done!\n")

# Open both in the browser
utils::browseURL(paste0("http://127.0.0.1:", PORT_APP1))
Sys.sleep(0.5)
utils::browseURL(paste0("http://127.0.0.1:", PORT_APP2))

message("Both apps running. Press Ctrl+C / Escape to stop.\n")

# Monitor; shut down cleanly on interrupt
tryCatch(
  {
    repeat {
      Sys.sleep(2)

      app1_alive <- bg_app1$is_alive()
      app2_alive <- bg_app2$is_alive()

      if (!app1_alive) {
        err <- trimws(paste(bg_app1$read_error(), collapse = "\n"))
        message("\n[!] App 1 (QuantPortR) stopped unexpectedly.")
        if (nchar(err) > 0) message("    stderr: ", err)
      }
      if (!app2_alive) {
        err <- trimws(paste(bg_app2$read_error(), collapse = "\n"))
        message("\n[!] App 2 (finlabR-dashboard) stopped unexpectedly.")
        if (nchar(err) > 0) message("    stderr: ", err)
      }

      if (!app1_alive && !app2_alive) {
        message("Both apps have exited. Stopping.")
        break
      }
    }
  },
  interrupt = function(e) {
    message("\n\nShutting down both apps...")
    if (bg_app1$is_alive()) bg_app1$kill()
    if (bg_app2$is_alive()) bg_app2$kill()
    message("Done. Goodbye!")
  }
)
