use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::SystemTime; use axum::extract::State; use axum::http::HeaderMap; use axum::response::Redirect; use serde::Deserialize; use time::OffsetDateTime; use time::format_description::well_known::Rfc3339; use tokio::io::AsyncWriteExt; use tracing::{info, warn}; use doctate_common::timestamp::{filename_stem_to_recorded_at, now_rfc3339}; use doctate_common::{RECORDING_META_SUFFIX, TranscriptState}; use crate::analyze::backend::{any_backend_available, find_backend}; use crate::analyze::{ ANALYSIS_INPUT_FILE, AnalysisInput, AnalyzeJob, AnalyzeSender, DOCUMENT_FILE, RecordingInput, }; use crate::auth::AuthenticatedWebUser; use crate::case_id::CaseIdPath; use crate::config::Config; use crate::csrf::{CsrfForm, CsrfOnlyForm, HasCsrfToken}; use crate::error::AppError; use crate::events::{self, CaseEventKind, EventSender}; use crate::oneliner_locks::OnelinerLocks; use crate::paths::{ CLOSE_MARKER, CloseMarker, delete_oneliner_unless_manual, read_close_marker, read_transcript_state, write_close_marker, }; use crate::routes::user_web::locate_case_or_404; use crate::routes::web::validate_filename; /// Form body for `POST /web/cases/{id}/analyze`. The `backend` value is set /// by the clicked submit button (`