using BomLocalService.Models;
using BomLocalService.Services.Interfaces.Registration;
namespace BomLocalService.Services.Interfaces;
///
/// Service interface for managing cached radar screenshot files and metadata.
/// Handles file system operations for storing and retrieving cached BOM radar screenshots.
///
public interface ICacheService : ISingletonService
{
///
/// Gets the cached screenshot folder path and associated metadata for a location and data type.
/// Searches for cache folders matching the location pattern and loads the corresponding metadata JSON file.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// The type of cached data to retrieve
/// Optional folder path to exclude from search (e.g., folder currently being written to)
/// Cancellation token to cancel the operation
/// Tuple containing the cache folder path and metadata, or (null, null) if not found
Task<(string? cacheFolderPath, LastUpdatedInfo? metadata)> GetCachedScreenshotWithMetadataAsync(
string suburb,
string state,
CachedDataType dataType,
string? excludeFolder = null,
CancellationToken cancellationToken = default);
///
/// Gets all complete cache folders for a location, ordered by timestamp (oldest first).
/// Returns basic folder information without loading all frame data.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// Cancellation token to cancel the operation
/// List of cache folders with available data types
Task> GetAllCacheFoldersAsync(
string suburb,
string state,
CancellationToken cancellationToken = default);
///
/// Gets frames from a specific cache folder and data type.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// The cache folder name
/// The type of cached data to retrieve
/// Cancellation token to cancel the operation
/// List of cached frames, or empty list if not found
Task> GetFramesFromCacheFolderAsync(
string suburb,
string state,
string cacheFolderName,
CachedDataType dataType,
CancellationToken cancellationToken = default);
///
/// Gets all cached frames for a location.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// Cancellation token to cancel the operation
/// List of cached frames, or empty list if not found
Task> GetCachedFramesAsync(
string suburb,
string state,
CancellationToken cancellationToken = default);
///
/// Gets a specific cached frame for a location.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// Frame index (0-6)
/// Cancellation token to cancel the operation
/// The cached frame, or null if not found
Task GetCachedFrameAsync(
string suburb,
string state,
int frameIndex,
CancellationToken cancellationToken = default);
///
/// Saves metadata JSON file in a cache folder.
/// Creates a metadata.json file in the specified cache folder.
///
/// Full path to the cache folder
/// Metadata to save (observation time, forecast time, weather station, distance)
/// Cancellation token to cancel the operation
Task SaveMetadataAsync(string cacheFolderPath, LastUpdatedInfo metadata, CancellationToken cancellationToken = default);
///
/// Saves frame metadata (frame index and observation time) to a frames.json file in the data type subfolder.
///
/// Full path to the cache folder
/// The type of cached data
/// List of frames with their metadata
/// Cancellation token to cancel the operation
Task SaveFramesMetadataAsync(string cacheFolderPath, CachedDataType dataType, List frames, CancellationToken cancellationToken = default);
///
/// Checks if cached metadata is still valid (not expired).
/// Cache is valid if observation time + expiration buffer (typically 15.5 minutes) is still in the future.
/// BOM updates observations every 15 minutes, so the buffer accounts for timing variations.
///
/// The metadata to validate, or null
/// True if metadata exists and cache is still valid, false otherwise
bool IsCacheValid(LastUpdatedInfo? metadata);
///
/// Gets the file system path to the most recent cached screenshot for a location.
/// Returns files ordered by creation time, most recent first.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// Cancellation token to cancel the operation
/// File system path to the cached screenshot, or empty string if not found
Task GetCachedScreenshotPathAsync(string suburb, string state, CancellationToken cancellationToken = default);
///
/// Deletes all cached folders (containing frames and metadata) for a location.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// Cancellation token to cancel the operation
/// True if any folders were deleted, false if no cached folders existed
Task DeleteCachedLocationAsync(string suburb, string state, CancellationToken cancellationToken = default);
///
/// Gets the cache directory path where screenshots and metadata are stored.
///
/// The full path to the cache directory
string GetCacheDirectory();
///
/// Cleans up incomplete cache folders (e.g., from a previous crash or restart).
/// Scans all cache folders and deletes any that are incomplete (missing frames, metadata, etc.).
/// This should be called on application startup to recover from interrupted cache updates.
///
/// The number of incomplete folders that were deleted
int CleanupIncompleteCacheFolders();
///
/// Checks if a location is currently being updated (has an active cache folder being written to).
///
bool IsLocationUpdating(string locationKey);
///
/// Gets the active cache folder path for a location (if one is being written to).
///
string? GetActiveCacheFolder(string locationKey);
///
/// Sets the active cache folder for a location (indicates a cache update is in progress).
///
void SetActiveCacheFolder(string locationKey, string cacheFolderPath);
///
/// Clears the active cache folder for a location (indicates cache update is complete).
///
void ClearActiveCacheFolder(string locationKey);
///
/// Creates a new cache folder for a location and timestamp.
/// Creates the folder structure and ensures data type subfolders are ready.
///
string CreateCacheFolder(string suburb, string state, string timestamp);
///
/// Deletes an incomplete cache folder (cleanup on error).
/// Only deletes if the folder is incomplete (missing required files).
///
bool TryDeleteIncompleteCacheFolder(string cacheFolderPath);
///
/// Deletes an empty cache folder.
///
bool TryDeleteEmptyCacheFolder(string cacheFolderPath);
///
/// Gets cache status information for a location and data type without triggering an update.
/// Returns information about whether cache exists, is valid, is updating, etc.
///
/// The suburb name (e.g., "Pomona", "Brisbane")
/// The Australian state abbreviation (e.g., "QLD", "NSW", "VIC")
/// The type of cached data to check
/// The number of minutes after observation time that cache expires (will be cast to int)
/// The interval in minutes that the background cache management service checks for updates
/// Cancellation token to cancel the operation
/// Cache status information
Task GetCacheStatusAsync(
string suburb,
string state,
CachedDataType dataType,
int cacheExpirationMinutes,
int cacheManagementCheckIntervalMinutes,
CancellationToken cancellationToken = default);
///
/// Records progress update for a cache update operation using cacheFolderPath.
/// This is useful when locationKey is not directly available (e.g., in ScrapingService).
///
/// The cache folder path being updated
/// The current phase of the update
/// The current frame being captured (if in CapturingFrames phase)
/// The total number of frames to capture
void RecordUpdateProgressByFolder(string cacheFolderPath, CacheUpdatePhase phase, int? currentFrame = null, int? totalFrames = null);
///
/// Gets the estimated remaining seconds for an in-progress cache update.
/// Returns 0 if not updating or no metrics available.
///
/// The location key (suburb_state)
/// Estimated remaining seconds, or 0 if not updating or no metrics
int GetEstimatedRemainingSeconds(string locationKey);
///
/// Records step completion timing for metrics tracking.
///
/// The name of the step
/// The duration of the step in seconds
void RecordStepCompletion(string stepName, double durationSeconds);
///
/// Gets the average duration for a specific step from historical data.
///
/// The name of the step
/// Average duration in seconds, or 0 if no data available
double GetAverageStepDuration(string stepName);
///
/// Gets step performance metrics for debugging/logging.
///
/// Dictionary mapping step names to their average durations
Dictionary GetStepMetrics();
///
/// Gets the average total duration of cache updates from recent metrics.
/// Uses median for robustness against outliers.
///
/// Average total duration in seconds, or 0 if no data available
double GetAverageTotalDuration();
}