using Extrudex.Domain.DTOs.Moonraker;

namespace Extrudex.Domain.Interfaces;

/// <summary>
/// Client interface for communicating with Moonraker REST API endpoints
/// on Klipper-based printers (e.g., Elegoo Centauri Carbon).
/// Provides strongly-typed methods for server discovery, printer status,
/// print job history, and real-time telemetry.
/// </summary>
public interface IMoonrakerClient
{
    /// <summary>
    /// Checks whether the Moonraker server is reachable and responding.
    /// Calls the /server/info endpoint and returns the server information
    /// if successful, or null if the server is unreachable.
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns>Server info if reachable; <c>null</c> if unreachable.</returns>
    Task<MoonrakerServerInfo?> GetServerInfoAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Checks whether the Moonraker server is reachable and responding.
    /// This is a convenience method equivalent to calling GetServerInfoAsync
    /// and checking for a non-null result.
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns><c>true</c> if the server responded successfully; otherwise <c>false</c>.</returns>
    Task<bool> IsReachableAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches the current printer info from the /printer/info endpoint.
    /// Returns the Klipper state and readiness status.
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns>Printer info if successful; <c>null</c> if the request failed.</returns>
    Task<MoonrakerPrinterInfo?> GetPrinterInfoAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches print job history from the /server/history/items endpoint.
    /// Returns the most recent print jobs with filament usage data,
    /// print duration, and completion status.
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="limit">Maximum number of history items to return. Default: 50.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns>History response with print jobs; empty list if request failed.</returns>
    Task<MoonrakerHistoryResponse> GetPrintHistoryAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        int limit = 50,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches the current print statistics from the /printer/objects/query endpoint.
    /// Returns real-time data including filament used, print duration,
    /// and current print state for the active or most recent print.
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns>Print stats if successful; <c>null</c> if the request failed.</returns>
    Task<MoonrakerPrintStats?> GetPrintStatsAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches the current display status from the /printer/objects/query endpoint.
    /// Returns progress percentage and status message for the active print.
    /// Used by SignalR to push real-time progress updates to connected clients.
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns>Display status if successful; <c>null</c> if the request failed.</returns>
    Task<MoonrakerDisplayStatus?> GetDisplayStatusAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches the current filament usage data from the Moonraker server.
    /// Returns a dictionary of usage metrics reported by the printer.
    /// 
    /// <para>
    /// <b>Prefer GetPrintHistoryAsync or GetPrintStatsAsync for new code.</b>
    /// This method is retained for backward compatibility with the
    /// FilamentUsageSyncService and returns a dictionary of metric names
    /// to their decimal values for callers that don't need typed DTOs.
    /// </para>
    /// </summary>
    /// <param name="hostnameOrIp">The printer's hostname or IP address.</param>
    /// <param name="port">The Moonraker API port (default: 7125).</param>
    /// <param name="apiKey">Optional API key for authentication.</param>
    /// <param name="cancellationToken">Cancellation token for the HTTP request.</param>
    /// <returns>A dictionary of usage metric names to their decimal values.</returns>
    Task<Dictionary<string, decimal>> GetFilamentUsageAsync(
        string hostnameOrIp,
        int port,
        string? apiKey,
        CancellationToken cancellationToken = default);
}