using OrderPROPrint.Forms;
using OrderPROPrint.Models;
using OrderPROPrint.Services;

namespace OrderPROPrint;

public class TrayApplicationContext : ApplicationContext
{
    private readonly NotifyIcon _trayIcon;
    private readonly ToolStripMenuItem _pauseMenuItem;
    private readonly SynchronizationContext _syncContext;
    private PollingService? _pollingService;
    private AppSettings _settings;
    private bool _isPaused;
    private bool _isDisposed;

    public TrayApplicationContext()
    {
        _syncContext = SynchronizationContext.Current ?? new SynchronizationContext();
        _settings = AppSettings.Load();

        _pauseMenuItem = new ToolStripMenuItem("Wstrzymaj", null, OnPauseToggle);

        var contextMenu = new ContextMenuStrip();
        contextMenu.Items.Add("Ustawienia", null, OnSettings);
        contextMenu.Items.Add("Logi", null, OnLogs);
        contextMenu.Items.Add(_pauseMenuItem);
        contextMenu.Items.Add(new ToolStripSeparator());
        contextMenu.Items.Add("O programie", null, OnAbout);
        contextMenu.Items.Add("Zamknij", null, OnExit);

        _trayIcon = new NotifyIcon
        {
            Icon = SystemIcons.Application,
            Text = "OrderPRO Print — Oczekiwanie",
            ContextMenuStrip = contextMenu,
            Visible = true
        };
        _trayIcon.DoubleClick += OnSettings;

        if (_settings.IsConfigured)
        {
            StartPolling();
        }
        else
        {
            _trayIcon.ShowBalloonTip(3000, "OrderPRO Print", "Skonfiguruj połączenie w Ustawieniach.", ToolTipIcon.Info);
        }
    }

    private void StartPolling()
    {
        _pollingService?.Stop();

        var apiClient = new PrintApiClient(_settings.ApiUrl, _settings.ApiKey);
        var printService = new PrintService();

        _pollingService = new PollingService(
            apiClient,
            printService,
            _settings.PrinterName,
            _settings.PollIntervalSeconds,
            OnStatusUpdate,
            OnError
        );
        _pollingService.Start();
        _isPaused = false;
        _pauseMenuItem.Text = "Wstrzymaj";
        SetNormalState();
    }

    private void OnStatusUpdate(string message)
    {
        LogForm.Log(message);
        if (_isDisposed) return;
        _syncContext.Post(_ =>
        {
            if (_isDisposed) return;
            _trayIcon.Text = TruncateTooltip($"OrderPRO Print — {message}");
            _trayIcon.Icon = SystemIcons.Application;
        }, null);
    }

    private void OnError(string message)
    {
        LogForm.Log($"BŁĄD: {message}");
        if (_isDisposed) return;
        _syncContext.Post(_ =>
        {
            if (_isDisposed) return;
            _trayIcon.Text = TruncateTooltip($"OrderPRO Print — Błąd: {message}");
            _trayIcon.Icon = SystemIcons.Error;
        }, null);
    }

    private void OnLogs(object? sender, EventArgs e)
    {
        LogForm.ShowInstance();
    }

    private void SetNormalState()
    {
        _trayIcon.Icon = SystemIcons.Application;
        _trayIcon.Text = "OrderPRO Print — Aktywne";
    }

    private void OnSettings(object? sender, EventArgs e)
    {
        using var form = new SettingsForm(_settings);
        if (form.ShowDialog() == DialogResult.OK)
        {
            _settings = AppSettings.Load();
            if (_settings.IsConfigured)
            {
                StartPolling();
            }
        }
    }

    private void OnPauseToggle(object? sender, EventArgs e)
    {
        if (_pollingService == null) return;

        if (_isPaused)
        {
            _pollingService.Start();
            _isPaused = false;
            _pauseMenuItem.Text = "Wstrzymaj";
            SetNormalState();
        }
        else
        {
            _pollingService.Stop();
            _isPaused = true;
            _pauseMenuItem.Text = "Wznów";
            _trayIcon.Text = "OrderPRO Print — Wstrzymane";
        }
    }

    private void OnAbout(object? sender, EventArgs e)
    {
        MessageBox.Show(
            "OrderPRO Print v1.0\n\nKlient zdalnego drukowania etykiet.\nPobiera zlecenia z orderPRO i drukuje na drukarce termicznej.",
            "O programie",
            MessageBoxButtons.OK,
            MessageBoxIcon.Information
        );
    }

    private void OnExit(object? sender, EventArgs e)
    {
        _pollingService?.Stop();
        _trayIcon.Visible = false;
        _trayIcon.Dispose();
        Application.Exit();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _isDisposed = true;
            _pollingService?.Stop();
            _trayIcon.Visible = false;
            _trayIcon.Dispose();
        }
        base.Dispose(disposing);
    }

    private static string TruncateTooltip(string text)
    {
        return text.Length > 63 ? text[..63] : text;
    }
}
