box::use(
  shiny[tagList, fluidRow, HTML, column,p, br, div, moduleServer, NS, selectInput, textOutput, renderText, tags, dateRangeInput, checkboxInput, icon,
        downloadButton, observeEvent, reactive, showModal, modalDialog,modalButton, bindCache, req],
  shinydashboard[valueBoxOutput, renderValueBox, valueBox],
  bslib[value_box, card, card_header],
  shinycssloaders[withSpinner],
  shinyBS[bsModal, ],
  DT[DTOutput, renderDT, datatable],
  data.table[as.data.table],
  datasets[mtcars],
  shinyWidgets[actionBttn],
  reactable[reactableOutput, renderReactable, reactable, colDef, JS, getReactableState, reactableTheme, reactableLang],
  memoise[memoise],
  cachem[cache_mem, ],
  stringr[str_extract]
)

box::use(
  app/data_prep/data_fcts[clean_genotype_columns]
)


#' @export
ui <- function(id) {
  ns <- NS(id)
  tagList(

    div(
      value_box(
        title = textOutput(ns("title")),
        value = textOutput(ns("value")),
        theme = "primary",
        textOutput(ns("description1")),
        textOutput(ns("description2")),
        textOutput(ns("description3")),
        showcase = tagList(
          actionBttn(
            inputId = ns("my_button"),
            label = "Details",
            style = "bordered",
            color = "default",
            size = "xs",
            block = TRUE,
            no_outline = TRUE
          )
        ),
        showcase_layout = "bottom" # Position the button at the bottom
      )
    ),

    bsModal("modalExample", "Data Table", "my_button", size = "large",
         reactableOutput(ns("table")))
  )
}

#' @export
server <- function(id, title, data_file, controls, date_col, seed_column ) {
  moduleServer(id, function(input, output, session) {
    ns <- NS(id)

    # data_input <- reactive({
    #   result <- as.data.table(data)
    #   if(controls$site !="All"){
    #     result <- result[Location == controls$site]
    #   }
    #
    #   start_date <- lubridate::ymd(controls$daterange[1])
    #   end_date <- lubridate::ymd(controls$daterange[2])
    #   result[get(date_col) >= start_date & get(date_col) <= end_date]
    #
    # })
    #
    #


    # Create a memory cache (adjust size as needed, 200MB shown here)
    data_cache <- cache_mem(max_size = 200 * 1024^2)

    data_input <- reactive({
      # Create a unique cache key based on all filtering parameters
      cache_key <- paste(
        controls$site,
        controls$daterange[1],
        controls$daterange[2],
        sep = "|"
      )

      # Define the filtering function with memoization
      filtered_data <- memoise(
        function() {
          # Start with the most restrictive filter to reduce data size quickly
          data <- readRDS(paste0("app/data/",tolower(controls$site), "_", data_file,".rds"))
          result <- data |>
            clean_genotype_columns()

          # Apply site filter if needed
          if (controls$site !="All") {
            result <- result |>
              dplyr::filter(Location == controls$site)
          }


          # Convert dates once (outside the filter)
          start_date <- lubridate::ymd(controls$daterange[1])
          end_date <- lubridate::ymd(controls$daterange[2])

          # Date filtering using base R for better performance
          date_vector <- result[[date_col]]
          result <- result[date_vector >= start_date & date_vector <= end_date, ]

          return(result)
        },
        cache = data_cache  # Use our predefined cache
      )

      # Return the cached or newly computed result
      filtered_data()
    })

    uniq_input <- reactive({
      seed_column <- rlang::sym(seed_column)
      data_input() |>
        dplyr::group_by(Female_Genotype, Male_Genotype) |>
        dplyr::summarise(n = sum(!!seed_column, na.rm = TRUE), .groups = "drop")
    })

    output$title<- renderText({
      req(controls$site)
      title
    })

    output$value<- renderText({
      req(controls$site)
      sum(uniq_input()$n)
    })

    output$description1<- renderText({
      req(controls$site)
      paste(nrow(uniq_input())," Unique combinations")
    })


    # table
    observeEvent(input$my_button, {
      # Trigger the modal when the action button is clicked
      showModal(modalDialog(
        title = title,
        renderReactable({
          reactable(
            data_input(),
            defaultColDef = colDef(minWidth = 100, maxWidth = 200, width = 150,
                                   headerStyle = list(color = "hsl(203, 15%, 47%)")),
            columns = list(
              `Female Genotype` = colDef(html = TRUE, cell = function(value, index) {
                sprintf('<a href="%s" target="_blank">%s</a>', dt$`Female URL`[index], value)
              }),
              `Male Genotype` = colDef(html = TRUE, cell = function(value, index) {
                sprintf('<a href="%s" target="_blank">%s</a>', dt$`Male URL`[index], value)
              }),
              `Female URL` = colDef(show = FALSE),
              `Male URL` = colDef(show = FALSE)
            ),
            filterable = TRUE,
            searchable = TRUE,
            selection = "multiple",
            onClick = "select",
            minRows = 10,
            highlight = TRUE,
            language = reactableLang(
              noData = "No data found",
              pageInfo = "{rowStart}\u2013{rowEnd} of {rows} data"
            ),
            theme = reactableTheme(
              highlightColor = "#f3fafb",
              borderColor = "hsl(0, 0%, 93%)",
              headerStyle = list(borderColor = "hsl(0, 0%, 90%)")
            )
          )
        }),
        size = "xl",
        easyClose = TRUE,
        footer = modalButton("Dismiss"),
        fade = TRUE  # No footer buttons
      ))
    })


  })
}
