---
title: "RWE Cohort Validation Report"
date: "`r params$run_date`"
output:
  html_document:
    self_contained: true
    toc: true
    toc_float: true
    theme: cosmo
params:
  results: null
  cdm_schema: null
  cohort_id: null
  check_summary: null
  package_version: null
  run_date: null
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE,
                      fig.width = 9, fig.height = 4.5)
has_ggplot <- requireNamespace("ggplot2", quietly = TRUE)
if (has_ggplot) library(ggplot2)

res          <- params$results
attrition    <- res$attrition
density      <- res$density
concepts     <- res$concepts
covariates   <- res$covariates
data_source  <- res$data_source
check_sum    <- params$check_summary

status_badge <- function(s) {
  switch(s,
    pass = "\U1F7E2 PASS",
    warn = "\U1F7E1 WARN",
    fail = "\U1F534 FAIL",
    s)
}

kbl <- function(df, ...) knitr::kable(df, ...)
```

This report validates an instantiated cohort on an OMOP CDM database for
real-world-evidence use, following the FDA RWE framework (Relevance +
Reliability) and HARPER protocol structure.

- **CDM schema:** `r params$cdm_schema`
- **Cohort definition id:** `r params$cohort_id`
- **Generated:** `r params$run_date`
- **rwevalidate version:** `r params$package_version`

# 6. Validation Summary {-}

*Traffic-light status per check (shown first for at-a-glance review).*

```{r summary}
if (!is.null(check_sum) && nrow(check_sum) > 0) {
  disp <- data.frame(
    Status  = vapply(check_sum$status, status_badge, character(1)),
    Section = check_sum$section,
    `Maps to` = check_sum$maps_to,
    Detail  = check_sum$detail,
    check.names = FALSE, stringsAsFactors = FALSE
  )
  kbl(disp, align = "llll")
} else {
  cat("_No checks were run._")
}
```

# 1. Data Source Summary

*FDA Relevance: is the data fit for the question?*

```{r data-source}
if (!is.null(data_source)) {
  ds <- data.frame(
    Property = names(data_source),
    Value    = vapply(data_source, function(x) paste(format(x), collapse = ", "),
                      character(1)),
    stringsAsFactors = FALSE
  )
  kbl(ds)
} else if (!is.null(attrition)) {
  cat(sprintf("Cohort size: **%d** subjects in schema `%s` (cohort id %s).\n\n",
              attrition$cohort_size, params$cdm_schema, params$cohort_id))
  cat("_Full data-source metadata (CDM version, patient N, date range) is",
      "populated when the report is produced via_ `validate_cohort()`.")
} else {
  cat("_No data-source information available._")
}
```

# 2. Concept Coverage

*FDA Relevance - vocabulary and concept mapping.*

```{r concepts, results='asis'}
if (is.null(concepts)) {
  cat("_Concept coverage was not run. Supply_ `concept_ids` _to_ `validate_cohort()`",
      "_to enable Module 1._")
} else {
  cat(sprintf(
    "**Concept prevalence:** %d of %d CDM persons (%.1f%%) have a cohort-defining concept.\n\n",
    concepts$prevalence$n_with, concepts$prevalence$n_total, concepts$prevalence$pct))

  cat(sprintf(
    "**Ancestor coverage:** %d of %d descendant concepts (%.1f%%) appear in the data.\n\n",
    concepts$ancestor_coverage$present_descendants,
    concepts$ancestor_coverage$total_descendants,
    concepts$ancestor_coverage$pct_present))

  cat("**Vocabulary mapping rate by domain**\n\n")
  print(kbl(concepts$mapping_by_domain))

  if (length(concepts$flags)) {
    cat("\n\n**Flags**\n\n")
    for (f in concepts$flags) cat("-", f, "\n")
  }
  cat("\n")
}
```

# 3. Cohort Attrition

*HARPER Section 5 and RECORD-PE Item 6: who is in the cohort and how it was built.*

```{r attrition, results='asis'}
if (is.null(attrition)) {
  cat("_Attrition module was not run._\n")
} else {
  cat(sprintf("**Cohort size:** %d subjects.\n\n", attrition$cohort_size))

  cat("**Prior observation coverage**\n\n")
  print(kbl(attrition$obs_coverage))
  cat("\n\n**Demographics at index**\n\n")
  print(kbl(attrition$demographics))

  if (length(attrition$flags)) {
    cat("\n\n**Flags**\n\n")
    for (f in attrition$flags) cat("-", f, "\n")
  }
  cat("\n")
}
```

```{r attrition-plot, eval=has_ggplot}
if (!is.null(attrition) && nrow(attrition$index_date_summary) > 0) {
  ggplot(attrition$index_date_summary, aes(index_year, n)) +
    geom_col(fill = "#2c7fb8") +
    labs(title = "Index date distribution by year",
         x = "Index year", y = "Patients") +
    theme_minimal()
}
```

# 4. Temporal Data Density

*FDA Reliability: data accrual around the index date.*

```{r density-heatmap, eval=has_ggplot}
if (!is.null(density) && nrow(density$density_by_domain) > 0) {
  ggplot(density$density_by_domain,
         aes(months_from_index, domain, fill = records_per_patient)) +
    geom_tile() +
    scale_fill_viridis_c(option = "C", trans = "log10") +
    labs(title = "Record density: records per patient per month",
         x = "Months from index", y = NULL, fill = "Rec/patient (log)") +
    theme_minimal()
} else {
  cat("_No density data available._")
}
```

```{r followup, results='asis'}
if (!is.null(density) && nrow(density$followup_summary) > 0) {
  cat("**Follow-up completeness: censoring breakdown**\n\n")
  print(kbl(density$followup_summary))
  cat("\n")
  if (length(density$flags)) {
    cat("\n**Flags**\n\n")
    for (f in density$flags) cat("-", f, "\n")
  }
} else {
  cat("_Follow-up summary not available._")
}
```

```{r followup-plot, eval=has_ggplot}
if (!is.null(density) && nrow(density$followup_detail) > 0) {
  ggplot(density$followup_detail, aes(followup_days)) +
    geom_histogram(bins = 30, fill = "#41b6c4") +
    labs(title = "Follow-up duration", x = "Follow-up (days)", y = "Patients") +
    theme_minimal()
}
```

# 5. Covariate Feasibility

*HARPER Sec.4 - comparability between target and comparator arms.*

```{r covariates, results='asis'}
if (is.null(covariates)) {
  cat("_Covariate feasibility was not run. Supply_ `comparator_id`",
      "_to_ `validate_cohort()` _to enable Module 4._")
} else {
  pw <- covariates$power
  cat(sprintf(
    "**Power:** %s at n = %d (target) vs %d (comparator), assuming %.2f vs %.2f event rates (alpha = %.2f).\n\n",
    ifelse(is.na(pw$power), "NA", format(pw$power)),
    pw$n_target, pw$n_comparator, pw$assumed_p_target,
    pw$assumed_p_comparator, pw$sig_level))

  cat("**Standardized mean differences (baseline)**\n\n")
  print(kbl(covariates$smd_table))

  if (length(covariates$flags)) {
    cat("\n\n**Flags**\n\n")
    for (f in covariates$flags) cat("-", f, "\n")
  }
  cat("\n\n**Top covariate prevalence by arm**\n\n")
  print(kbl(utils::head(covariates$prevalence_table, 20)))
  cat("\n")
}
```

```{r love-plot, eval=has_ggplot}
if (!is.null(covariates) && nrow(covariates$smd_table) > 0) {
  d <- covariates$smd_table[!is.na(covariates$smd_table$abs_smd), ]
  d$covariate <- factor(d$covariate, levels = d$covariate[order(d$abs_smd)])
  ggplot(d, aes(abs_smd, covariate)) +
    geom_point(size = 2.5, colour = "#2c7fb8") +
    geom_vline(xintercept = 0.1, linetype = "dashed", colour = "red") +
    labs(title = "Love plot: absolute SMD by covariate",
         x = "|SMD| (dashed line = 0.1 imbalance threshold)", y = NULL) +
    theme_minimal()
}
```

---

```{r footer, results='asis'}
cat(sprintf("_Report generated by rwevalidate %s. JSON sidecar: ",
            params$package_version))
cat("`validation_results.json` (same directory)._")
```
