#' Identifies Candidate Genes based on identified Quantitative Trait Loci (QTL) analysis
#'
#' @param data_file The input data in .csv format. (sample_data_wheat_qtl or sample_data_rice_qtl for demo purpose)
#' @param crop Either "wheat" or "rice". (by default it will be wheat)
#' @param genome_source Character specifying either "online" (default Ensembl lookup) or "local" (uses a local GFF3 file).
#' @param gff3_file Path to a local custom .gff3 file. Only utilized if genome_source = "local".
#'
#' @returns A data frame containing traits, QTL, gene_id, gene_size, and gene_type.
#' @export
#'
#' @examples
#' load(system.file("extdata", "precomputed_sample_results_qtl.rda", package = "geneNR"))
#' message(sample_results)
#' \dontrun{
#' result <- geneQTL("sample_data_wheat_qtl", crop="wheat")
#' # Local mapping workflow:
#' # gff_path <- system.file("extdata", "sample_crop.gff3", package = "geneNR")
#' # result <- geneQTL("sample_data_wheat_qtl", genome_source="local", gff3_file=gff_path)
#' }
geneQTL <- function(data_file, crop = "wheat", genome_source = "online", gff3_file = NULL) {
  # Save current working directory and options, ensure they are reset
  parent_dir <- getwd()
  on.exit(setwd(parent_dir), add = TRUE)  # Reset working directory

  # Save current options and ensure they are reset
  old_options <- options()  # Save all current options
  on.exit(options(old_options), add = TRUE)  # Reset all options to their original state

  # Check for required packages
  required_pkgs <- c("readr", "stringr", "utils", "httr", "rvest", "xml2", "writexl")
  for (pkg in required_pkgs) {
    if (!requireNamespace(pkg, quietly = TRUE)) {
      stop(paste("The", pkg, "package is required but not installed."))
    }
  }

  # Define file paths for sample data included in the package
  sample_data_wheat_qtl <- sample_data_wheat_qtl
  sample_data_rice_qtl <- sample_data_rice_qtl

  # Load data
  if (data_file == "sample_data_wheat_qtl") {
    data <- sample_data_wheat_qtl
  } else if (data_file == "sample_data_rice_qtl") {
    data <- sample_data_rice_qtl
  } else {
    if (!file.exists(data_file)) {
      stop("The specified data file does not exist.")
    }
    data <- readr::read_csv(data_file)
  }

  # Print column names for verification
  message(colnames(data))

  # Check if essential columns exist
  required_columns <- c("start", "stop", "Chr", "traits")
  missing_columns <- setdiff(required_columns, colnames(data))
  if (length(missing_columns) > 0) {
    stop(paste("Missing required columns:", paste(missing_columns, collapse = ", ")))
  }

  data$Chr   <- as.character(data$Chr)
  data$start <- as.numeric(data$start)
  data$stop  <- as.numeric(data$stop)

  # ==========================================================================
  # BRANCH 1: LOCAL CUSTOM GFF3 INTERSECTION
  # ==========================================================================
  if (genome_source == "local") {
    if (is.null(gff3_file) || !file.exists(gff3_file)) {
      stop("A valid local .gff3 file path must be provided when genome_source = 'local'")
    }

    message("Parsing local GFF3 reference file...")
    gff <- readr::read_tsv(gff3_file, comment = "#",
                           col_names = c("seqname", "source", "feature", "start", "end", "score", "strand", "frame", "attribute"),
                           col_types = "ccciidccc")

    gff_genes <- gff[gff$feature == "gene", ]
    if (nrow(gff_genes) == 0) stop("No features labeled as 'gene' discovered within GFF3.")
    gff_genes$seqname <- as.character(gff_genes$seqname)

    final_list <- list()
    for (i in 1:nrow(data)) {
      current_chr <- data$Chr[i]
      win_start   <- data$start[i]
      win_stop    <- data$stop[i]

      matched_genes <- gff_genes[gff_genes$seqname == current_chr &
                                   gff_genes$start <= win_stop &
                                   gff_genes$end >= win_start, ]

      if (nrow(matched_genes) > 0) {
        gene_ids <- stringr::str_match(matched_genes$attribute, "ID=([^;]+)")[, 2]
        gene_ids[is.na(gene_ids)] <- stringr::str_match(matched_genes$attribute[is.na(gene_ids)], "Name=([^;]+)")[, 2]

        chunk <- data.frame(
          traits    = data$traits[i],
          QTL       = paste0(current_chr, "_", win_start, "_", win_stop),
          gene_size = paste0(matched_genes$seqname, ":", matched_genes$start, "-", matched_genes$end),
          gene_id   = gene_ids,
          gene_type = matched_genes$source,
          stringsAsFactors = FALSE
        )
        final_list[[length(final_list) + 1]] <- chunk
      }
    }

    if (length(final_list) == 0) {
      filtered_df <- data.frame(traits=character(), QTL=character(), gene_size=character(), gene_id=character(), gene_type=character())
    } else {
      filtered_df <- do.call(rbind, final_list)
      filtered_df <- filtered_df[!duplicated(filtered_df$gene_id), ]
    }

    output_file <- tempfile("filtered_gene_id_qtl", fileext = ".xlsx")
    writexl::write_xlsx(filtered_df, output_file)
    return(filtered_df)
  }

  # ==========================================================================
  # BRANCH 2: ONLINE DATABASE EXTRACTION (Original Workflow Execution)
  # ==========================================================================
  base_url <- switch(crop,
                     "wheat" = "https://plants.ensembl.org/Triticum_aestivum/Export/Output/Location?db=core;flank3_display=0;flank5_display=0;output=csv;r='a';strand=feature;param=gene;_format=Text",
                     "rice" = "https://plants.ensembl.org/Oryza_sativa/Export/Output/Location?db=core;flank3_display=0;flank5_display=0;output=csv;r='a';strand=feature;param=gene;_format=Text",
                     stop("Unsupported crop type"))

  data$search_window <- paste0(data$Chr, ":", data$start, "-", data$stop)
  data$url <- stringr::str_replace(base_url, "'a'", data$search_window)
  data$file_name <- paste0(data$traits, "_", data$Chr, "_", data$start, "_", data$stop)

  message(utils::head(data))

  temp_dir <- tempdir()
  new_folder <- file.path(temp_dir, "rough_results")
  if (!dir.exists(new_folder)) {
    dir.create(new_folder)
  }
  setwd(new_folder)

  results <- data.frame(file_name = character(), search_window = character(), text_content = character(), stringsAsFactors = FALSE)

  retry_request <- function(url, max_attempts = 3, delay = 5) {
    attempt <- 1
    while (attempt <= max_attempts) {
      tryCatch({
        response <- httr::GET(url, httr::timeout(5))
        if (httr::status_code(response) == 200) {
          return(response)
        } else {
          stop("Server returned non-200 status code")
        }
      }, error = function(e) {
        if (attempt == max_attempts) {
          stop("Max attempts reached. Error: ", e)
        } else {
          Sys.sleep(delay)
          attempt <- attempt + 1
        }
      })
    }
  }

  for (i in 1:nrow(data)) {
    url <- data$url[i]
    tryCatch({
      response <- retry_request(url)
      webpage <- xml2::read_html(response)
      text_content <- rvest::html_text(rvest::html_nodes(webpage, "body"))
      file_name <- paste0(data$file_name[i], ".txt")
      results <- rbind(results, data.frame(file_name = file_name, search_window = data$search_window[i], text_content = text_content, stringsAsFactors = FALSE))
      writeLines(text_content, file_name)
    }, error = function(e) {
      message(paste("Error processing URL:", url, "Error:", e))
    })
  }

  files <- list.files(pattern = "\\.txt$")
  data_list <- lapply(files, function(file) {
    df <- readr::read_delim(file, delim = ",")
    df$file_name <- file
    return(df)
  })

  data_data <- do.call(rbind, data_list)

  if (!all(c("file_name", "seqname", "start", "end", "gene_id", "gene_type") %in% colnames(data_data))) {
    stop("The data does not contain the expected columns.")
  }

  data_data$file_name <- as.character(data_data$file_name)
  data_data$seqname <- as.character(data_data$seqname)
  data_data$start <- as.character(data_data$start)
  data_data$stop <- as.character(data_data$end)
  data_data$gene_size <- paste0(data_data$seqname, ":", data_data$start, "-", data_data$stop)

  data_data <- data_data[, c("file_name", "gene_size", "gene_id", "gene_type")]

  df <- data_data
  filtered_df <- df[grepl("^[^_]+\\d+$", df$gene_id) & !grepl("LC", df$gene_id), ]
  filtered_df <- filtered_df[!duplicated(filtered_df$gene_id), ]

  split_columns <- stringr::str_match(filtered_df$file_name, "^(.*?)_(.*)\\.txt$")
  filtered_df$traits <- split_columns[, 2]
  filtered_df$QTL <- split_columns[, 3]

  filtered_df <- filtered_df[, c("traits", "QTL", "gene_size", "gene_id", "gene_type")]

  message(filtered_df)
  setwd(parent_dir)
  output_file <- tempfile("filtered_gene_id", fileext = ".xlsx")
  writexl::write_xlsx(filtered_df, output_file)
  message(paste("Filtered gene IDs saved to", output_file))
  unlink(new_folder, recursive = TRUE)

  return(filtered_df)
}
