library(ncdf4)
library(lubridate)

dates <- format(seq(as.Date("2024-03-01"), as.Date("2024-10-01"), by = "month"), "%Y%m")
patho <- "/esarchive/recon/ecmwf/era5land/daily/"

# Define locations
locations <- list(
  vriotajo = c(lat = 39.87, lon = 355.87)
)
location_names <- names(locations)

# Function to find nearest index
find_nearest_index <- function(value, grid) {
  which.min(abs(grid - value))
}

# Function to load one variable (tasmax or tasmin) and return s2dv_cube
load_variable_to_cube <- function(var_name) {
  all_obs <- list()
  all_days <- c()
  
  for (j in seq_along(dates)) {
    date <- dates[j]
    file_path <- paste0(patho, var_name, "/", var_name, "_", date, ".nc")
    cat("Loading:", file_path, "\n")
    
    nc_data <- nc_open(file_path)
    lat_vals <- ncvar_get(nc_data, "lat")
    lon_vals <- ncvar_get(nc_data, "lon")
    time_vals <- ncvar_get(nc_data, "time")
    var_vals <- ncvar_get(nc_data, var_name)
    fill_value <- ncatt_get(nc_data, var_name, "_FillValue")$value
    
    time_units <- ncatt_get(nc_data, "time", "units")$value
    ref_date <- sub("hours since ", "", time_units)
    ref_date <- as.POSIXct(ref_date, tz = "UTC")
    dates_current <- as.Date(ref_date + time_vals * 3600, tz = "UTC")
    
    # Ensure dates are in the correct format (YYYYMMDD with zero padding for days < 10)
    dates_current <- format(dates_current, "%Y%m%d")
    
    nc_close(nc_data)
    
    for (i in seq_along(locations)) {
      loc_name <- location_names[i]
      loc <- locations[[i]]
      lat_idx <- find_nearest_index(loc["lat"], lat_vals)
      lon_idx <- find_nearest_index(loc["lon"], lon_vals)
      
      obs_vals <- var_vals[lon_idx, lat_idx, ]
      obs_vals[obs_vals == fill_value] <- NA
      
      if (j == 1) {
        all_obs[[loc_name]] <- obs_vals
      } else {
        all_obs[[loc_name]] <- c(all_obs[[loc_name]], obs_vals)
      }
    }
    
    all_days <- c(all_days, dates_current)
  }
  
  n_loc <- length(locations)
  n_time <- length(all_days)
  result_array <- array(NA, dim = c(n_loc, n_time, 1),
                        dimnames = list(
                          loc = location_names,
                          time = NULL,
                          variable = var_name))
  
  for (i in seq_along(locations)) {
    loc_name <- location_names[i]
    result_array[i, , 1] <- all_obs[[loc_name]]
  }
  
  # Properly format Dates
  dates_list <- list(start = as.Date(all_days, format = "%Y%m%d"))
  names(dates_list$start) <- all_days  # Use all_days as names to match the dates
  
  # Return as s2dv_cube
  cube <- list(
    data = result_array,
    Dates = dates_list,
    lat = sapply(locations, function(x) x["lat"]),
    lon = sapply(locations, function(x) x["lon"]),
    var = list(list(name = var_name, units = "K")),
    source = "era5land"
  )
  class(cube) <- "s2dv_cube"
  
  return(cube)
}

# Load tasmax and tasmin as separate s2dv_cube objects
obs_tasmax <- load_variable_to_cube("tasmax")
obs_tasmin <- load_variable_to_cube("tasmin")

obs_tasmax$data <- obs_tasmax$data - 273.15
obs_tasmin$data <- obs_tasmin$data - 273.15


# Set base temperature
base_temp <- 10

gdd <- obs_tasmax

# Compute daily excess above 10°C using Prentice et al. (1992) method
gdd$data <- ((obs_tasmin$data + obs_tasmax$data) / 2) - base_temp

# Set values below 0 to 0 (i.e., no accumulation if below base)
gdd$data[gdd$data < 0] <- 0

# Step 1: Extract GDD data and dates
gdd_data <- gdd$data

n_days <- dim(gdd_data)[2]
n_weeks <- floor(n_days / 7)

# Step 2: Trim data to include only full weeks
trimmed_data <- gdd_data[, 1:(n_weeks * 7), 1]

# Step 3: Reshape to [locations, 7 days, weeks]
reshaped <- array(trimmed_data, dim = c(dim(gdd_data)[1], 7, n_weeks))

# Step 4: Sum over 7-day windows to get weekly totals
weekly_totals <- apply(reshaped, c(1, 3), sum, na.rm = TRUE)

# Step 5: Apply cumulative sum across weeks for each location
weekly_cumsum <- t(apply(weekly_totals, 1, cumsum))

# Step 6: Convert to 3D array [locations, weeks, 1]
weekly_cumsum_array <- array(weekly_cumsum, dim = c(dim(weekly_cumsum), 1))

# Step 7: Construct weekly dates (starting date of each week)
gdd_dates <- as.Date(names(gdd$Dates$start), format = "%Y%m%d")
weekly_dates <- gdd_dates[seq(1, n_weeks * 7, by = 7)]
names(weekly_dates) <- format(weekly_dates, "%Y%m%d")

# Step 8: Create s2dv_cube for weekly cumulative GDD
gdd_weekly_cumsum <- list(
  data = weekly_cumsum_array,
  Dates = list(start = weekly_dates),
  lat = gdd$lat,
  lon = gdd$lon,
  var = list(list(name = "GDD_cumulative", units = "°C·day")),
  source = gdd$source
)
class(gdd_weekly_cumsum) <- "s2dv_cube"


gdd_data <- gdd_weekly_cumsum$data[1, , 1]  # First location, first time dimension
dates <- as.Date(names(gdd_weekly_cumsum$Dates$start), format = "%Y%m%d")
location <- names(gdd_weekly_cumsum$lat)[1]

# Create a data frame for the weekly cumulative GDD
df_weekly_gdd <- data.frame(
  Date = dates,
  GDD = gdd_data,
  Location = location
)

# If you're using CSTools format for plotting, you can recreate the time series for cumulative GDD
gdd_cst <- gdd_weekly_cumsum  # Use your s2dv_cube
gdd_cst$data <- gdd_weekly_cumsum$data

# Flatten time series (weekly)
gdd_series <- as.numeric(gdd_cst$data)

# Rebuild date axis from the original list of dates for the weekly data
weekly_dates <- as.Date(format(seq(as.Date("20240301", "%Y%m%d"), 
                                   as.Date("20241031", "%Y%m%d"), 7), "%Y%m%d"), "%Y%m%d")

# Create a dataframe for plotting
df_gdd <- data.frame(
  Date = weekly_dates,
  GDD = gdd_series[1:length(weekly_dates)]
)

# Define the output path for the plot
output_path <- "gdd_timeseries.png"  # or a custom path

# Open PNG device to save the plot
png(filename = output_path, width = 1200, height = 600, res = 150)

# Create the plot with weekly cumulative GDD
p <- ggplot(df_gdd, aes(x = Date, y = GDD)) +
  geom_line(color = "#1b9e77", size = 1) +
  geom_point(color = "#1b9e77", size = 1) +
  
  # Set up the x-axis scale for month names, only once per month
  scale_x_date(date_breaks = "1 month", date_labels = "%b") +  # Month name on the main axis
  
  # Adding the day labels manually using geom_text() (for each date point)
  geom_text(aes(x = Date, y = rep(min(df_gdd$GDD) - 2, length(Date)), 
                label = format(Date, "%d")), 
            size = 3, angle = 0, vjust = 1.5) +  # Above the x-axis
  
  labs(title = "Accumulated Growing Degree Days (GDD)",
       subtitle = "Threshold base: 10°C | Location: Viñedos del Río Tajo",
       x = "Week Start",
       y = "Accumulated GDD (°C)") +
  theme_minimal(base_size = 14) +
  
  # Theme adjustments for label positioning
  theme(axis.text.x = element_text(angle = 0, hjust = 0.5, size = 12),
        plot.title = element_text(face = "bold"),
        plot.subtitle = element_text(color = "gray40"),
        axis.title.x = element_blank(),  # Removing default x-axis label
        axis.title.y = element_text(size = 14))

# Render the plot to PNG
print(p)

# Close the PNG device after saving
dev.off()
