# To test locally, run this in a docker container:
# docker run -d --rm -v $(pwd):/home/golem rocker/shiny:latest tail -f /dev/null
# Attach VSCode to the container
# Then run this script in the terminal

# This script is launched internally by ThinkR every day by our GitLab CI
temp_app <- commandArgs(TRUE)[1]
if (is.na(temp_app)) {
  temp_app <- "/golemmetrics"
}
cli::cat_bullet(temp_app)
if (dir.exists(temp_app)) {
  unlink(temp_app, TRUE, TRUE)
}

options("repos" = "https://packagemanager.posit.co/cran/__linux__/jammy/latest")

install.packages(c("pak"))

if (!rlang::is_installed("cli")) {
  pak::pak("cli")
}

if (!rlang::is_installed("testthat")) {
  pak::pak("testthat")
}

if (!rlang::is_installed("desc")) {
  pak::pak("desc")
}

if (!rlang::is_installed("devtools")) {
  pak::pak("devtools")
}

library(desc)
library(testthat)
cat("\n")

# rstudioapi::jobRunScript(here::here("inst/mantests/build.R"), workingDir = here::here())
cat_ok <- function() cli::cat_bullet("Passed", bullet = "tick", bullet_col = "green")

# We prevent the random name from having
# ui or server inside it
safe_let <- function() {
  letters[-c(5, 9, 18, 19, 21, 22)]
}

## fake package
fakename <- sprintf(
  "%s%s",
  paste0(sample(safe_let(), 10, TRUE), collapse = ""),
  gsub("[ :-]", "", Sys.time())
)

cli::cat_rule("Installing the dev version of golem")
pak::pak("thinkr-open/golem@dev")

cli::cat_rule("Install crystalmountains")
pak::pak(
  "thinkr-open/crystalmountains"
)

cli::cat_rule("Creating a golem based app")

# Going to the temp dir and create a new golem
cli::cat_rule("Creating a golem based app")
library(golem)

zz <- file("all.Rout", open = "wt")
sink(zz)
sink(zz, type = "message")

# This is our temp app

create_golem(
  temp_app,
  open = FALSE,
  project_hook = crystalmountains::golem_hook
)
sink(type = "message")
sink()

expect_true(
  dir.exists(temp_app)
)

expect_true(
  any(grepl(
    "golem::install_dev_deps()",
    readLines("all.Rout")
  ))
)
unlink("all.Rout", TRUE, TRUE)

golem::install_dev_deps(force = TRUE)

for (pak in golem:::dev_deps) {
  expect_true(
    rlang::is_installed(pak)
  )
}

old <- setwd(temp_app)

usethis::use_build_ignore(".here")

cat(
  readLines("DESCRIPTION"),
  sep = "\n"
)

usethis::use_build_ignore(".here")

usethis::use_dev_package("golem")

cat(
  readLines("DESCRIPTION"),
  sep = "\n"
)

cat_ok()


cli::cat_rule("Checking the hook has set the MIT licence")
expect_true(
  file.exists("LICENSE")
)
expect_true(
  desc_get("License") == "MIT + file LICENSE"
)
cat_ok()

cli::cat_rule("Checking the DESCRIPTION is correct")
expect_true(
  desc_get("Package") == "golemmetrics"
)
expect_true(
  desc_get("Title") == "An Amazing Shiny App"
)
expect_true(
  all(desc_get_deps()$package %in% c("config", "golem", "shiny"))
)
cat_ok()

cli::cat_rule("Checking all files are here")

expected_files <- c(
  "DESCRIPTION",
  "NAMESPACE",
  "R",
  "R/app_config.R",
  "R/app_server.R",
  "R/app_ui.R",
  "R/run_app.R",
  "dev",
  "dev/01_start.R",
  "dev/02_dev.R",
  "dev/03_deploy.R",
  "dev/run_dev.R",
  "inst",
  "inst/app",
  "inst/app/www",
  "inst/app/www/favicon.ico",
  "inst/golem-config.yml",
  "man",
  "man/run_app.Rd"
)
actual_files <- fs::dir_ls(recurse = TRUE)

for (i in expected_files) {
  expect_true(i %in% actual_files)
}
cat_ok()

# Going through 01_start.R ----
#
cli::cat_rule("Going through 01_start.R")
cli::cat_line()

golem::fill_desc(
  pkg = temp_app,
  pkg_name = "golemmetrics", # The Name of the package containing the App
  pkg_title = "A App with Metrics about 'Golem'", # The Title of the package containing the App
  pkg_description = "Read metrics about {golem}.", # The Description of the package containing the App
  authors = person(
    given = "Colin", # Your First Name
    family = "Fay", # Your Last Name
    role = c("cre", "aut"),
    email = "colin@thinkr.fr"),
  repo_url = NULL, # The URL of the GitHub Repo (optional)
  pkg_version = "0.0.0.9000" # The Version of the package containing the App
)

cli::cat_rule("checking package name")
expect_equal(
  desc_get_field("Package"),
  "golemmetrics"
)
cat_ok()
cli::cat_rule("checking pkg_title name")
expect_equal(
  desc_get_field("Title"),
  "A App with Metrics about 'Golem'"
)
cat_ok()
cli::cat_rule("checking package name")
expect_equal(
  desc_get_field("Description"),
  "Read metrics about {golem}."
)
cat_ok()
cli::cat_rule("checking package name")
expect_equal(
  as.character(desc_get_author()),
  "Colin Fay <colin@thinkr.fr> [cre, aut]"
)
cat_ok()
cli::cat_rule("checking package version")
expect_equal(
  as.character(desc_get_version()),
  "0.0.0.9000"
)
cat_ok()

cli::cat_rule("set_golem_options")

expect_equal(
  golem::get_golem_wd(),
  golem::pkg_path()
)
expect_equal(
  golem::get_golem_name(),
  "golemmetrics"
)
expect_equal(
  golem::get_golem_version(),
  "0.0.0.9000"
)
expect_false(
  golem::app_prod()
)

cat_ok()

cli::cat_rule("Create Common Files")

# usethis::use_mit_license( "Golem User" )

expect_equal(
  desc_get_field("License"),
  "MIT + file LICENSE"
)
expect_true(
  file.exists("LICENSE")
)
usethis::use_readme_rmd(open = FALSE)
expect_true(
  file.exists("README.Rmd")
)

usethis::use_code_of_conduct("Golem user")
expect_true(
  file.exists("CODE_OF_CONDUCT.md")
)

usethis::use_news_md(open = FALSE)
expect_true(
  file.exists("NEWS.md")
)

cat_ok()

cli::cat_rule("use_recommended")

golem::use_recommended_tests(spellcheck = FALSE)
expect_true(
  dir.exists("tests")
)

# golem::use_recommended_deps()

golem::use_utils_ui(with_test = TRUE)
expect_true(
  file.exists("R/golem_utils_ui.R")
)
expect_true(
  file.exists("tests/testthat/test-golem_utils_ui.R")
)

golem::use_utils_server()
expect_true(
  file.exists("R/golem_utils_server.R")
)

cat_ok()

# Going through 02_dev ----
cli::cat_rule("Going through 02_dev.R")

cli::cat_rule("Testing usepackage")
if (!requireNamespace("cranlogs")) {
  pak::pak("cranlogs")
}
usethis::use_package("cranlogs")
expect_true(
  "cranlogs" %in% desc_get_deps()$package
)
cat_ok()

cli::cat_rule("Testing modules")
golem::add_module(
  name = "main",
  open = FALSE,
  module_template = crystalmountains::module_template,
  fct = "golem_logs",
  js = "golem_stars",
  utils = "pretty_num"
)

expect_true(
  file.exists("R/mod_main.R")
)

expect_true(
  file.exists("R/mod_main_fct_golem_logs.R")
)
write(
  readLines(
    system.file(
      "golemlogs",
      package = "crystalmountains"
    )
  ),
  "R/mod_main_fct_golem_logs.R",
  append = TRUE
)
expect_true(
  file.exists("R/mod_main_utils_pretty_num.R")
)
write(
  readLines(
    system.file(
      "prettynum",
      package = "crystalmountains"
    )
  ),
  "R/mod_main_utils_pretty_num.R",
  append = TRUE
)
expect_true(
  file.exists("inst/app/www/golem_stars.js")
)
unlink("inst/app/www/golem_stars.js", TRUE, TRUE)

golem::document_and_reload()

cat_ok()

golem::add_fct("helpers", open = FALSE)
expect_true(
  file.exists("R/fct_helpers.R")
)
unlink("R/fct_helpers.R", TRUE, TRUE)
golem::add_utils("helpers", open = FALSE)
expect_true(
  file.exists("R/utils_helpers.R")
)
unlink("R/utils_helpers.R", TRUE, TRUE)

golem::add_js_file("script", template = crystalmountains::js_file, open = FALSE)
golem::add_js_handler("handlers", template = crystalmountains::js_handler, open = FALSE)
golem::add_css_file("custom", template = crystalmountains::css_file, open = FALSE)

cli::cat_rule("Testing and installing package")
golem::document_and_reload()

usethis::use_dev_package(
  "golem",
  remote = "https://github.com/ThinkR-open/golem"
)

devtools::test()
cat_ok()

cli::cat_rule("Testing 03_dev")
devtools::check()
remotes::install_local(force = TRUE, upgrade = FALSE)
targz <- devtools::build()
remotes::install_local(targz, force = TRUE, upgrade = FALSE)

cat_ok()

golem::add_positconnect_file()

golem::add_dockerfile_with_renv(
  repos = "https://packagemanager.rstudio.com/all/__linux__/focal/latest",
  from = "rocker/shiny-verse:4.0.4",
  extra_sysreqs = c("libxml2-dev"),
  open = FALSE,
  output_dir = "/golemmetrics/deploy",
  document = FALSE
)

# Restore old wd

# unlink(temp_app, TRUE, TRUE)
# unlink(temp_golem, TRUE, TRUE)
# unlink(temp_lib, TRUE, TRUE)

cli::cat_rule("Completed")
