```{r backend, include=FALSE}
# Load all functions from main.Rmd
knitr::purl("./main.Rmd", output = tempfile(), quiet = TRUE) |> source()
```

# Web Interface
```{r shiny}
# Flight Trajectory Analysis - Shiny GUI Application
# This app allows interactive selection of flights and displays trajectory analysis
# All core functions are loaded from main.Rmd

# UI Definition
ui <- fluidPage(
  titlePanel("Flight Trajectory Analysis - GUI"),
  
  sidebarLayout(
    sidebarPanel(
      width = 3,
      
      h4("OpenSky Credentials"),
      textInput("client_id", "Client ID:", value = Sys.getenv('OPENSKY_CLIENT_ID')),
      passwordInput("client_secret", "Client Secret:", value = Sys.getenv('OPENSKY_CLIENT_SECRET')),
      
      hr(),
      
      h4("Airport Selection"),
      textInput("airport_code", "Airport ICAO Code:", value = "EDDF"),
      sliderInput("hours_back", "Hours back from now:", min = 1, max = 12, value = 1),
      
      actionButton("load_departures", "Load Departures", class = "btn-primary"),
      
      hr(),
      
      h4("Flight Selection"),
      selectInput("selected_flight", "Select Flight:", choices = NULL),
      
      actionButton("analyze_flight", "Analyze Selected Flight", class = "btn-success"),
      
      hr(),
      
      h4("Batch Analysis"),
      numericInput("batch_size", "Days of flights to analyze:", value = 5, min = 1, max = 30),
      actionButton("batch_analyze", "Run Batch Analysis", class = "btn-warning"),
      
      hr(),
      
      verbatimTextOutput("status_text")
    ),
    
    mainPanel(
      width = 9,
      
      tabsetPanel(
        id = "main_tabs",
        
        tabPanel("Departures List",
                 h4("Available Departures"),
                 tableOutput("departures_table")
        ),
        
        tabPanel("Single Flight Analysis",
                 fluidRow(
                   column(6, leafletOutput("route_plot", height = "400px")),
                   column(6, plotOutput("altitude_plot", height = "400px"))
                 ),
                 fluidRow(
                   column(6, plotOutput("trajectory_plot", height = "400px")),
                   column(6, 
                          h4("Trajectory Characteristics"),
                          tableOutput("characteristics_table"))
                 )
        ),
        
        tabPanel("Statistical Analysis",
                 h4("Multiple Trajectory Statistics"),
                 tableOutput("stats_summary_table"),
                 hr(),
                 fluidRow(
                   column(12, plotOutput("boxplots", height = "500px"))
                 ),
                 fluidRow(
                   column(12, plotOutput("density_plots", height = "500px"))
                 ),
                 fluidRow(
                   column(12, plotOutput("histograms", height = "500px"))
                 )
        ),
        
        tabPanel("Interpretation",
                 h4("Analysis Interpretation"),
                 verbatimTextOutput("interpretation_text")
        )
      )
    )
  )
)

# Server Logic
server <- function(input, output, session) {
  
  # Reactive values to store data
  rv <- reactiveValues(
    creds = NULL,
    departures = NULL,
    departures_df = NULL,
    current_route = NULL,
    current_trj = NULL,
    current_icao = NULL,
    trajectory_stats_df = NULL
  )
  
  # Status message
  status <- reactiveVal("Ready. Enter credentials and load departures.")
  
  output$status_text <- renderText({
    status()
  })
  
  # Load departures
  observeEvent(input$load_departures, {
    req(input$client_id, input$client_secret, input$airport_code)
    
    status("Loading departures...")
    
    tryCatch({
      # Use getCredentials from main.Rmd
      rv$creds <- getCredentials(
        client_id = input$client_id,
        client_secret = input$client_secret
      )
      
      time_now <- Sys.time()
      rv$departures <- getAirportDepartures(
        airport = input$airport_code,
        startTime = time_now - hours(input$hours_back),
        endTime = time_now,
        credentials = rv$creds
      )
      
      if (length(rv$departures) > 0) {
        # Create departures dataframe for display
        departures_list <- lapply(seq_along(rv$departures), function(i) {
          dep <- rv$departures[[i]]
          data.frame(
            Index = i,
            ICAO24 = dep[["ICAO24"]] %||% NA,
            #FIXME Callsign, Origin, Destination
            Callsign = dep[["callsign"]] %||% NA,
            Origin = dep[["estDepartureAirport"]] %||% NA,
            Destination = dep[["estArrivalAirport"]] %||% NA,
            DepartureTime = as.POSIXct(dep[["departure_time"]] %||% NA, origin = "1970-01-01"),
            stringsAsFactors = FALSE
          )
        })
        rv$departures_df <- do.call(rbind, departures_list)
        
        # Update flight selection dropdown
        choices <- setNames(
          seq_along(rv$departures),
          paste(rv$departures_df$ICAO24, "-", rv$departures_df$Callsign, 
                "(", rv$departures_df$Destination, ")")
        )
        updateSelectInput(session, "selected_flight", choices = choices)
        
        status(paste("Loaded", length(rv$departures), "departures from", input$airport_code))
      } else {
        status("No departures found for the selected time period.")
      }
      
    }, error = function(e) {
      status(paste("Error loading departures:", e$message))
    })
  })
  
  # Display departures table
  output$departures_table <- renderTable({
    req(rv$departures_df)
    rv$departures_df
  })
  
  # Analyze selected flight
  observeEvent(input$analyze_flight, {
    req(rv$departures, input$selected_flight, rv$creds)
    
    status("Analyzing selected flight...")
    
    tryCatch({
      idx <- as.integer(input$selected_flight)
      dep <- rv$departures[[idx]]
      icao24 <- dep[["ICAO24"]]
      dep_time <- dep[["departure_time"]]
      
      rv$current_icao <- icao24
      
      # Use getAircraftTrack from main.Rmd
      route_df <- getAircraftTrack(icao24, dep_time, rv$creds)
      
      if (is.null(route_df) || nrow(route_df) < 2) {
        status(paste("No path data available for", icao24))
        return()
      }
      
      rv$current_route <- route_df
      
      # Use getTrajFromRoute from main.Rmd
      rv$current_trj <- getTrajFromRoute(route_df)
      status(paste("Successfully analyzed", icao24, "with", nrow(route_df), "points"))
      
      # Switch to analysis tab
      updateTabsetPanel(session, "main_tabs", selected = "Single Flight Analysis")
      
    }, error = function(e) {
      status(paste("Error analyzing flight:", e$message))
    })
  })
  
  # Route plot
  output$route_plot <- renderLeaflet({
    req(rv$current_route)
    createInteractiveMap(rv$current_route)
  })
  
  # Altitude plot
  output$altitude_plot <- renderPlot({
    req(rv$current_route)
    plot(rv$current_route$time, rv$current_route$alt, type = "l", col = "red", lwd = 2,
         main = paste("Altitude Profile of", rv$current_icao),
         xlab = "Time (Unix)", ylab = "Altitude (m)")
  })
  
  # Trajectory plot
  output$trajectory_plot <- renderPlot({
    req(rv$current_trj)
    plot(rv$current_trj, main = paste("Trajectory of", rv$current_icao))
  })
  
  # Characteristics table
  output$characteristics_table <- renderTable({
    req(rv$current_trj)
    calculateTrajectoryStats(rv$current_trj, format = "table")
  })
  
  # Batch analysis
  observeEvent(input$batch_analyze, {
    req(rv$departures, rv$creds)
    
    status("Running batch analysis...")
    
    tryCatch({
      
      withProgress(message = 'Analyzing flights', value = 0, {
        all_trajectories <- getAircraftTrajectories(rv$current_icao, time = Sys.time(), creds, days = input$batch_size)
      })
      
      if (length(all_trajectories) > 0) {
        rv$trajectory_stats_df <- do.call(rbind, all_trajectories)
        status(paste("Batch analysis complete:", nrow(rv$trajectory_stats_df), "trajectories analyzed"))
        updateTabsetPanel(session, "main_tabs", selected = "Statistical Analysis")
      } else {
        status("No trajectory data collected in batch analysis")
      }
      
    }, error = function(e) {
      status(paste("Error in batch analysis:", e$message))
    })
  })
  
  # Statistics summary table - use calculateStatsSummary from main.Rmd
  output$stats_summary_table <- renderTable({
    req(rv$trajectory_stats_df)
    calculateStatsSummary(rv$trajectory_stats_df)
  })
  
  # Boxplots - use createBoxplots from main.Rmd
  output$boxplots <- renderPlot({
    req(rv$trajectory_stats_df)
    createBoxplots(rv$trajectory_stats_df)
  })
  
  # Density plots - use createDensityPlots from main.Rmd
  output$density_plots <- renderPlot({
    req(rv$trajectory_stats_df)
    createDensityPlots(rv$trajectory_stats_df)
  })
  
  # Histograms - use createHistograms from main.Rmd
  output$histograms <- renderPlot({
    req(rv$trajectory_stats_df)
    createHistograms(rv$trajectory_stats_df)
  })
  
  # Interpretation text - use generateInterpretation from main.Rmd
  output$interpretation_text <- renderText({
    req(rv$trajectory_stats_df)
    generateInterpretation(rv$trajectory_stats_df)
  })
}

# Run the application
shinyApp(ui = ui, server = server)
```
