using System.Text;
using Microsoft.Extensions.Logging;

namespace Inspectron.Epson;

/// <summary>
/// Comprehensive diagnostics for Epson TM-m30III printer
/// </summary>
public class EpsonDiagnostics
{
    private readonly ILogger _logger;

    /// <summary>
    /// Initialize a new instance of EpsonDiagnostics
    /// </summary>
    /// <param name="logger">Optional logger for diagnostic output</param>
    public EpsonDiagnostics(ILogger logger = null)
    {
        _logger = logger;
    }

    /// <summary>
    /// Run full diagnostic check and return formatted report
    /// </summary>
    /// <param name="ip">Printer IP address</param>
    /// <param name="port">Printer port (default 9100)</param>
    /// <param name="timeoutSeconds">Connection timeout in seconds (default 5)</param>
    /// <returns>Formatted diagnostic report as string</returns>
    public async Task<string> RunFullDiagnosticsAsync(string ip, int port = 9100, int timeoutSeconds = 5)
    {
        var report = new StringBuilder();
        var separator = new string('=', 70);

        report.AppendLine();
        report.AppendLine(separator);
        report.AppendLine("  EPSON TM-m30III PRINTER DIAGNOSTICS");
        report.AppendLine(separator);
        report.AppendLine($"  Printer IP:    {ip}:{port}");
        report.AppendLine($"  Timestamp:     {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
        report.AppendLine(separator);

        _logger?.LogInformation("Starting diagnostics for printer at {Ip}:{Port}", ip, port);

        await using var printer = new EpsonPrinter(_logger);

        // Connect to printer
        report.AppendLine();
        report.AppendLine("⏳ Connecting to printer...");

        try
        {
            await printer.ConnectAsync(ip, port, timeoutSeconds);
            report.AppendLine("✅ Connection established");
        }
        catch (Exception ex)
        {
            report.AppendLine();
            report.AppendLine("❌ DIAGNOSTIC FAILED: Cannot connect to printer");
            report.AppendLine($"   {ex.Message}");
            report.AppendLine($"   Make sure the printer is powered on and accessible at {ip}");
            report.AppendLine();
            report.AppendLine(separator);
            report.AppendLine("  DIAGNOSTIC COMPLETE");
            report.AppendLine(separator);

            _logger?.LogError(ex, "Diagnostics failed - cannot connect to printer");
            return report.ToString();
        }

        // Gather status information
        report.AppendLine();
        report.AppendLine("⏳ Retrieving printer information...");
        report.AppendLine("⏳ Querying printer status...");

        try
        {
            var overallStatus = await printer.GetOverallStatusAsync();

            // Overall Status Section
            PrintSectionHeader(report, "OVERALL STATUS");
            report.AppendLine();
            report.AppendLine($"  {overallStatus.StatusIcon} {overallStatus.StatusText}");
            report.AppendLine();

            if (!string.IsNullOrEmpty(overallStatus.PrinterModel))
            {
                PrintStatusLine(report, "Printer Model", overallStatus.PrinterModel, "🖨️");
            }

            // General Printer Status Section
            if (overallStatus.PrinterStatus != null)
            {
                var ps = overallStatus.PrinterStatus;
                PrintSectionHeader(report, "GENERAL PRINTER STATUS");
                PrintStatusLine(report, "Raw Status Byte", ps.Hex, "📊");
                PrintStatusLine(report, "Binary", ps.Binary, "📊");
                report.AppendLine();
                PrintStatusLine(report, "Printer Online", ps.IsOnline);
                PrintStatusLine(report, "Cover Closed", ps.IsCoverClosed);
                PrintStatusLine(report, "Paper Feed Button Pressed", ps.PaperFeedButtonPressed);
                PrintStatusLine(report, "Drawer Open Signal", ps.DrawerOpen);
            }

            // Offline Status Section
            if (overallStatus.OfflineStatus != null)
            {
                var os = overallStatus.OfflineStatus;
                PrintSectionHeader(report, "OFFLINE STATUS (Reasons for Offline)");
                PrintStatusLine(report, "Raw Status Byte", os.Hex, "📊");
                PrintStatusLine(report, "Binary", os.Binary, "📊");
                report.AppendLine();
                PrintStatusLine(report, "Cover Open", os.CoverOpen);
                PrintStatusLine(report, "Paper Feed Button Active", os.PaperFeedButton);
                PrintStatusLine(report, "Paper End Detected", os.PaperEnd);
                PrintStatusLine(report, "Error Occurred", os.ErrorOccurred);
            }

            // Error Status Section
            if (overallStatus.ErrorStatus != null)
            {
                var es = overallStatus.ErrorStatus;
                PrintSectionHeader(report, "ERROR STATUS");
                PrintStatusLine(report, "Raw Status Byte", es.Hex, "📊");
                PrintStatusLine(report, "Binary", es.Binary, "📊");
                report.AppendLine();
                PrintStatusLine(report, "Recoverable Error", es.RecoverableError);
                PrintStatusLine(report, "Auto-Cutter Error", es.AutoCutterError);
                PrintStatusLine(report, "Unrecoverable Error", es.UnrecoverableError);
                PrintStatusLine(report, "Auto-Recovery Error", es.AutoRecoveryError);

                // Error guidance
                if (es.UnrecoverableError)
                {
                    report.AppendLine();
                    report.AppendLine("  ⚠️  UNRECOVERABLE ERROR DETECTED:");
                    report.AppendLine("      - Power cycle the printer");
                    report.AppendLine("      - Check for hardware failures");
                    report.AppendLine("      - Contact technical support if issue persists");
                }
                else if (es.RecoverableError)
                {
                    report.AppendLine();
                    report.AppendLine("  ⚠️  RECOVERABLE ERROR DETECTED:");
                    report.AppendLine("      - Check for paper jams");
                    report.AppendLine("      - Ensure paper is loaded correctly");
                    report.AppendLine("      - Close the printer cover");
                }

                if (es.AutoCutterError)
                {
                    report.AppendLine();
                    report.AppendLine("  ⚠️  AUTO-CUTTER ERROR DETECTED:");
                    report.AppendLine("      - Check for paper jams in cutter");
                    report.AppendLine("      - Remove any obstructions");
                    report.AppendLine("      - May require service");
                }
            }

            // Paper Sensor Status Section
            if (overallStatus.PaperStatus != null)
            {
                var pps = overallStatus.PaperStatus;
                PrintSectionHeader(report, "PAPER SENSOR STATUS");
                PrintStatusLine(report, "Raw Status Byte", pps.Hex, "📊");
                PrintStatusLine(report, "Binary", pps.Binary, "📊");
                report.AppendLine();
                PrintStatusLine(report, "Paper Present", pps.PaperPresent);
                PrintStatusLine(report, "Paper Near End", pps.PaperNearEnd);

                if (!pps.PaperPresent)
                {
                    report.AppendLine();
                    report.AppendLine("  ⚠️  NO PAPER DETECTED:");
                    report.AppendLine("      - Load paper roll");
                    report.AppendLine("      - Ensure paper is inserted correctly");
                }
                else if (pps.PaperNearEnd)
                {
                    report.AppendLine();
                    report.AppendLine("  ⚠️  PAPER LOW:");
                    report.AppendLine("      - Replace paper roll soon to avoid interruption");
                }
            }

            // Recommendations Section
            PrintSectionHeader(report, "RECOMMENDATIONS");
            if (overallStatus.Recommendations.Count == 0)
            {
                report.AppendLine();
                report.AppendLine("  ✅ No issues detected - printer is ready for operation");
            }
            else
            {
                report.AppendLine();
                for (int i = 0; i < overallStatus.Recommendations.Count; i++)
                {
                    report.AppendLine($"  {i + 1}. {overallStatus.Recommendations[i]}");
                }
            }
        }
        catch (Exception ex)
        {
            report.AppendLine();
            report.AppendLine($"❌ Error during diagnostics: {ex.Message}");
            _logger?.LogError(ex, "Error during diagnostics");
        }

        // Footer
        report.AppendLine();
        report.AppendLine(separator);
        report.AppendLine("  DIAGNOSTIC COMPLETE");
        report.AppendLine(separator);
        report.AppendLine();

        _logger?.LogInformation("Diagnostics completed");
        return report.ToString();
    }

    private static void PrintSectionHeader(StringBuilder report, string title)
    {
        var separator = new string('=', 70);
        report.AppendLine();
        report.AppendLine(separator);
        report.AppendLine($"  {title}");
        report.AppendLine(separator);
    }

    private static void PrintStatusLine(StringBuilder report, string label, bool value)
    {
        var icon = value ? "✅" : "❌";
        var valueStr = value ? "YES" : "NO";
        report.AppendLine($"  {icon} {label,-35} {valueStr}");
    }

    private static void PrintStatusLine(StringBuilder report, string label, string value, string icon = "ℹ️")
    {
        report.AppendLine($"  {icon} {label,-35} {value}");
    }
}
