using System.ComponentModel.DataAnnotations;

namespace Extrudex.API.DTOs.Printers;

/// <summary>
/// Response DTO for a Printer entity. Contains all printer details
/// including connection configuration and operational status.
/// </summary>
public class PrinterResponse
{
    /// <summary>Unique identifier for the printer.</summary>
    public Guid Id { get; set; }

    /// <summary>Current operational status (Idle, Printing, Offline, Error, Paused).</summary>
    public string Status { get; set; } = string.Empty;

    /// <summary>Human-readable name (e.g., "Bambu X1C #1", "Elegoo Centauri").</summary>
    public string Name { get; set; } = string.Empty;

    /// <summary>Manufacturer/brand (e.g., "Bambu Lab", "Elegoo").</summary>
    public string Manufacturer { get; set; } = string.Empty;

    /// <summary>Model name (e.g., "X1 Carbon", "Centauri Carbon").</summary>
    public string Model { get; set; } = string.Empty;

    /// <summary>Printer hardware type ("Fdm" or "Resin").</summary>
    public string PrinterType { get; set; } = string.Empty;

    /// <summary>Connectivity protocol ("Mqtt" or "Moonraker").</summary>
    public string ConnectionType { get; set; } = string.Empty;

    /// <summary>Hostname or IP address for printer connection.</summary>
    public string HostnameOrIp { get; set; } = string.Empty;

    /// <summary>Port number for the connection (8883 for MQTT/TLS, 7125 for Moonraker).</summary>
    public int Port { get; set; }

    /// <summary>Whether the printer is currently active and available for jobs.</summary>
    public bool IsActive { get; set; }

    /// <summary>Timestamp of the last status update received from the printer (UTC).</summary>
    public DateTime? LastSeenAt { get; set; }

    /// <summary>Timestamp when this record was created (UTC).</summary>
    public DateTime CreatedAt { get; set; }

    /// <summary>Timestamp when this record was last modified (UTC).</summary>
    public DateTime UpdatedAt { get; set; }
}

/// <summary>
/// Lightweight response DTO for printer status. Optimized for polling
/// and dashboard displays. For real-time updates, use the SignalR PrinterHub.
/// </summary>
public class PrinterStatusResponse
{
    /// <summary>Unique identifier for the printer.</summary>
    public Guid Id { get; set; }

    /// <summary>Human-readable name of the printer.</summary>
    public string Name { get; set; } = string.Empty;

    /// <summary>Current operational status (Idle, Printing, Offline, Error, Paused).</summary>
    public string Status { get; set; } = string.Empty;

    /// <summary>Timestamp of the last status update received from the printer (UTC).</summary>
    public DateTime? LastSeenAt { get; set; }

    /// <summary>Whether the printer is currently active and available for jobs.</summary>
    public bool IsActive { get; set; }
}

/// <summary>
/// Request DTO for registering a new printer in the fleet.
/// All string enums accept: PrinterType = "Fdm"|"Resin",
/// ConnectionType = "Mqtt"|"Moonraker" (case-insensitive).
/// </summary>
public class CreatePrinterRequest
{
    /// <summary>Human-readable name for the printer. Required, max 100 characters.</summary>
    [Required(ErrorMessage = "Name is required.")]
    [StringLength(100, MinimumLength = 1, ErrorMessage = "Name must be between 1 and 100 characters.")]
    public string Name { get; set; } = string.Empty;

    /// <summary>Manufacturer/brand (e.g., "Bambu Lab", "Elegoo"). Required, max 50 characters.</summary>
    [Required(ErrorMessage = "Manufacturer is required.")]
    [StringLength(50, MinimumLength = 1, ErrorMessage = "Manufacturer must be between 1 and 50 characters.")]
    public string Manufacturer { get; set; } = string.Empty;

    /// <summary>Model name (e.g., "X1 Carbon", "Centauri Carbon"). Required, max 50 characters.</summary>
    [Required(ErrorMessage = "Model is required.")]
    [StringLength(50, MinimumLength = 1, ErrorMessage = "Model must be between 1 and 50 characters.")]
    public string Model { get; set; } = string.Empty;

    /// <summary>Printer hardware type: "Fdm" or "Resin". Defaults to "Fdm".</summary>
    [Required(ErrorMessage = "PrinterType is required.")]
    [RegularExpression("^(Fdm|Resin)$", ErrorMessage = "PrinterType must be 'Fdm' or 'Resin'.")]
    public string PrinterType { get; set; } = "Fdm";

    /// <summary>Connectivity protocol: "Mqtt" or "Moonraker". Defaults to "Mqtt".</summary>
    [Required(ErrorMessage = "ConnectionType is required.")]
    [RegularExpression("^(Mqtt|Moonraker)$", ErrorMessage = "ConnectionType must be 'Mqtt' or 'Moonraker'.")]
    public string ConnectionType { get; set; } = "Mqtt";

    /// <summary>Hostname or IP address for printer connection. Required, max 253 characters.</summary>
    [Required(ErrorMessage = "HostnameOrIp is required.")]
    [StringLength(253, MinimumLength = 1, ErrorMessage = "HostnameOrIp must be between 1 and 253 characters.")]
    public string HostnameOrIp { get; set; } = string.Empty;

    /// <summary>Port number. Defaults: 8883 (MQTT/TLS), 7125 (Moonraker) if zero.</summary>
    [Range(0, 65535, ErrorMessage = "Port must be between 0 and 65535.")]
    public int Port { get; set; }

    /// <summary>MQTT username for Bambu Lab authentication. Used only for MQTT connection type.</summary>
    [StringLength(100, ErrorMessage = "MqttUsername must be at most 100 characters.")]
    public string MqttUsername { get; set; } = string.Empty;

    /// <summary>MQTT password for Bambu Lab authentication. Used only for MQTT connection type.</summary>
    [StringLength(200, ErrorMessage = "MqttPassword must be at most 200 characters.")]
    public string MqttPassword { get; set; } = string.Empty;

    /// <summary>Whether to use TLS for MQTT. Bambu Lab printers require TLS on port 8883.</summary>
    public bool MqttUseTls { get; set; }

    /// <summary>Moonraker API key for Elegoo Centauri Carbon. Used only for Moonraker connection type.</summary>
    [StringLength(100, ErrorMessage = "ApiKey must be at most 100 characters.")]
    public string ApiKey { get; set; } = string.Empty;

    /// <summary>Whether the printer is active and available for jobs. Defaults to true.</summary>
    public bool IsActive { get; set; } = true;
}

/// <summary>
/// Request DTO for updating an existing printer's configuration and connection info.
/// All fields are provided on update (full replacement semantics).
/// </summary>
public class UpdatePrinterRequest
{
    /// <summary>Human-readable name for the printer. Required, max 100 characters.</summary>
    [Required(ErrorMessage = "Name is required.")]
    [StringLength(100, MinimumLength = 1, ErrorMessage = "Name must be between 1 and 100 characters.")]
    public string Name { get; set; } = string.Empty;

    /// <summary>Manufacturer/brand. Required, max 50 characters.</summary>
    [Required(ErrorMessage = "Manufacturer is required.")]
    [StringLength(50, MinimumLength = 1, ErrorMessage = "Manufacturer must be between 1 and 50 characters.")]
    public string Manufacturer { get; set; } = string.Empty;

    /// <summary>Model name. Required, max 50 characters.</summary>
    [Required(ErrorMessage = "Model is required.")]
    [StringLength(50, MinimumLength = 1, ErrorMessage = "Model must be between 1 and 50 characters.")]
    public string Model { get; set; } = string.Empty;

    /// <summary>Printer hardware type: "Fdm" or "Resin".</summary>
    [Required(ErrorMessage = "PrinterType is required.")]
    [RegularExpression("^(Fdm|Resin)$", ErrorMessage = "PrinterType must be 'Fdm' or 'Resin'.")]
    public string PrinterType { get; set; } = "Fdm";

    /// <summary>Connectivity protocol: "Mqtt" or "Moonraker".</summary>
    [Required(ErrorMessage = "ConnectionType is required.")]
    [RegularExpression("^(Mqtt|Moonraker)$", ErrorMessage = "ConnectionType must be 'Mqtt' or 'Moonraker'.")]
    public string ConnectionType { get; set; } = "Mqtt";

    /// <summary>Hostname or IP address. Required, max 253 characters.</summary>
    [Required(ErrorMessage = "HostnameOrIp is required.")]
    [StringLength(253, MinimumLength = 1, ErrorMessage = "HostnameOrIp must be between 1 and 253 characters.")]
    public string HostnameOrIp { get; set; } = string.Empty;

    /// <summary>Port number. Defaults: 8883 (MQTT/TLS), 7125 (Moonraker) if zero.</summary>
    [Range(0, 65535, ErrorMessage = "Port must be between 0 and 65535.")]
    public int Port { get; set; }

    /// <summary>MQTT username. Used only for MQTT connection type.</summary>
    [StringLength(100, ErrorMessage = "MqttUsername must be at most 100 characters.")]
    public string MqttUsername { get; set; } = string.Empty;

    /// <summary>MQTT password. Used only for MQTT connection type.</summary>
    [StringLength(200, ErrorMessage = "MqttPassword must be at most 200 characters.")]
    public string MqttPassword { get; set; } = string.Empty;

    /// <summary>Whether to use TLS for MQTT.</summary>
    public bool MqttUseTls { get; set; }

    /// <summary>Moonraker API key. Used only for Moonraker connection type.</summary>
    [StringLength(100, ErrorMessage = "ApiKey must be at most 100 characters.")]
    public string ApiKey { get; set; } = string.Empty;

    /// <summary>Whether the printer is active and available for jobs.</summary>
    public bool IsActive { get; set; } = true;
}