---
title: "Data Quality Report"
format:
  html:
    embed-resources: true
    theme: flatly
    toc: false
params:
  rds_path: ""
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE,
                      fig.path = file.path(tempdir(), "dqcheckr_figs", ""))
library(kableExtra)
library(ggplot2)
library(dplyr)

p <- readRDS(params$rds_path)

`%||%` <- function(a, b) if (!is.null(a)) a else b

status_colour <- function(s) {
  switch(s, FAIL = "red", WARN = "orange", PASS = "green", INFO = "grey", "grey")
}

badge_html <- function(s) {
  col <- switch(s, FAIL = "#d9534f", WARN = "#f0ad4e", PASS = "#5cb85c", "#777")
  sprintf('<span style="background:%s;color:#fff;padding:4px 10px;border-radius:4px;font-weight:bold;">%s</span>',
          col, s)
}

results_to_df <- function(results) {
  if (length(results) == 0) return(data.frame())
  do.call(rbind, lapply(results, function(r) {
    data.frame(
      `Check ID`   = r$check_id,
      `Check Name` = r$check_name,
      Column       = ifelse(is.na(r$column), "-", r$column),
      Status       = r$status,
      Observed     = r$observed,
      Threshold    = ifelse(is.na(r$threshold), "-", r$threshold),
      Message      = r$message,
      stringsAsFactors = FALSE,
      check.names = FALSE
    )
  }))
}

status_order <- c(FAIL = 1, WARN = 2, PASS = 3, INFO = 4)

sort_results_df <- function(df) {
  if (nrow(df) == 0) return(df)
  df[order(status_order[df$Status]), ]
}

colour_status_col <- function(df) {
  df$Status <- kableExtra::cell_spec(
    df$Status,
    color = sapply(df$Status, status_colour),
    bold  = TRUE
  )
  df
}
```

## 1. Header

**Dataset**: `r p$dataset_name`
**File**: `r p$file_name`
**Run time**: `r p$run_timestamp`
**Overall status**: `r knitr::raw_html(badge_html(p$overall_status))`

---

## 2. File summary

```{r file-summary}
fsize <- tryCatch(file.info(p$file_path)$size, error = function(e) NA)
fsize_str <- if (!is.na(fsize)) sprintf("%.1f KB", fsize / 1024) else "N/A"

summary_df <- data.frame(
  Item  = c("Row count", "Column count", "File size", "Format", "Encoding"),
  Value = c(
    as.character(nrow(p$df)),
    as.character(ncol(p$df)),
    fsize_str,
    toupper(p$config$format %||% "CSV"),
    p$config$encoding %||% "UTF-8"
  ),
  stringsAsFactors = FALSE
)

kableExtra::kbl(summary_df, col.names = c("Item", "Value")) |>
  kableExtra::kable_styling(full_width = FALSE)
```

---

## 3. Quality checks

```{r qc-table}
qc_df <- results_to_df(p$qc_results)
if (nrow(qc_df) > 0) {
  qc_df <- sort_results_df(qc_df)
  qc_df <- colour_status_col(qc_df)
  kableExtra::kbl(qc_df, escape = FALSE) |>
    kableExtra::kable_styling(bootstrap_options = c("striped", "hover"))
} else {
  cat("No quality check results.")
}
```

---

```{r custom-section, results='asis'}
if (length(p$custom_results) > 0) {
  cat("## Custom checks\n\n")
  cc_df <- results_to_df(p$custom_results)
  cc_df <- sort_results_df(cc_df)
  cc_df <- colour_status_col(cc_df)
  print(kableExtra::kbl(cc_df, escape = FALSE) |>
    kableExtra::kable_styling(bootstrap_options = c("striped", "hover")))
  cat("\n\n---\n\n")
}
```

```{r comparison-section, results='asis'}
if (length(p$cp_results) > 0) {
  cat("## Version comparison\n\n")

  # C-05: show all FAIL/WARN messages as a bullet list
  bad_results <- Filter(\(r) r$status %in% c("FAIL", "WARN"), p$cp_results)
  if (length(bad_results) > 0) {
    cat("**Issues found:**\n\n")
    for (r in bad_results) cat(sprintf("- %s\n", r$message))
    cat("\n")
  } else {
    cat("**Summary**: All comparison checks passed.\n\n")
  }

  cp_df <- results_to_df(p$cp_results)
  cp_df <- sort_results_df(cp_df)
  cp_df <- colour_status_col(cp_df)
  print(kableExtra::kbl(cp_df, escape = FALSE) |>
    kableExtra::kable_styling(bootstrap_options = c("striped", "hover")))
  cat("\n\n---\n\n")
}
```

```{r trend-header, results='asis'}
hist <- p$snapshot_history
show_trend <- !is.null(hist) && nrow(hist) >= 2
if (show_trend) {
  hist$run_timestamp <- as.POSIXct(hist$run_timestamp,
                                    format = "%Y-%m-%dT%H:%M:%SZ", tz = "UTC")
  hist <- hist[order(hist$run_timestamp), ]
  cat("## Historical trend\n\n")
}
```

```{r trend-plot, fig.width=10, fig.height=4}
if (show_trend) {
  p1 <- ggplot(hist, aes(x = run_timestamp, y = row_count)) +
    geom_line() + geom_point() +
    labs(title = "Row count over last runs", x = "Run time", y = "Row count") +
    theme_minimal()

  hist_long <- tidyr::pivot_longer(
    hist[, c("run_timestamp", "check_pass_count",
             "check_warn_count", "check_fail_count")],
    cols = -run_timestamp, names_to = "type", values_to = "count"
  )
  hist_long$type <- gsub("check_|_count", "", hist_long$type)

  p2 <- ggplot(hist_long, aes(x = run_timestamp, y = count, fill = type)) +
    geom_col(position = "stack") +
    scale_fill_manual(values = c(pass = "#5cb85c", warn = "#f0ad4e", fail = "#d9534f")) +
    labs(title = "Check outcomes over last runs", x = "Run time", y = "Count",
         fill = "Status") +
    theme_minimal()

  gridExtra::grid.arrange(p1, p2, ncol = 2)
}
```

```{r trend-footer, results='asis'}
if (show_trend) cat("\n\n---\n\n")
```

## Appendix - Column statistics

Per-column statistics computed for this run.

```{r appendix}
if (!is.null(p$col_stats)) {
  col_stats <- p$col_stats
  names(col_stats) <- c("Column", "Stat", "Value", "Threshold", "Severity")
  kableExtra::kbl(col_stats) |>
    kableExtra::kable_styling(bootstrap_options = c("striped", "condensed"),
                              full_width = TRUE)
}
```
