suppressPackageStartupMessages({
  library(dplyr)
  library(jsonlite)
  library(readxl)
})

args <- commandArgs(trailingOnly = TRUE)
if (length(args) != 1) {
  stop("Usage: Rscript analyze_scores.R /path/to/reviews_5scores_all_providers.xlsx")
}

workbook_path <- normalizePath(args[[1]], mustWork = TRUE)
script_arg <- grep("^--file=", commandArgs(trailingOnly = FALSE), value = TRUE)[[1]]
script_path <- normalizePath(sub("^--file=", "", script_arg), mustWork = TRUE)
output_path <- file.path(dirname(script_path), "aggregate-results.json")

constructs <- c("emotional", "epistemic", "social", "functional", "conditional")
providers <- c("OpenAI", "Claude", "Cohere", "Gemini")
suffixes <- c(OpenAI = "", Claude = "_claude", Cohere = "_cohere", Gemini = "_gemini")

score_column <- function(construct, provider) {
  paste0(construct, "_value_score", suffixes[[provider]])
}

to_numeric <- function(values) {
  suppressWarnings(as.numeric(trimws(as.character(values))))
}

scores <- read_excel(workbook_path, sheet = 1, col_types = "text") |>
  filter(!is.na(Review_Overall_No), trimws(Review_Overall_No) != "")

required_columns <- unlist(lapply(
  providers,
  function(provider) vapply(constructs, score_column, character(1), provider = provider)
))
missing_columns <- setdiff(required_columns, names(scores))
if (length(missing_columns) > 0) {
  stop("Missing expected score columns: ", paste(missing_columns, collapse = ", "))
}

for (column in required_columns) {
  scores[[column]] <- to_numeric(scores[[column]])
  invalid_range <- !is.na(scores[[column]]) & (scores[[column]] < 0 | scores[[column]] > 100)
  if (any(invalid_range)) {
    stop("Score outside 0-100 range in column: ", column)
  }
}

score_summary <- lapply(constructs, function(construct) {
  row <- list(construct = tools::toTitleCase(construct))
  for (provider in providers) {
    values <- scores[[score_column(construct, provider)]]
    usable <- values[!is.na(values)]
    row[[provider]] <- list(
      usable_rows = length(usable),
      mean = round(mean(usable), 2),
      median = round(median(usable), 2),
      zero_rate_pct = round(mean(usable == 0) * 100, 2)
    )
  }
  row
})

comparisons <- lapply(constructs, function(construct) {
  baseline <- scores[[score_column(construct, "OpenAI")]]
  row <- list(construct = tools::toTitleCase(construct))
  for (provider in providers[providers != "OpenAI"]) {
    candidate <- scores[[score_column(construct, provider)]]
    keep <- !is.na(baseline) & !is.na(candidate)
    differences <- candidate[keep] - baseline[keep]
    row[[provider]] <- list(
      paired_rows = sum(keep),
      correlation = round(cor(candidate[keep], baseline[keep]), 4),
      mean_absolute_error = round(mean(abs(differences)), 2),
      mean_difference = round(mean(differences), 2)
    )
  }
  row
})

coverage <- lapply(providers[providers != "OpenAI"], function(provider) {
  columns <- vapply(constructs, score_column, character(1), provider = provider)
  scored <- sum(complete.cases(scores[, columns]))
  list(
    provider = provider,
    scored = scored,
    coverage_pct = round(scored / nrow(scores) * 100, 2),
    unscored = nrow(scores) - scored
  )
})

openai_usable <- vapply(
  constructs,
  function(construct) sum(!is.na(scores[[score_column(construct, "OpenAI")]])),
  numeric(1)
)

output <- list(
  project = list(
    review_count = nrow(scores),
    construct_count = length(constructs),
    model_count = length(providers),
    added_provider_count = length(providers) - 1,
    target_provider_review_pairs = nrow(scores) * (length(providers) - 1),
    appended_score_fields = length(constructs) * (length(providers) - 1)
  ),
  coverage = coverage,
  baseline_quality = list(
    provider = "OpenAI",
    usable_numeric_rows_per_construct = as.list(openai_usable),
    excluded_or_unusable_rows_per_construct = as.list(nrow(scores) - openai_usable)
  ),
  score_summary = score_summary,
  comparisons_with_openai = comparisons,
  correlations_with_openai = lapply(comparisons, function(row) {
    list(
      construct = row$construct,
      Claude = row$Claude$correlation,
      Cohere = row$Cohere$correlation,
      Gemini = row$Gemini$correlation
    )
  })
)

write_json(output, output_path, auto_unbox = TRUE, pretty = TRUE, digits = 4)
cat("Wrote aggregate analysis to", output_path, "\n")
